1 //===- llvm/unittest/IR/OpenMPIRBuilderTest.cpp - OpenMPIRBuilder tests ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Frontend/OpenMP/OMPConstants.h" 10 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 11 #include "llvm/IR/BasicBlock.h" 12 #include "llvm/IR/DIBuilder.h" 13 #include "llvm/IR/Function.h" 14 #include "llvm/IR/InstIterator.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/IR/Verifier.h" 18 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 using namespace omp; 23 24 namespace { 25 26 class OpenMPIRBuilderTest : public testing::Test { 27 protected: 28 void SetUp() override { 29 M.reset(new Module("MyModule", Ctx)); 30 FunctionType *FTy = 31 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, 32 /*isVarArg=*/false); 33 F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); 34 BB = BasicBlock::Create(Ctx, "", F); 35 36 DIBuilder DIB(*M); 37 auto File = DIB.createFile("test.dbg", "/src", llvm::None, 38 Optional<StringRef>("/src/test.dbg")); 39 auto CU = 40 DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0); 41 auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); 42 auto SP = DIB.createFunction( 43 CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, 44 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); 45 F->setSubprogram(SP); 46 auto Scope = DIB.createLexicalBlockFile(SP, File, 0); 47 DIB.finalize(); 48 DL = DebugLoc::get(3, 7, Scope); 49 } 50 51 void TearDown() override { 52 BB = nullptr; 53 M.reset(); 54 } 55 56 LLVMContext Ctx; 57 std::unique_ptr<Module> M; 58 Function *F; 59 BasicBlock *BB; 60 DebugLoc DL; 61 }; 62 63 TEST_F(OpenMPIRBuilderTest, CreateBarrier) { 64 OpenMPIRBuilder OMPBuilder(*M); 65 OMPBuilder.initialize(); 66 67 IRBuilder<> Builder(BB); 68 69 OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for); 70 EXPECT_TRUE(M->global_empty()); 71 EXPECT_EQ(M->size(), 1U); 72 EXPECT_EQ(F->size(), 1U); 73 EXPECT_EQ(BB->size(), 0U); 74 75 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 76 OMPBuilder.CreateBarrier(Loc, OMPD_for); 77 EXPECT_FALSE(M->global_empty()); 78 EXPECT_EQ(M->size(), 3U); 79 EXPECT_EQ(F->size(), 1U); 80 EXPECT_EQ(BB->size(), 2U); 81 82 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 83 EXPECT_NE(GTID, nullptr); 84 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 85 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 86 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 87 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 88 89 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 90 EXPECT_NE(Barrier, nullptr); 91 EXPECT_EQ(Barrier->getNumArgOperands(), 2U); 92 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier"); 93 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); 94 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); 95 96 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); 97 98 Builder.CreateUnreachable(); 99 EXPECT_FALSE(verifyModule(*M, &errs())); 100 } 101 102 TEST_F(OpenMPIRBuilderTest, CreateCancel) { 103 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 104 OpenMPIRBuilder OMPBuilder(*M); 105 OMPBuilder.initialize(); 106 107 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 108 new UnreachableInst(Ctx, CBB); 109 auto FiniCB = [&](InsertPointTy IP) { 110 ASSERT_NE(IP.getBlock(), nullptr); 111 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 112 BranchInst::Create(CBB, IP.getBlock()); 113 }; 114 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 115 116 IRBuilder<> Builder(BB); 117 118 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 119 auto NewIP = OMPBuilder.CreateCancel(Loc, nullptr, OMPD_parallel); 120 Builder.restoreIP(NewIP); 121 EXPECT_FALSE(M->global_empty()); 122 EXPECT_EQ(M->size(), 3U); 123 EXPECT_EQ(F->size(), 4U); 124 EXPECT_EQ(BB->size(), 4U); 125 126 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 127 EXPECT_NE(GTID, nullptr); 128 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 129 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 130 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 131 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 132 133 CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode()); 134 EXPECT_NE(Cancel, nullptr); 135 EXPECT_EQ(Cancel->getNumArgOperands(), 3U); 136 EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel"); 137 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory()); 138 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory()); 139 EXPECT_EQ(Cancel->getNumUses(), 1U); 140 Instruction *CancelBBTI = Cancel->getParent()->getTerminator(); 141 EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U); 142 EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock()); 143 EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U); 144 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 145 1U); 146 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 147 CBB); 148 149 EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID); 150 151 OMPBuilder.popFinalizationCB(); 152 153 Builder.CreateUnreachable(); 154 EXPECT_FALSE(verifyModule(*M, &errs())); 155 } 156 157 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) { 158 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 159 OpenMPIRBuilder OMPBuilder(*M); 160 OMPBuilder.initialize(); 161 162 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 163 new UnreachableInst(Ctx, CBB); 164 auto FiniCB = [&](InsertPointTy IP) { 165 ASSERT_NE(IP.getBlock(), nullptr); 166 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 167 BranchInst::Create(CBB, IP.getBlock()); 168 }; 169 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 170 171 IRBuilder<> Builder(BB); 172 173 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 174 auto NewIP = OMPBuilder.CreateCancel(Loc, Builder.getTrue(), OMPD_parallel); 175 Builder.restoreIP(NewIP); 176 EXPECT_FALSE(M->global_empty()); 177 EXPECT_EQ(M->size(), 3U); 178 EXPECT_EQ(F->size(), 7U); 179 EXPECT_EQ(BB->size(), 1U); 180 ASSERT_TRUE(isa<BranchInst>(BB->getTerminator())); 181 ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U); 182 BB = BB->getTerminator()->getSuccessor(0); 183 EXPECT_EQ(BB->size(), 4U); 184 185 186 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 187 EXPECT_NE(GTID, nullptr); 188 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 189 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 190 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 191 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 192 193 CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode()); 194 EXPECT_NE(Cancel, nullptr); 195 EXPECT_EQ(Cancel->getNumArgOperands(), 3U); 196 EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel"); 197 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory()); 198 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory()); 199 EXPECT_EQ(Cancel->getNumUses(), 1U); 200 Instruction *CancelBBTI = Cancel->getParent()->getTerminator(); 201 EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U); 202 EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U); 203 EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock()); 204 EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U); 205 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 206 1U); 207 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 208 CBB); 209 210 EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID); 211 212 OMPBuilder.popFinalizationCB(); 213 214 Builder.CreateUnreachable(); 215 EXPECT_FALSE(verifyModule(*M, &errs())); 216 } 217 218 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) { 219 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 220 OpenMPIRBuilder OMPBuilder(*M); 221 OMPBuilder.initialize(); 222 223 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 224 new UnreachableInst(Ctx, CBB); 225 auto FiniCB = [&](InsertPointTy IP) { 226 ASSERT_NE(IP.getBlock(), nullptr); 227 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 228 BranchInst::Create(CBB, IP.getBlock()); 229 }; 230 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 231 232 IRBuilder<> Builder(BB); 233 234 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 235 auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for); 236 Builder.restoreIP(NewIP); 237 EXPECT_FALSE(M->global_empty()); 238 EXPECT_EQ(M->size(), 3U); 239 EXPECT_EQ(F->size(), 4U); 240 EXPECT_EQ(BB->size(), 4U); 241 242 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 243 EXPECT_NE(GTID, nullptr); 244 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 245 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 246 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 247 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 248 249 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 250 EXPECT_NE(Barrier, nullptr); 251 EXPECT_EQ(Barrier->getNumArgOperands(), 2U); 252 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier"); 253 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); 254 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); 255 EXPECT_EQ(Barrier->getNumUses(), 1U); 256 Instruction *BarrierBBTI = Barrier->getParent()->getTerminator(); 257 EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U); 258 EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock()); 259 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U); 260 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 261 1U); 262 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 263 CBB); 264 265 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); 266 267 OMPBuilder.popFinalizationCB(); 268 269 Builder.CreateUnreachable(); 270 EXPECT_FALSE(verifyModule(*M, &errs())); 271 } 272 273 TEST_F(OpenMPIRBuilderTest, DbgLoc) { 274 OpenMPIRBuilder OMPBuilder(*M); 275 OMPBuilder.initialize(); 276 F->setName("func"); 277 278 IRBuilder<> Builder(BB); 279 280 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 281 OMPBuilder.CreateBarrier(Loc, OMPD_for); 282 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 283 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 284 EXPECT_EQ(GTID->getDebugLoc(), DL); 285 EXPECT_EQ(Barrier->getDebugLoc(), DL); 286 EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0))); 287 if (!isa<GlobalVariable>(Barrier->getOperand(0))) 288 return; 289 GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0)); 290 EXPECT_TRUE(Ident->hasInitializer()); 291 if (!Ident->hasInitializer()) 292 return; 293 Constant *Initializer = Ident->getInitializer(); 294 EXPECT_TRUE( 295 isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts())); 296 GlobalVariable *SrcStrGlob = 297 cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()); 298 if (!SrcStrGlob) 299 return; 300 EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer())); 301 ConstantDataArray *SrcSrc = 302 dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer()); 303 if (!SrcSrc) 304 return; 305 EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;"); 306 } 307 308 TEST_F(OpenMPIRBuilderTest, ParallelSimple) { 309 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 310 OpenMPIRBuilder OMPBuilder(*M); 311 OMPBuilder.initialize(); 312 F->setName("func"); 313 IRBuilder<> Builder(BB); 314 315 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 316 317 AllocaInst *PrivAI = nullptr; 318 319 unsigned NumBodiesGenerated = 0; 320 unsigned NumPrivatizedVars = 0; 321 unsigned NumFinalizationPoints = 0; 322 323 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 324 BasicBlock &ContinuationIP) { 325 ++NumBodiesGenerated; 326 327 Builder.restoreIP(AllocaIP); 328 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 329 Builder.CreateStore(F->arg_begin(), PrivAI); 330 331 Builder.restoreIP(CodeGenIP); 332 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 333 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 334 Instruction *ThenTerm, *ElseTerm; 335 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 336 &ThenTerm, &ElseTerm); 337 338 Builder.SetInsertPoint(ThenTerm); 339 Builder.CreateBr(&ContinuationIP); 340 ThenTerm->eraseFromParent(); 341 }; 342 343 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 344 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy { 345 ++NumPrivatizedVars; 346 347 if (!isa<AllocaInst>(VPtr)) { 348 EXPECT_EQ(&VPtr, F->arg_begin()); 349 ReplacementValue = &VPtr; 350 return CodeGenIP; 351 } 352 353 // Trivial copy (=firstprivate). 354 Builder.restoreIP(AllocaIP); 355 Type *VTy = VPtr.getType()->getPointerElementType(); 356 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload"); 357 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy"); 358 Builder.restoreIP(CodeGenIP); 359 Builder.CreateStore(V, ReplacementValue); 360 return CodeGenIP; 361 }; 362 363 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 364 365 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 366 F->getEntryBlock().getFirstInsertionPt()); 367 IRBuilder<>::InsertPoint AfterIP = 368 OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 369 nullptr, nullptr, OMP_PROC_BIND_default, false); 370 EXPECT_EQ(NumBodiesGenerated, 1U); 371 EXPECT_EQ(NumPrivatizedVars, 1U); 372 EXPECT_EQ(NumFinalizationPoints, 1U); 373 374 Builder.restoreIP(AfterIP); 375 Builder.CreateRetVoid(); 376 377 OMPBuilder.finalize(); 378 379 EXPECT_NE(PrivAI, nullptr); 380 Function *OutlinedFn = PrivAI->getFunction(); 381 EXPECT_NE(F, OutlinedFn); 382 EXPECT_FALSE(verifyModule(*M, &errs())); 383 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind)); 384 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse)); 385 EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias)); 386 EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias)); 387 388 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 389 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 390 391 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 392 EXPECT_EQ(OutlinedFn->getNumUses(), 1U); 393 User *Usr = OutlinedFn->user_back(); 394 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 395 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 396 ASSERT_NE(ForkCI, nullptr); 397 398 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 399 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 400 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 401 EXPECT_EQ(ForkCI->getArgOperand(1), 402 ConstantInt::get(Type::getInt32Ty(Ctx), 1U)); 403 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 404 EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin()); 405 } 406 407 TEST_F(OpenMPIRBuilderTest, ParallelNested) { 408 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 409 OpenMPIRBuilder OMPBuilder(*M); 410 OMPBuilder.initialize(); 411 F->setName("func"); 412 IRBuilder<> Builder(BB); 413 414 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 415 416 unsigned NumInnerBodiesGenerated = 0; 417 unsigned NumOuterBodiesGenerated = 0; 418 unsigned NumFinalizationPoints = 0; 419 420 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 421 BasicBlock &ContinuationIP) { 422 ++NumInnerBodiesGenerated; 423 }; 424 425 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 426 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy { 427 // Trivial copy (=firstprivate). 428 Builder.restoreIP(AllocaIP); 429 Type *VTy = VPtr.getType()->getPointerElementType(); 430 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload"); 431 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy"); 432 Builder.restoreIP(CodeGenIP); 433 Builder.CreateStore(V, ReplacementValue); 434 return CodeGenIP; 435 }; 436 437 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 438 439 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 440 BasicBlock &ContinuationIP) { 441 ++NumOuterBodiesGenerated; 442 Builder.restoreIP(CodeGenIP); 443 BasicBlock *CGBB = CodeGenIP.getBlock(); 444 BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 445 CGBB->getTerminator()->eraseFromParent(); 446 ; 447 448 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel( 449 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 450 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 451 452 Builder.restoreIP(AfterIP); 453 Builder.CreateBr(NewBB); 454 }; 455 456 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 457 F->getEntryBlock().getFirstInsertionPt()); 458 IRBuilder<>::InsertPoint AfterIP = 459 OMPBuilder.CreateParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 460 nullptr, nullptr, OMP_PROC_BIND_default, false); 461 462 EXPECT_EQ(NumInnerBodiesGenerated, 1U); 463 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 464 EXPECT_EQ(NumFinalizationPoints, 2U); 465 466 Builder.restoreIP(AfterIP); 467 Builder.CreateRetVoid(); 468 469 OMPBuilder.finalize(); 470 471 EXPECT_EQ(M->size(), 5U); 472 for (Function &OutlinedFn : *M) { 473 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 474 continue; 475 EXPECT_FALSE(verifyModule(*M, &errs())); 476 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 477 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 478 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 479 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 480 481 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 482 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 483 484 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 485 User *Usr = OutlinedFn.user_back(); 486 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 487 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 488 ASSERT_NE(ForkCI, nullptr); 489 490 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 491 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 492 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 493 EXPECT_EQ(ForkCI->getArgOperand(1), 494 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 495 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 496 } 497 } 498 499 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) { 500 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 501 OpenMPIRBuilder OMPBuilder(*M); 502 OMPBuilder.initialize(); 503 F->setName("func"); 504 IRBuilder<> Builder(BB); 505 506 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 507 508 unsigned NumInnerBodiesGenerated = 0; 509 unsigned NumOuterBodiesGenerated = 0; 510 unsigned NumFinalizationPoints = 0; 511 512 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 513 BasicBlock &ContinuationIP) { 514 ++NumInnerBodiesGenerated; 515 }; 516 517 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 518 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy { 519 // Trivial copy (=firstprivate). 520 Builder.restoreIP(AllocaIP); 521 Type *VTy = VPtr.getType()->getPointerElementType(); 522 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload"); 523 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy"); 524 Builder.restoreIP(CodeGenIP); 525 Builder.CreateStore(V, ReplacementValue); 526 return CodeGenIP; 527 }; 528 529 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 530 531 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 532 BasicBlock &ContinuationIP) { 533 ++NumOuterBodiesGenerated; 534 Builder.restoreIP(CodeGenIP); 535 BasicBlock *CGBB = CodeGenIP.getBlock(); 536 BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 537 BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt()); 538 CGBB->getTerminator()->eraseFromParent(); 539 ; 540 NewBB1->getTerminator()->eraseFromParent(); 541 ; 542 543 IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.CreateParallel( 544 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 545 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 546 547 Builder.restoreIP(AfterIP1); 548 Builder.CreateBr(NewBB1); 549 550 IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.CreateParallel( 551 InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB, 552 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 553 554 Builder.restoreIP(AfterIP2); 555 Builder.CreateBr(NewBB2); 556 }; 557 558 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 559 F->getEntryBlock().getFirstInsertionPt()); 560 IRBuilder<>::InsertPoint AfterIP = 561 OMPBuilder.CreateParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 562 nullptr, nullptr, OMP_PROC_BIND_default, false); 563 564 EXPECT_EQ(NumInnerBodiesGenerated, 2U); 565 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 566 EXPECT_EQ(NumFinalizationPoints, 3U); 567 568 Builder.restoreIP(AfterIP); 569 Builder.CreateRetVoid(); 570 571 OMPBuilder.finalize(); 572 573 EXPECT_EQ(M->size(), 6U); 574 for (Function &OutlinedFn : *M) { 575 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 576 continue; 577 EXPECT_FALSE(verifyModule(*M, &errs())); 578 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 579 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 580 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 581 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 582 583 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 584 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 585 586 unsigned NumAllocas = 0; 587 for (Instruction &I : instructions(OutlinedFn)) 588 NumAllocas += isa<AllocaInst>(I); 589 EXPECT_EQ(NumAllocas, 1U); 590 591 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 592 User *Usr = OutlinedFn.user_back(); 593 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 594 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 595 ASSERT_NE(ForkCI, nullptr); 596 597 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 598 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 599 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 600 EXPECT_EQ(ForkCI->getArgOperand(1), 601 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 602 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 603 } 604 } 605 606 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) { 607 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 608 OpenMPIRBuilder OMPBuilder(*M); 609 OMPBuilder.initialize(); 610 F->setName("func"); 611 IRBuilder<> Builder(BB); 612 613 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 614 615 AllocaInst *PrivAI = nullptr; 616 617 unsigned NumBodiesGenerated = 0; 618 unsigned NumPrivatizedVars = 0; 619 unsigned NumFinalizationPoints = 0; 620 621 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 622 BasicBlock &ContinuationIP) { 623 ++NumBodiesGenerated; 624 625 Builder.restoreIP(AllocaIP); 626 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 627 Builder.CreateStore(F->arg_begin(), PrivAI); 628 629 Builder.restoreIP(CodeGenIP); 630 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 631 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 632 Instruction *ThenTerm, *ElseTerm; 633 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 634 &ThenTerm, &ElseTerm); 635 636 Builder.SetInsertPoint(ThenTerm); 637 Builder.CreateBr(&ContinuationIP); 638 ThenTerm->eraseFromParent(); 639 }; 640 641 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 642 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy { 643 ++NumPrivatizedVars; 644 645 if (!isa<AllocaInst>(VPtr)) { 646 EXPECT_EQ(&VPtr, F->arg_begin()); 647 ReplacementValue = &VPtr; 648 return CodeGenIP; 649 } 650 651 // Trivial copy (=firstprivate). 652 Builder.restoreIP(AllocaIP); 653 Type *VTy = VPtr.getType()->getPointerElementType(); 654 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload"); 655 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy"); 656 Builder.restoreIP(CodeGenIP); 657 Builder.CreateStore(V, ReplacementValue); 658 return CodeGenIP; 659 }; 660 661 auto FiniCB = [&](InsertPointTy CodeGenIP) { 662 ++NumFinalizationPoints; 663 // No destructors. 664 }; 665 666 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 667 F->getEntryBlock().getFirstInsertionPt()); 668 IRBuilder<>::InsertPoint AfterIP = 669 OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 670 Builder.CreateIsNotNull(F->arg_begin()), 671 nullptr, OMP_PROC_BIND_default, false); 672 673 EXPECT_EQ(NumBodiesGenerated, 1U); 674 EXPECT_EQ(NumPrivatizedVars, 1U); 675 EXPECT_EQ(NumFinalizationPoints, 1U); 676 677 Builder.restoreIP(AfterIP); 678 Builder.CreateRetVoid(); 679 OMPBuilder.finalize(); 680 681 EXPECT_NE(PrivAI, nullptr); 682 Function *OutlinedFn = PrivAI->getFunction(); 683 EXPECT_NE(F, OutlinedFn); 684 EXPECT_FALSE(verifyModule(*M, &errs())); 685 686 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 687 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 688 689 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 690 ASSERT_EQ(OutlinedFn->getNumUses(), 2U); 691 692 CallInst *DirectCI = nullptr; 693 CallInst *ForkCI = nullptr; 694 for (User *Usr : OutlinedFn->users()) { 695 if (isa<CallInst>(Usr)) { 696 ASSERT_EQ(DirectCI, nullptr); 697 DirectCI = cast<CallInst>(Usr); 698 } else { 699 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 700 ASSERT_EQ(Usr->getNumUses(), 1U); 701 ASSERT_TRUE(isa<CallInst>(Usr->user_back())); 702 ForkCI = cast<CallInst>(Usr->user_back()); 703 } 704 } 705 706 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 707 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 708 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 709 EXPECT_EQ(ForkCI->getArgOperand(1), 710 ConstantInt::get(Type::getInt32Ty(Ctx), 1)); 711 EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin()); 712 713 EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn); 714 EXPECT_EQ(DirectCI->getNumArgOperands(), 3U); 715 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0))); 716 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1))); 717 EXPECT_EQ(DirectCI->getArgOperand(2), F->arg_begin()); 718 } 719 720 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) { 721 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 722 OpenMPIRBuilder OMPBuilder(*M); 723 OMPBuilder.initialize(); 724 F->setName("func"); 725 IRBuilder<> Builder(BB); 726 727 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 728 729 unsigned NumBodiesGenerated = 0; 730 unsigned NumPrivatizedVars = 0; 731 unsigned NumFinalizationPoints = 0; 732 733 CallInst *CheckedBarrier = nullptr; 734 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 735 BasicBlock &ContinuationIP) { 736 ++NumBodiesGenerated; 737 738 Builder.restoreIP(CodeGenIP); 739 740 // Create three barriers, two cancel barriers but only one checked. 741 Function *CBFn, *BFn; 742 743 Builder.restoreIP( 744 OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel)); 745 746 CBFn = M->getFunction("__kmpc_cancel_barrier"); 747 BFn = M->getFunction("__kmpc_barrier"); 748 ASSERT_NE(CBFn, nullptr); 749 ASSERT_EQ(BFn, nullptr); 750 ASSERT_EQ(CBFn->getNumUses(), 1U); 751 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 752 ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U); 753 CheckedBarrier = cast<CallInst>(CBFn->user_back()); 754 755 Builder.restoreIP( 756 OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, true)); 757 CBFn = M->getFunction("__kmpc_cancel_barrier"); 758 BFn = M->getFunction("__kmpc_barrier"); 759 ASSERT_NE(CBFn, nullptr); 760 ASSERT_NE(BFn, nullptr); 761 ASSERT_EQ(CBFn->getNumUses(), 1U); 762 ASSERT_EQ(BFn->getNumUses(), 1U); 763 ASSERT_TRUE(isa<CallInst>(BFn->user_back())); 764 ASSERT_EQ(BFn->user_back()->getNumUses(), 0U); 765 766 Builder.restoreIP(OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, 767 false, false)); 768 ASSERT_EQ(CBFn->getNumUses(), 2U); 769 ASSERT_EQ(BFn->getNumUses(), 1U); 770 ASSERT_TRUE(CBFn->user_back() != CheckedBarrier); 771 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 772 ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U); 773 }; 774 775 auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, 776 Value *&) -> InsertPointTy { 777 ++NumPrivatizedVars; 778 llvm_unreachable("No privatization callback call expected!"); 779 }; 780 781 FunctionType *FakeDestructorTy = 782 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, 783 /*isVarArg=*/false); 784 auto *FakeDestructor = Function::Create( 785 FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get()); 786 787 auto FiniCB = [&](InsertPointTy IP) { 788 ++NumFinalizationPoints; 789 Builder.restoreIP(IP); 790 Builder.CreateCall(FakeDestructor, 791 {Builder.getInt32(NumFinalizationPoints)}); 792 }; 793 794 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 795 F->getEntryBlock().getFirstInsertionPt()); 796 IRBuilder<>::InsertPoint AfterIP = 797 OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 798 Builder.CreateIsNotNull(F->arg_begin()), 799 nullptr, OMP_PROC_BIND_default, true); 800 801 EXPECT_EQ(NumBodiesGenerated, 1U); 802 EXPECT_EQ(NumPrivatizedVars, 0U); 803 EXPECT_EQ(NumFinalizationPoints, 2U); 804 EXPECT_EQ(FakeDestructor->getNumUses(), 2U); 805 806 Builder.restoreIP(AfterIP); 807 Builder.CreateRetVoid(); 808 OMPBuilder.finalize(); 809 810 EXPECT_FALSE(verifyModule(*M, &errs())); 811 812 BasicBlock *ExitBB = nullptr; 813 for (const User *Usr : FakeDestructor->users()) { 814 const CallInst *CI = dyn_cast<CallInst>(Usr); 815 ASSERT_EQ(CI->getCalledFunction(), FakeDestructor); 816 ASSERT_TRUE(isa<BranchInst>(CI->getNextNode())); 817 ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U); 818 if (ExitBB) 819 ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB); 820 else 821 ExitBB = CI->getNextNode()->getSuccessor(0); 822 ASSERT_EQ(ExitBB->size(), 1U); 823 if (!isa<ReturnInst>(ExitBB->front())) { 824 ASSERT_TRUE(isa<BranchInst>(ExitBB->front())); 825 ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U); 826 ASSERT_TRUE(isa<ReturnInst>( 827 cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front())); 828 } 829 } 830 } 831 832 TEST_F(OpenMPIRBuilderTest, MasterDirective) { 833 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 834 OpenMPIRBuilder OMPBuilder(*M); 835 OMPBuilder.initialize(); 836 F->setName("func"); 837 IRBuilder<> Builder(BB); 838 839 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 840 841 AllocaInst *PrivAI = nullptr; 842 843 BasicBlock *EntryBB = nullptr; 844 BasicBlock *ExitBB = nullptr; 845 BasicBlock *ThenBB = nullptr; 846 847 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 848 BasicBlock &FiniBB) { 849 if (AllocaIP.isSet()) 850 Builder.restoreIP(AllocaIP); 851 else 852 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 853 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 854 Builder.CreateStore(F->arg_begin(), PrivAI); 855 856 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 857 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 858 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 859 860 Builder.restoreIP(CodeGenIP); 861 862 // collect some info for checks later 863 ExitBB = FiniBB.getUniqueSuccessor(); 864 ThenBB = Builder.GetInsertBlock(); 865 EntryBB = ThenBB->getUniquePredecessor(); 866 867 // simple instructions for body 868 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 869 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 870 }; 871 872 auto FiniCB = [&](InsertPointTy IP) { 873 BasicBlock *IPBB = IP.getBlock(); 874 EXPECT_NE(IPBB->end(), IP.getPoint()); 875 }; 876 877 Builder.restoreIP(OMPBuilder.CreateMaster(Builder, BodyGenCB, FiniCB)); 878 Value *EntryBBTI = EntryBB->getTerminator(); 879 EXPECT_NE(EntryBBTI, nullptr); 880 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 881 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 882 EXPECT_TRUE(EntryBr->isConditional()); 883 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 884 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 885 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 886 887 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 888 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 889 890 CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0)); 891 EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U); 892 EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master"); 893 EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0))); 894 895 CallInst *MasterEndCI = nullptr; 896 for (auto &FI : *ThenBB) { 897 Instruction *cur = &FI; 898 if (isa<CallInst>(cur)) { 899 MasterEndCI = cast<CallInst>(cur); 900 if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master") 901 break; 902 MasterEndCI = nullptr; 903 } 904 } 905 EXPECT_NE(MasterEndCI, nullptr); 906 EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U); 907 EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0))); 908 EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1)); 909 } 910 911 TEST_F(OpenMPIRBuilderTest, CriticalDirective) { 912 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 913 OpenMPIRBuilder OMPBuilder(*M); 914 OMPBuilder.initialize(); 915 F->setName("func"); 916 IRBuilder<> Builder(BB); 917 918 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 919 920 AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 921 922 BasicBlock *EntryBB = nullptr; 923 924 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 925 BasicBlock &FiniBB) { 926 // collect some info for checks later 927 EntryBB = FiniBB.getUniquePredecessor(); 928 929 // actual start for bodyCB 930 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 931 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 932 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 933 EXPECT_EQ(EntryBB, CodeGenIPBB); 934 935 // body begin 936 Builder.restoreIP(CodeGenIP); 937 Builder.CreateStore(F->arg_begin(), PrivAI); 938 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 939 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 940 }; 941 942 auto FiniCB = [&](InsertPointTy IP) { 943 BasicBlock *IPBB = IP.getBlock(); 944 EXPECT_NE(IPBB->end(), IP.getPoint()); 945 }; 946 947 Builder.restoreIP(OMPBuilder.CreateCritical(Builder, BodyGenCB, FiniCB, 948 "testCRT", nullptr)); 949 950 Value *EntryBBTI = EntryBB->getTerminator(); 951 EXPECT_EQ(EntryBBTI, nullptr); 952 953 CallInst *CriticalEntryCI = nullptr; 954 for (auto &EI : *EntryBB) { 955 Instruction *cur = &EI; 956 if (isa<CallInst>(cur)) { 957 CriticalEntryCI = cast<CallInst>(cur); 958 if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical") 959 break; 960 CriticalEntryCI = nullptr; 961 } 962 } 963 EXPECT_NE(CriticalEntryCI, nullptr); 964 EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U); 965 EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical"); 966 EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0))); 967 968 CallInst *CriticalEndCI = nullptr; 969 for (auto &FI : *EntryBB) { 970 Instruction *cur = &FI; 971 if (isa<CallInst>(cur)) { 972 CriticalEndCI = cast<CallInst>(cur); 973 if (CriticalEndCI->getCalledFunction()->getName() == 974 "__kmpc_end_critical") 975 break; 976 CriticalEndCI = nullptr; 977 } 978 } 979 EXPECT_NE(CriticalEndCI, nullptr); 980 EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U); 981 EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0))); 982 EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1)); 983 PointerType *CriticalNamePtrTy = 984 PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8)); 985 EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2)); 986 EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy); 987 } 988 989 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) { 990 OpenMPIRBuilder OMPBuilder(*M); 991 OMPBuilder.initialize(); 992 F->setName("func"); 993 IRBuilder<> Builder(BB); 994 995 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 996 997 IntegerType* Int32 = Type::getInt32Ty(M->getContext()); 998 AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo()); 999 AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo()); 1000 1001 BasicBlock *EntryBB = BB; 1002 1003 OMPBuilder.CreateCopyinClauseBlocks(Builder.saveIP(), MasterAddress, PrivAddress, Int32, /*BranchtoEnd*/true); 1004 1005 BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator()); 1006 1007 EXPECT_NE(EntryBr, nullptr); 1008 EXPECT_TRUE(EntryBr->isConditional()); 1009 1010 BasicBlock* NotMasterBB = EntryBr->getSuccessor(0); 1011 BasicBlock* CopyinEnd = EntryBr->getSuccessor(1); 1012 CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition()); 1013 1014 EXPECT_NE(CMP, nullptr); 1015 EXPECT_NE(NotMasterBB, nullptr); 1016 EXPECT_NE(CopyinEnd, nullptr); 1017 1018 BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator()); 1019 EXPECT_NE(NotMasterBr, nullptr); 1020 EXPECT_FALSE(NotMasterBr->isConditional()); 1021 EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0)); 1022 } 1023 1024 TEST_F(OpenMPIRBuilderTest, SingleDirective) { 1025 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1026 OpenMPIRBuilder OMPBuilder(*M); 1027 OMPBuilder.initialize(); 1028 F->setName("func"); 1029 IRBuilder<> Builder(BB); 1030 1031 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1032 1033 AllocaInst *PrivAI = nullptr; 1034 1035 BasicBlock *EntryBB = nullptr; 1036 BasicBlock *ExitBB = nullptr; 1037 BasicBlock *ThenBB = nullptr; 1038 1039 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1040 BasicBlock &FiniBB) { 1041 if (AllocaIP.isSet()) 1042 Builder.restoreIP(AllocaIP); 1043 else 1044 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 1045 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1046 Builder.CreateStore(F->arg_begin(), PrivAI); 1047 1048 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1049 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1050 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1051 1052 Builder.restoreIP(CodeGenIP); 1053 1054 // collect some info for checks later 1055 ExitBB = FiniBB.getUniqueSuccessor(); 1056 ThenBB = Builder.GetInsertBlock(); 1057 EntryBB = ThenBB->getUniquePredecessor(); 1058 1059 // simple instructions for body 1060 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 1061 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1062 }; 1063 1064 auto FiniCB = [&](InsertPointTy IP) { 1065 BasicBlock *IPBB = IP.getBlock(); 1066 EXPECT_NE(IPBB->end(), IP.getPoint()); 1067 }; 1068 1069 Builder.restoreIP( 1070 OMPBuilder.CreateSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr)); 1071 Value *EntryBBTI = EntryBB->getTerminator(); 1072 EXPECT_NE(EntryBBTI, nullptr); 1073 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 1074 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 1075 EXPECT_TRUE(EntryBr->isConditional()); 1076 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 1077 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 1078 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 1079 1080 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 1081 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 1082 1083 CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0)); 1084 EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U); 1085 EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single"); 1086 EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0))); 1087 1088 CallInst *SingleEndCI = nullptr; 1089 for (auto &FI : *ThenBB) { 1090 Instruction *cur = &FI; 1091 if (isa<CallInst>(cur)) { 1092 SingleEndCI = cast<CallInst>(cur); 1093 if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single") 1094 break; 1095 SingleEndCI = nullptr; 1096 } 1097 } 1098 EXPECT_NE(SingleEndCI, nullptr); 1099 EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U); 1100 EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0))); 1101 EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1)); 1102 } 1103 1104 } // namespace 1105