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