| //===- llvm/unittest/IR/OpenMPIRBuilderTest.cpp - OpenMPIRBuilder tests ---===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" |
| #include "llvm/IR/BasicBlock.h" |
| #include "llvm/IR/DIBuilder.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Frontend/OpenMP/OMPConstants.h" |
| #include "llvm/IR/Verifier.h" |
| #include "gtest/gtest.h" |
| |
| using namespace llvm; |
| using namespace omp; |
| using namespace types; |
| |
| namespace { |
| |
| class OpenMPIRBuilderTest : public testing::Test { |
| protected: |
| void SetUp() override { |
| M.reset(new Module("MyModule", Ctx)); |
| FunctionType *FTy = |
| FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, |
| /*isVarArg=*/false); |
| F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); |
| BB = BasicBlock::Create(Ctx, "", F); |
| |
| DIBuilder DIB(*M); |
| auto File = DIB.createFile("test.dbg", "/"); |
| auto CU = |
| DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0); |
| auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); |
| auto SP = DIB.createFunction( |
| CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, |
| DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); |
| F->setSubprogram(SP); |
| auto Scope = DIB.createLexicalBlockFile(SP, File, 0); |
| DIB.finalize(); |
| DL = DebugLoc::get(3, 7, Scope); |
| } |
| |
| void TearDown() override { |
| BB = nullptr; |
| M.reset(); |
| uninitializeTypes(); |
| } |
| |
| LLVMContext Ctx; |
| std::unique_ptr<Module> M; |
| Function *F; |
| BasicBlock *BB; |
| DebugLoc DL; |
| }; |
| |
| TEST_F(OpenMPIRBuilderTest, CreateBarrier) { |
| OpenMPIRBuilder OMPBuilder(*M); |
| OMPBuilder.initialize(); |
| |
| IRBuilder<> Builder(BB); |
| |
| OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for); |
| EXPECT_TRUE(M->global_empty()); |
| EXPECT_EQ(M->size(), 1U); |
| EXPECT_EQ(F->size(), 1U); |
| EXPECT_EQ(BB->size(), 0U); |
| |
| OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); |
| OMPBuilder.CreateBarrier(Loc, OMPD_for); |
| EXPECT_FALSE(M->global_empty()); |
| EXPECT_EQ(M->size(), 3U); |
| EXPECT_EQ(F->size(), 1U); |
| EXPECT_EQ(BB->size(), 2U); |
| |
| CallInst *GTID = dyn_cast<CallInst>(&BB->front()); |
| EXPECT_NE(GTID, nullptr); |
| EXPECT_EQ(GTID->getNumArgOperands(), 1U); |
| EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); |
| EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); |
| EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); |
| |
| CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); |
| EXPECT_NE(Barrier, nullptr); |
| EXPECT_EQ(Barrier->getNumArgOperands(), 2U); |
| EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier"); |
| EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); |
| EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); |
| |
| EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); |
| |
| Builder.CreateUnreachable(); |
| EXPECT_FALSE(verifyModule(*M)); |
| } |
| |
| TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) { |
| OpenMPIRBuilder OMPBuilder(*M); |
| OMPBuilder.initialize(); |
| |
| BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); |
| new UnreachableInst(Ctx, CBB); |
| OMPBuilder.setCancellationBlock(CBB); |
| |
| IRBuilder<> Builder(BB); |
| |
| OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); |
| auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for); |
| Builder.restoreIP(NewIP); |
| EXPECT_FALSE(M->global_empty()); |
| EXPECT_EQ(M->size(), 3U); |
| EXPECT_EQ(F->size(), 3U); |
| EXPECT_EQ(BB->size(), 4U); |
| |
| CallInst *GTID = dyn_cast<CallInst>(&BB->front()); |
| EXPECT_NE(GTID, nullptr); |
| EXPECT_EQ(GTID->getNumArgOperands(), 1U); |
| EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); |
| EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); |
| EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); |
| |
| CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); |
| EXPECT_NE(Barrier, nullptr); |
| EXPECT_EQ(Barrier->getNumArgOperands(), 2U); |
| EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier"); |
| EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); |
| EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); |
| EXPECT_EQ(Barrier->getNumUses(), 1U); |
| Instruction *BarrierBBTI = Barrier->getParent()->getTerminator(); |
| EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U); |
| EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock()); |
| EXPECT_EQ(BarrierBBTI->getSuccessor(1), CBB); |
| |
| EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); |
| |
| Builder.CreateUnreachable(); |
| EXPECT_FALSE(verifyModule(*M)); |
| } |
| |
| TEST_F(OpenMPIRBuilderTest, DbgLoc) { |
| OpenMPIRBuilder OMPBuilder(*M); |
| OMPBuilder.initialize(); |
| F->setName("func"); |
| |
| IRBuilder<> Builder(BB); |
| |
| OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); |
| OMPBuilder.CreateBarrier(Loc, OMPD_for); |
| CallInst *GTID = dyn_cast<CallInst>(&BB->front()); |
| CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); |
| EXPECT_EQ(GTID->getDebugLoc(), DL); |
| EXPECT_EQ(Barrier->getDebugLoc(), DL); |
| EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0))); |
| if (!isa<GlobalVariable>(Barrier->getOperand(0))) |
| return; |
| GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0)); |
| EXPECT_TRUE(Ident->hasInitializer()); |
| if (!Ident->hasInitializer()) |
| return; |
| Constant *Initializer = Ident->getInitializer(); |
| EXPECT_TRUE( |
| isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts())); |
| GlobalVariable *SrcStrGlob = |
| cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()); |
| if (!SrcStrGlob) |
| return; |
| EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer())); |
| ConstantDataArray *SrcSrc = |
| dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer()); |
| if (!SrcSrc) |
| return; |
| EXPECT_EQ(SrcSrc->getAsCString(), ";test.dbg;foo;3;7;;"); |
| } |
| } // namespace |