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 /// Create an instruction that uses the values in \p Values. We use "printf" 27 /// just because it is often used for this purpose in test code, but it is never 28 /// executed here. 29 static CallInst *createPrintfCall(IRBuilder<> &Builder, StringRef FormatStr, 30 ArrayRef<Value *> Values) { 31 Module *M = Builder.GetInsertBlock()->getParent()->getParent(); 32 33 GlobalVariable *GV = Builder.CreateGlobalString(FormatStr, "", 0, M); 34 Constant *Zero = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0); 35 Constant *Indices[] = {Zero, Zero}; 36 Constant *FormatStrConst = 37 ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, Indices); 38 39 Function *PrintfDecl = M->getFunction("printf"); 40 if (!PrintfDecl) { 41 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; 42 FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true); 43 PrintfDecl = Function::Create(Ty, Linkage, "printf", M); 44 } 45 46 SmallVector<Value *, 4> Args; 47 Args.push_back(FormatStrConst); 48 Args.append(Values.begin(), Values.end()); 49 return Builder.CreateCall(PrintfDecl, Args); 50 } 51 52 /// Verify that blocks in \p RefOrder are corresponds to the depth-first visit 53 /// order the control flow of \p F. 54 /// 55 /// This is an easy way to verify the branching structure of the CFG without 56 /// checking every branch instruction individually. For the CFG of a 57 /// CanonicalLoopInfo, the Cond BB's terminating branch's first edge is entering 58 /// the body, i.e. the DFS order corresponds to the execution order with one 59 /// loop iteration. 60 static testing::AssertionResult 61 verifyDFSOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) { 62 ArrayRef<BasicBlock *>::iterator It = RefOrder.begin(); 63 ArrayRef<BasicBlock *>::iterator E = RefOrder.end(); 64 65 df_iterator_default_set<BasicBlock *, 16> Visited; 66 auto DFS = llvm::depth_first_ext(&F->getEntryBlock(), Visited); 67 68 BasicBlock *Prev = nullptr; 69 for (BasicBlock *BB : DFS) { 70 if (It != E && BB == *It) { 71 Prev = *It; 72 ++It; 73 } 74 } 75 76 if (It == E) 77 return testing::AssertionSuccess(); 78 if (!Prev) 79 return testing::AssertionFailure() 80 << "Did not find " << (*It)->getName() << " in control flow"; 81 return testing::AssertionFailure() 82 << "Expected " << Prev->getName() << " before " << (*It)->getName() 83 << " in control flow"; 84 } 85 86 /// Verify that blocks in \p RefOrder are in the same relative order in the 87 /// linked lists of blocks in \p F. The linked list may contain additional 88 /// blocks in-between. 89 /// 90 /// While the order in the linked list is not relevant for semantics, keeping 91 /// the order roughly in execution order makes its printout easier to read. 92 static testing::AssertionResult 93 verifyListOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) { 94 ArrayRef<BasicBlock *>::iterator It = RefOrder.begin(); 95 ArrayRef<BasicBlock *>::iterator E = RefOrder.end(); 96 97 BasicBlock *Prev = nullptr; 98 for (BasicBlock &BB : *F) { 99 if (It != E && &BB == *It) { 100 Prev = *It; 101 ++It; 102 } 103 } 104 105 if (It == E) 106 return testing::AssertionSuccess(); 107 if (!Prev) 108 return testing::AssertionFailure() << "Did not find " << (*It)->getName() 109 << " in function " << F->getName(); 110 return testing::AssertionFailure() 111 << "Expected " << Prev->getName() << " before " << (*It)->getName() 112 << " in function " << F->getName(); 113 } 114 115 class OpenMPIRBuilderTest : public testing::Test { 116 protected: 117 void SetUp() override { 118 M.reset(new Module("MyModule", Ctx)); 119 FunctionType *FTy = 120 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, 121 /*isVarArg=*/false); 122 F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); 123 BB = BasicBlock::Create(Ctx, "", F); 124 125 DIBuilder DIB(*M); 126 auto File = DIB.createFile("test.dbg", "/src", llvm::None, 127 Optional<StringRef>("/src/test.dbg")); 128 auto CU = 129 DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0); 130 auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); 131 auto SP = DIB.createFunction( 132 CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, 133 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); 134 F->setSubprogram(SP); 135 auto Scope = DIB.createLexicalBlockFile(SP, File, 0); 136 DIB.finalize(); 137 DL = DILocation::get(Ctx, 3, 7, Scope); 138 } 139 140 void TearDown() override { 141 BB = nullptr; 142 M.reset(); 143 } 144 145 LLVMContext Ctx; 146 std::unique_ptr<Module> M; 147 Function *F; 148 BasicBlock *BB; 149 DebugLoc DL; 150 }; 151 152 // Returns the value stored in the given allocation. Returns null if the given 153 // value is not a result of an allocation, if no value is stored or if there is 154 // more than one store. 155 static Value *findStoredValue(Value *AllocaValue) { 156 Instruction *Alloca = dyn_cast<AllocaInst>(AllocaValue); 157 if (!Alloca) 158 return nullptr; 159 StoreInst *Store = nullptr; 160 for (Use &U : Alloca->uses()) { 161 if (auto *CandidateStore = dyn_cast<StoreInst>(U.getUser())) { 162 EXPECT_EQ(Store, nullptr); 163 Store = CandidateStore; 164 } 165 } 166 if (!Store) 167 return nullptr; 168 return Store->getValueOperand(); 169 } 170 171 TEST_F(OpenMPIRBuilderTest, CreateBarrier) { 172 OpenMPIRBuilder OMPBuilder(*M); 173 OMPBuilder.initialize(); 174 175 IRBuilder<> Builder(BB); 176 177 OMPBuilder.createBarrier({IRBuilder<>::InsertPoint()}, OMPD_for); 178 EXPECT_TRUE(M->global_empty()); 179 EXPECT_EQ(M->size(), 1U); 180 EXPECT_EQ(F->size(), 1U); 181 EXPECT_EQ(BB->size(), 0U); 182 183 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 184 OMPBuilder.createBarrier(Loc, OMPD_for); 185 EXPECT_FALSE(M->global_empty()); 186 EXPECT_EQ(M->size(), 3U); 187 EXPECT_EQ(F->size(), 1U); 188 EXPECT_EQ(BB->size(), 2U); 189 190 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 191 EXPECT_NE(GTID, nullptr); 192 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 193 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 194 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 195 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 196 197 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 198 EXPECT_NE(Barrier, nullptr); 199 EXPECT_EQ(Barrier->getNumArgOperands(), 2U); 200 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier"); 201 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); 202 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); 203 204 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); 205 206 Builder.CreateUnreachable(); 207 EXPECT_FALSE(verifyModule(*M, &errs())); 208 } 209 210 TEST_F(OpenMPIRBuilderTest, CreateCancel) { 211 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 212 OpenMPIRBuilder OMPBuilder(*M); 213 OMPBuilder.initialize(); 214 215 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 216 new UnreachableInst(Ctx, CBB); 217 auto FiniCB = [&](InsertPointTy IP) { 218 ASSERT_NE(IP.getBlock(), nullptr); 219 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 220 BranchInst::Create(CBB, IP.getBlock()); 221 }; 222 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 223 224 IRBuilder<> Builder(BB); 225 226 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 227 auto NewIP = OMPBuilder.createCancel(Loc, nullptr, OMPD_parallel); 228 Builder.restoreIP(NewIP); 229 EXPECT_FALSE(M->global_empty()); 230 EXPECT_EQ(M->size(), 3U); 231 EXPECT_EQ(F->size(), 4U); 232 EXPECT_EQ(BB->size(), 4U); 233 234 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 235 EXPECT_NE(GTID, nullptr); 236 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 237 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 238 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 239 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 240 241 CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode()); 242 EXPECT_NE(Cancel, nullptr); 243 EXPECT_EQ(Cancel->getNumArgOperands(), 3U); 244 EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel"); 245 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory()); 246 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory()); 247 EXPECT_EQ(Cancel->getNumUses(), 1U); 248 Instruction *CancelBBTI = Cancel->getParent()->getTerminator(); 249 EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U); 250 EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock()); 251 EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U); 252 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 253 1U); 254 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 255 CBB); 256 257 EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID); 258 259 OMPBuilder.popFinalizationCB(); 260 261 Builder.CreateUnreachable(); 262 EXPECT_FALSE(verifyModule(*M, &errs())); 263 } 264 265 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) { 266 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 267 OpenMPIRBuilder OMPBuilder(*M); 268 OMPBuilder.initialize(); 269 270 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 271 new UnreachableInst(Ctx, CBB); 272 auto FiniCB = [&](InsertPointTy IP) { 273 ASSERT_NE(IP.getBlock(), nullptr); 274 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 275 BranchInst::Create(CBB, IP.getBlock()); 276 }; 277 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 278 279 IRBuilder<> Builder(BB); 280 281 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 282 auto NewIP = OMPBuilder.createCancel(Loc, Builder.getTrue(), OMPD_parallel); 283 Builder.restoreIP(NewIP); 284 EXPECT_FALSE(M->global_empty()); 285 EXPECT_EQ(M->size(), 3U); 286 EXPECT_EQ(F->size(), 7U); 287 EXPECT_EQ(BB->size(), 1U); 288 ASSERT_TRUE(isa<BranchInst>(BB->getTerminator())); 289 ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U); 290 BB = BB->getTerminator()->getSuccessor(0); 291 EXPECT_EQ(BB->size(), 4U); 292 293 294 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 295 EXPECT_NE(GTID, nullptr); 296 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 297 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 298 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 299 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 300 301 CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode()); 302 EXPECT_NE(Cancel, nullptr); 303 EXPECT_EQ(Cancel->getNumArgOperands(), 3U); 304 EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel"); 305 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory()); 306 EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory()); 307 EXPECT_EQ(Cancel->getNumUses(), 1U); 308 Instruction *CancelBBTI = Cancel->getParent()->getTerminator(); 309 EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U); 310 EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U); 311 EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock()); 312 EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U); 313 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 314 1U); 315 EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 316 CBB); 317 318 EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID); 319 320 OMPBuilder.popFinalizationCB(); 321 322 Builder.CreateUnreachable(); 323 EXPECT_FALSE(verifyModule(*M, &errs())); 324 } 325 326 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) { 327 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 328 OpenMPIRBuilder OMPBuilder(*M); 329 OMPBuilder.initialize(); 330 331 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F); 332 new UnreachableInst(Ctx, CBB); 333 auto FiniCB = [&](InsertPointTy IP) { 334 ASSERT_NE(IP.getBlock(), nullptr); 335 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint()); 336 BranchInst::Create(CBB, IP.getBlock()); 337 }; 338 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true}); 339 340 IRBuilder<> Builder(BB); 341 342 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()}); 343 auto NewIP = OMPBuilder.createBarrier(Loc, OMPD_for); 344 Builder.restoreIP(NewIP); 345 EXPECT_FALSE(M->global_empty()); 346 EXPECT_EQ(M->size(), 3U); 347 EXPECT_EQ(F->size(), 4U); 348 EXPECT_EQ(BB->size(), 4U); 349 350 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 351 EXPECT_NE(GTID, nullptr); 352 EXPECT_EQ(GTID->getNumArgOperands(), 1U); 353 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num"); 354 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory()); 355 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory()); 356 357 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 358 EXPECT_NE(Barrier, nullptr); 359 EXPECT_EQ(Barrier->getNumArgOperands(), 2U); 360 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier"); 361 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory()); 362 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory()); 363 EXPECT_EQ(Barrier->getNumUses(), 1U); 364 Instruction *BarrierBBTI = Barrier->getParent()->getTerminator(); 365 EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U); 366 EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock()); 367 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U); 368 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(), 369 1U); 370 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), 371 CBB); 372 373 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID); 374 375 OMPBuilder.popFinalizationCB(); 376 377 Builder.CreateUnreachable(); 378 EXPECT_FALSE(verifyModule(*M, &errs())); 379 } 380 381 TEST_F(OpenMPIRBuilderTest, DbgLoc) { 382 OpenMPIRBuilder OMPBuilder(*M); 383 OMPBuilder.initialize(); 384 F->setName("func"); 385 386 IRBuilder<> Builder(BB); 387 388 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 389 OMPBuilder.createBarrier(Loc, OMPD_for); 390 CallInst *GTID = dyn_cast<CallInst>(&BB->front()); 391 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode()); 392 EXPECT_EQ(GTID->getDebugLoc(), DL); 393 EXPECT_EQ(Barrier->getDebugLoc(), DL); 394 EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0))); 395 if (!isa<GlobalVariable>(Barrier->getOperand(0))) 396 return; 397 GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0)); 398 EXPECT_TRUE(Ident->hasInitializer()); 399 if (!Ident->hasInitializer()) 400 return; 401 Constant *Initializer = Ident->getInitializer(); 402 EXPECT_TRUE( 403 isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts())); 404 GlobalVariable *SrcStrGlob = 405 cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()); 406 if (!SrcStrGlob) 407 return; 408 EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer())); 409 ConstantDataArray *SrcSrc = 410 dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer()); 411 if (!SrcSrc) 412 return; 413 EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;"); 414 } 415 416 TEST_F(OpenMPIRBuilderTest, ParallelSimple) { 417 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 418 OpenMPIRBuilder OMPBuilder(*M); 419 OMPBuilder.initialize(); 420 F->setName("func"); 421 IRBuilder<> Builder(BB); 422 423 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 424 425 AllocaInst *PrivAI = nullptr; 426 427 unsigned NumBodiesGenerated = 0; 428 unsigned NumPrivatizedVars = 0; 429 unsigned NumFinalizationPoints = 0; 430 431 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 432 BasicBlock &ContinuationIP) { 433 ++NumBodiesGenerated; 434 435 Builder.restoreIP(AllocaIP); 436 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 437 Builder.CreateStore(F->arg_begin(), PrivAI); 438 439 Builder.restoreIP(CodeGenIP); 440 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 441 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 442 Instruction *ThenTerm, *ElseTerm; 443 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 444 &ThenTerm, &ElseTerm); 445 446 Builder.SetInsertPoint(ThenTerm); 447 Builder.CreateBr(&ContinuationIP); 448 ThenTerm->eraseFromParent(); 449 }; 450 451 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 452 Value &Orig, Value &Inner, 453 Value *&ReplacementValue) -> InsertPointTy { 454 ++NumPrivatizedVars; 455 456 if (!isa<AllocaInst>(Orig)) { 457 EXPECT_EQ(&Orig, F->arg_begin()); 458 ReplacementValue = &Inner; 459 return CodeGenIP; 460 } 461 462 // Since the original value is an allocation, it has a pointer type and 463 // therefore no additional wrapping should happen. 464 EXPECT_EQ(&Orig, &Inner); 465 466 // Trivial copy (=firstprivate). 467 Builder.restoreIP(AllocaIP); 468 Type *VTy = Inner.getType()->getPointerElementType(); 469 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 470 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 471 Builder.restoreIP(CodeGenIP); 472 Builder.CreateStore(V, ReplacementValue); 473 return CodeGenIP; 474 }; 475 476 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 477 478 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 479 F->getEntryBlock().getFirstInsertionPt()); 480 IRBuilder<>::InsertPoint AfterIP = 481 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 482 nullptr, nullptr, OMP_PROC_BIND_default, false); 483 EXPECT_EQ(NumBodiesGenerated, 1U); 484 EXPECT_EQ(NumPrivatizedVars, 1U); 485 EXPECT_EQ(NumFinalizationPoints, 1U); 486 487 Builder.restoreIP(AfterIP); 488 Builder.CreateRetVoid(); 489 490 OMPBuilder.finalize(); 491 492 EXPECT_NE(PrivAI, nullptr); 493 Function *OutlinedFn = PrivAI->getFunction(); 494 EXPECT_NE(F, OutlinedFn); 495 EXPECT_FALSE(verifyModule(*M, &errs())); 496 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind)); 497 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse)); 498 EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias)); 499 EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias)); 500 501 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 502 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 503 504 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 505 EXPECT_EQ(OutlinedFn->getNumUses(), 1U); 506 User *Usr = OutlinedFn->user_back(); 507 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 508 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 509 ASSERT_NE(ForkCI, nullptr); 510 511 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 512 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 513 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 514 EXPECT_EQ(ForkCI->getArgOperand(1), 515 ConstantInt::get(Type::getInt32Ty(Ctx), 1U)); 516 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 517 EXPECT_EQ(findStoredValue(ForkCI->getArgOperand(3)), F->arg_begin()); 518 } 519 520 TEST_F(OpenMPIRBuilderTest, ParallelNested) { 521 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 522 OpenMPIRBuilder OMPBuilder(*M); 523 OMPBuilder.initialize(); 524 F->setName("func"); 525 IRBuilder<> Builder(BB); 526 527 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 528 529 unsigned NumInnerBodiesGenerated = 0; 530 unsigned NumOuterBodiesGenerated = 0; 531 unsigned NumFinalizationPoints = 0; 532 533 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 534 BasicBlock &ContinuationIP) { 535 ++NumInnerBodiesGenerated; 536 }; 537 538 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 539 Value &Orig, Value &Inner, 540 Value *&ReplacementValue) -> InsertPointTy { 541 // Trivial copy (=firstprivate). 542 Builder.restoreIP(AllocaIP); 543 Type *VTy = Inner.getType()->getPointerElementType(); 544 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 545 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 546 Builder.restoreIP(CodeGenIP); 547 Builder.CreateStore(V, ReplacementValue); 548 return CodeGenIP; 549 }; 550 551 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 552 553 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 554 BasicBlock &ContinuationIP) { 555 ++NumOuterBodiesGenerated; 556 Builder.restoreIP(CodeGenIP); 557 BasicBlock *CGBB = CodeGenIP.getBlock(); 558 BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 559 CGBB->getTerminator()->eraseFromParent(); 560 ; 561 562 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel( 563 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 564 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 565 566 Builder.restoreIP(AfterIP); 567 Builder.CreateBr(NewBB); 568 }; 569 570 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 571 F->getEntryBlock().getFirstInsertionPt()); 572 IRBuilder<>::InsertPoint AfterIP = 573 OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 574 nullptr, nullptr, OMP_PROC_BIND_default, false); 575 576 EXPECT_EQ(NumInnerBodiesGenerated, 1U); 577 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 578 EXPECT_EQ(NumFinalizationPoints, 2U); 579 580 Builder.restoreIP(AfterIP); 581 Builder.CreateRetVoid(); 582 583 OMPBuilder.finalize(); 584 585 EXPECT_EQ(M->size(), 5U); 586 for (Function &OutlinedFn : *M) { 587 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 588 continue; 589 EXPECT_FALSE(verifyModule(*M, &errs())); 590 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 591 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 592 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 593 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 594 595 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 596 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 597 598 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 599 User *Usr = OutlinedFn.user_back(); 600 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 601 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 602 ASSERT_NE(ForkCI, nullptr); 603 604 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 605 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 606 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 607 EXPECT_EQ(ForkCI->getArgOperand(1), 608 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 609 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 610 } 611 } 612 613 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) { 614 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 615 OpenMPIRBuilder OMPBuilder(*M); 616 OMPBuilder.initialize(); 617 F->setName("func"); 618 IRBuilder<> Builder(BB); 619 620 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 621 622 unsigned NumInnerBodiesGenerated = 0; 623 unsigned NumOuterBodiesGenerated = 0; 624 unsigned NumFinalizationPoints = 0; 625 626 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 627 BasicBlock &ContinuationIP) { 628 ++NumInnerBodiesGenerated; 629 }; 630 631 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 632 Value &Orig, Value &Inner, 633 Value *&ReplacementValue) -> InsertPointTy { 634 // Trivial copy (=firstprivate). 635 Builder.restoreIP(AllocaIP); 636 Type *VTy = Inner.getType()->getPointerElementType(); 637 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 638 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 639 Builder.restoreIP(CodeGenIP); 640 Builder.CreateStore(V, ReplacementValue); 641 return CodeGenIP; 642 }; 643 644 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 645 646 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 647 BasicBlock &ContinuationIP) { 648 ++NumOuterBodiesGenerated; 649 Builder.restoreIP(CodeGenIP); 650 BasicBlock *CGBB = CodeGenIP.getBlock(); 651 BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 652 BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt()); 653 CGBB->getTerminator()->eraseFromParent(); 654 ; 655 NewBB1->getTerminator()->eraseFromParent(); 656 ; 657 658 IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel( 659 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 660 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 661 662 Builder.restoreIP(AfterIP1); 663 Builder.CreateBr(NewBB1); 664 665 IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel( 666 InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB, 667 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 668 669 Builder.restoreIP(AfterIP2); 670 Builder.CreateBr(NewBB2); 671 }; 672 673 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 674 F->getEntryBlock().getFirstInsertionPt()); 675 IRBuilder<>::InsertPoint AfterIP = 676 OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 677 nullptr, nullptr, OMP_PROC_BIND_default, false); 678 679 EXPECT_EQ(NumInnerBodiesGenerated, 2U); 680 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 681 EXPECT_EQ(NumFinalizationPoints, 3U); 682 683 Builder.restoreIP(AfterIP); 684 Builder.CreateRetVoid(); 685 686 OMPBuilder.finalize(); 687 688 EXPECT_EQ(M->size(), 6U); 689 for (Function &OutlinedFn : *M) { 690 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 691 continue; 692 EXPECT_FALSE(verifyModule(*M, &errs())); 693 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 694 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 695 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 696 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 697 698 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 699 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 700 701 unsigned NumAllocas = 0; 702 for (Instruction &I : instructions(OutlinedFn)) 703 NumAllocas += isa<AllocaInst>(I); 704 EXPECT_EQ(NumAllocas, 1U); 705 706 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 707 User *Usr = OutlinedFn.user_back(); 708 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 709 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 710 ASSERT_NE(ForkCI, nullptr); 711 712 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 713 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 714 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 715 EXPECT_EQ(ForkCI->getArgOperand(1), 716 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 717 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 718 } 719 } 720 721 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) { 722 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 723 OpenMPIRBuilder OMPBuilder(*M); 724 OMPBuilder.initialize(); 725 F->setName("func"); 726 IRBuilder<> Builder(BB); 727 728 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 729 730 AllocaInst *PrivAI = nullptr; 731 732 unsigned NumBodiesGenerated = 0; 733 unsigned NumPrivatizedVars = 0; 734 unsigned NumFinalizationPoints = 0; 735 736 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 737 BasicBlock &ContinuationIP) { 738 ++NumBodiesGenerated; 739 740 Builder.restoreIP(AllocaIP); 741 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 742 Builder.CreateStore(F->arg_begin(), PrivAI); 743 744 Builder.restoreIP(CodeGenIP); 745 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 746 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 747 Instruction *ThenTerm, *ElseTerm; 748 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 749 &ThenTerm, &ElseTerm); 750 751 Builder.SetInsertPoint(ThenTerm); 752 Builder.CreateBr(&ContinuationIP); 753 ThenTerm->eraseFromParent(); 754 }; 755 756 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 757 Value &Orig, Value &Inner, 758 Value *&ReplacementValue) -> InsertPointTy { 759 ++NumPrivatizedVars; 760 761 if (!isa<AllocaInst>(Orig)) { 762 EXPECT_EQ(&Orig, F->arg_begin()); 763 ReplacementValue = &Inner; 764 return CodeGenIP; 765 } 766 767 // Since the original value is an allocation, it has a pointer type and 768 // therefore no additional wrapping should happen. 769 EXPECT_EQ(&Orig, &Inner); 770 771 // Trivial copy (=firstprivate). 772 Builder.restoreIP(AllocaIP); 773 Type *VTy = Inner.getType()->getPointerElementType(); 774 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 775 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 776 Builder.restoreIP(CodeGenIP); 777 Builder.CreateStore(V, ReplacementValue); 778 return CodeGenIP; 779 }; 780 781 auto FiniCB = [&](InsertPointTy CodeGenIP) { 782 ++NumFinalizationPoints; 783 // No destructors. 784 }; 785 786 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 787 F->getEntryBlock().getFirstInsertionPt()); 788 IRBuilder<>::InsertPoint AfterIP = 789 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 790 Builder.CreateIsNotNull(F->arg_begin()), 791 nullptr, OMP_PROC_BIND_default, false); 792 793 EXPECT_EQ(NumBodiesGenerated, 1U); 794 EXPECT_EQ(NumPrivatizedVars, 1U); 795 EXPECT_EQ(NumFinalizationPoints, 1U); 796 797 Builder.restoreIP(AfterIP); 798 Builder.CreateRetVoid(); 799 OMPBuilder.finalize(); 800 801 EXPECT_NE(PrivAI, nullptr); 802 Function *OutlinedFn = PrivAI->getFunction(); 803 EXPECT_NE(F, OutlinedFn); 804 EXPECT_FALSE(verifyModule(*M, &errs())); 805 806 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 807 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 808 809 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 810 ASSERT_EQ(OutlinedFn->getNumUses(), 2U); 811 812 CallInst *DirectCI = nullptr; 813 CallInst *ForkCI = nullptr; 814 for (User *Usr : OutlinedFn->users()) { 815 if (isa<CallInst>(Usr)) { 816 ASSERT_EQ(DirectCI, nullptr); 817 DirectCI = cast<CallInst>(Usr); 818 } else { 819 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 820 ASSERT_EQ(Usr->getNumUses(), 1U); 821 ASSERT_TRUE(isa<CallInst>(Usr->user_back())); 822 ForkCI = cast<CallInst>(Usr->user_back()); 823 } 824 } 825 826 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 827 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 828 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 829 EXPECT_EQ(ForkCI->getArgOperand(1), 830 ConstantInt::get(Type::getInt32Ty(Ctx), 1)); 831 Value *StoredForkArg = findStoredValue(ForkCI->getArgOperand(3)); 832 EXPECT_EQ(StoredForkArg, F->arg_begin()); 833 834 EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn); 835 EXPECT_EQ(DirectCI->getNumArgOperands(), 3U); 836 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0))); 837 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1))); 838 Value *StoredDirectArg = findStoredValue(DirectCI->getArgOperand(2)); 839 EXPECT_EQ(StoredDirectArg, F->arg_begin()); 840 } 841 842 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) { 843 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 844 OpenMPIRBuilder OMPBuilder(*M); 845 OMPBuilder.initialize(); 846 F->setName("func"); 847 IRBuilder<> Builder(BB); 848 849 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 850 851 unsigned NumBodiesGenerated = 0; 852 unsigned NumPrivatizedVars = 0; 853 unsigned NumFinalizationPoints = 0; 854 855 CallInst *CheckedBarrier = nullptr; 856 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 857 BasicBlock &ContinuationIP) { 858 ++NumBodiesGenerated; 859 860 Builder.restoreIP(CodeGenIP); 861 862 // Create three barriers, two cancel barriers but only one checked. 863 Function *CBFn, *BFn; 864 865 Builder.restoreIP( 866 OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel)); 867 868 CBFn = M->getFunction("__kmpc_cancel_barrier"); 869 BFn = M->getFunction("__kmpc_barrier"); 870 ASSERT_NE(CBFn, nullptr); 871 ASSERT_EQ(BFn, nullptr); 872 ASSERT_EQ(CBFn->getNumUses(), 1U); 873 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 874 ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U); 875 CheckedBarrier = cast<CallInst>(CBFn->user_back()); 876 877 Builder.restoreIP( 878 OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true)); 879 CBFn = M->getFunction("__kmpc_cancel_barrier"); 880 BFn = M->getFunction("__kmpc_barrier"); 881 ASSERT_NE(CBFn, nullptr); 882 ASSERT_NE(BFn, nullptr); 883 ASSERT_EQ(CBFn->getNumUses(), 1U); 884 ASSERT_EQ(BFn->getNumUses(), 1U); 885 ASSERT_TRUE(isa<CallInst>(BFn->user_back())); 886 ASSERT_EQ(BFn->user_back()->getNumUses(), 0U); 887 888 Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, 889 false, false)); 890 ASSERT_EQ(CBFn->getNumUses(), 2U); 891 ASSERT_EQ(BFn->getNumUses(), 1U); 892 ASSERT_TRUE(CBFn->user_back() != CheckedBarrier); 893 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 894 ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U); 895 }; 896 897 auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &, 898 Value *&) -> InsertPointTy { 899 ++NumPrivatizedVars; 900 llvm_unreachable("No privatization callback call expected!"); 901 }; 902 903 FunctionType *FakeDestructorTy = 904 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, 905 /*isVarArg=*/false); 906 auto *FakeDestructor = Function::Create( 907 FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get()); 908 909 auto FiniCB = [&](InsertPointTy IP) { 910 ++NumFinalizationPoints; 911 Builder.restoreIP(IP); 912 Builder.CreateCall(FakeDestructor, 913 {Builder.getInt32(NumFinalizationPoints)}); 914 }; 915 916 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 917 F->getEntryBlock().getFirstInsertionPt()); 918 IRBuilder<>::InsertPoint AfterIP = 919 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 920 Builder.CreateIsNotNull(F->arg_begin()), 921 nullptr, OMP_PROC_BIND_default, true); 922 923 EXPECT_EQ(NumBodiesGenerated, 1U); 924 EXPECT_EQ(NumPrivatizedVars, 0U); 925 EXPECT_EQ(NumFinalizationPoints, 2U); 926 EXPECT_EQ(FakeDestructor->getNumUses(), 2U); 927 928 Builder.restoreIP(AfterIP); 929 Builder.CreateRetVoid(); 930 OMPBuilder.finalize(); 931 932 EXPECT_FALSE(verifyModule(*M, &errs())); 933 934 BasicBlock *ExitBB = nullptr; 935 for (const User *Usr : FakeDestructor->users()) { 936 const CallInst *CI = dyn_cast<CallInst>(Usr); 937 ASSERT_EQ(CI->getCalledFunction(), FakeDestructor); 938 ASSERT_TRUE(isa<BranchInst>(CI->getNextNode())); 939 ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U); 940 if (ExitBB) 941 ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB); 942 else 943 ExitBB = CI->getNextNode()->getSuccessor(0); 944 ASSERT_EQ(ExitBB->size(), 1U); 945 if (!isa<ReturnInst>(ExitBB->front())) { 946 ASSERT_TRUE(isa<BranchInst>(ExitBB->front())); 947 ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U); 948 ASSERT_TRUE(isa<ReturnInst>( 949 cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front())); 950 } 951 } 952 } 953 954 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) { 955 OpenMPIRBuilder OMPBuilder(*M); 956 OMPBuilder.initialize(); 957 F->setName("func"); 958 IRBuilder<> Builder(BB); 959 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 960 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 961 962 Type *I32Ty = Type::getInt32Ty(M->getContext()); 963 Type *I32PtrTy = Type::getInt32PtrTy(M->getContext()); 964 Type *StructTy = StructType::get(I32Ty, I32PtrTy); 965 Type *StructPtrTy = StructTy->getPointerTo(); 966 Type *VoidTy = Type::getVoidTy(M->getContext()); 967 FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty); 968 FunctionCallee TakeI32Func = 969 M->getOrInsertFunction("take_i32", VoidTy, I32Ty); 970 FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy); 971 FunctionCallee TakeI32PtrFunc = 972 M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy); 973 FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy); 974 FunctionCallee TakeStructFunc = 975 M->getOrInsertFunction("take_struct", VoidTy, StructTy); 976 FunctionCallee RetStructPtrFunc = 977 M->getOrInsertFunction("ret_structptr", StructPtrTy); 978 FunctionCallee TakeStructPtrFunc = 979 M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy); 980 Value *I32Val = Builder.CreateCall(RetI32Func); 981 Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc); 982 Value *StructVal = Builder.CreateCall(RetStructFunc); 983 Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc); 984 985 Instruction *Internal; 986 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 987 BasicBlock &ContinuationBB) { 988 IRBuilder<>::InsertPointGuard Guard(Builder); 989 Builder.restoreIP(CodeGenIP); 990 Internal = Builder.CreateCall(TakeI32Func, I32Val); 991 Builder.CreateCall(TakeI32PtrFunc, I32PtrVal); 992 Builder.CreateCall(TakeStructFunc, StructVal); 993 Builder.CreateCall(TakeStructPtrFunc, StructPtrVal); 994 }; 995 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &, 996 Value &Inner, Value *&ReplacementValue) { 997 ReplacementValue = &Inner; 998 return CodeGenIP; 999 }; 1000 auto FiniCB = [](InsertPointTy) {}; 1001 1002 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 1003 F->getEntryBlock().getFirstInsertionPt()); 1004 IRBuilder<>::InsertPoint AfterIP = 1005 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 1006 nullptr, nullptr, OMP_PROC_BIND_default, false); 1007 Builder.restoreIP(AfterIP); 1008 Builder.CreateRetVoid(); 1009 1010 OMPBuilder.finalize(); 1011 1012 EXPECT_FALSE(verifyModule(*M, &errs())); 1013 Function *OutlinedFn = Internal->getFunction(); 1014 1015 Type *Arg2Type = OutlinedFn->getArg(2)->getType(); 1016 EXPECT_TRUE(Arg2Type->isPointerTy()); 1017 EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty); 1018 1019 // Arguments that need to be passed through pointers and reloaded will get 1020 // used earlier in the functions and therefore will appear first in the 1021 // argument list after outlining. 1022 Type *Arg3Type = OutlinedFn->getArg(3)->getType(); 1023 EXPECT_TRUE(Arg3Type->isPointerTy()); 1024 EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy); 1025 1026 Type *Arg4Type = OutlinedFn->getArg(4)->getType(); 1027 EXPECT_EQ(Arg4Type, I32PtrTy); 1028 1029 Type *Arg5Type = OutlinedFn->getArg(5)->getType(); 1030 EXPECT_EQ(Arg5Type, StructPtrTy); 1031 } 1032 1033 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) { 1034 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1035 OpenMPIRBuilder OMPBuilder(*M); 1036 OMPBuilder.initialize(); 1037 IRBuilder<> Builder(BB); 1038 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1039 Value *TripCount = F->getArg(0); 1040 1041 unsigned NumBodiesGenerated = 0; 1042 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) { 1043 NumBodiesGenerated += 1; 1044 1045 Builder.restoreIP(CodeGenIP); 1046 1047 Value *Cmp = Builder.CreateICmpEQ(LC, TripCount); 1048 Instruction *ThenTerm, *ElseTerm; 1049 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 1050 &ThenTerm, &ElseTerm); 1051 }; 1052 1053 CanonicalLoopInfo *Loop = 1054 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount); 1055 1056 Builder.restoreIP(Loop->getAfterIP()); 1057 ReturnInst *RetInst = Builder.CreateRetVoid(); 1058 OMPBuilder.finalize(); 1059 1060 Loop->assertOK(); 1061 EXPECT_FALSE(verifyModule(*M, &errs())); 1062 1063 EXPECT_EQ(NumBodiesGenerated, 1U); 1064 1065 // Verify control flow structure (in addition to Loop->assertOK()). 1066 EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock()); 1067 EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock()); 1068 1069 Instruction *IndVar = Loop->getIndVar(); 1070 EXPECT_TRUE(isa<PHINode>(IndVar)); 1071 EXPECT_EQ(IndVar->getType(), TripCount->getType()); 1072 EXPECT_EQ(IndVar->getParent(), Loop->getHeader()); 1073 1074 EXPECT_EQ(Loop->getTripCount(), TripCount); 1075 1076 BasicBlock *Body = Loop->getBody(); 1077 Instruction *CmpInst = &Body->getInstList().front(); 1078 EXPECT_TRUE(isa<ICmpInst>(CmpInst)); 1079 EXPECT_EQ(CmpInst->getOperand(0), IndVar); 1080 1081 BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor(); 1082 EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) { 1083 return SuccBB->getSingleSuccessor() == LatchPred; 1084 })); 1085 1086 EXPECT_EQ(&Loop->getAfter()->front(), RetInst); 1087 } 1088 1089 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) { 1090 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1091 OpenMPIRBuilder OMPBuilder(*M); 1092 OMPBuilder.initialize(); 1093 IRBuilder<> Builder(BB); 1094 1095 // Check the trip count is computed correctly. We generate the canonical loop 1096 // but rely on the IRBuilder's constant folder to compute the final result 1097 // since all inputs are constant. To verify overflow situations, limit the 1098 // trip count / loop counter widths to 16 bits. 1099 auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step, 1100 bool IsSigned, bool InclusiveStop) -> int64_t { 1101 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1102 Type *LCTy = Type::getInt16Ty(Ctx); 1103 Value *StartVal = ConstantInt::get(LCTy, Start); 1104 Value *StopVal = ConstantInt::get(LCTy, Stop); 1105 Value *StepVal = ConstantInt::get(LCTy, Step); 1106 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {}; 1107 CanonicalLoopInfo *Loop = 1108 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal, 1109 StepVal, IsSigned, InclusiveStop); 1110 Loop->assertOK(); 1111 Builder.restoreIP(Loop->getAfterIP()); 1112 Value *TripCount = Loop->getTripCount(); 1113 return cast<ConstantInt>(TripCount)->getValue().getZExtValue(); 1114 }; 1115 1116 EXPECT_EQ(EvalTripCount(0, 0, 1, false, false), 0); 1117 EXPECT_EQ(EvalTripCount(0, 1, 2, false, false), 1); 1118 EXPECT_EQ(EvalTripCount(0, 42, 1, false, false), 42); 1119 EXPECT_EQ(EvalTripCount(0, 42, 2, false, false), 21); 1120 EXPECT_EQ(EvalTripCount(21, 42, 1, false, false), 21); 1121 EXPECT_EQ(EvalTripCount(0, 5, 5, false, false), 1); 1122 EXPECT_EQ(EvalTripCount(0, 9, 5, false, false), 2); 1123 EXPECT_EQ(EvalTripCount(0, 11, 5, false, false), 3); 1124 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF); 1125 EXPECT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0); 1126 EXPECT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1); 1127 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100); 1128 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1); 1129 1130 EXPECT_EQ(EvalTripCount(0, 6, 5, false, false), 2); 1131 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2); 1132 EXPECT_EQ(EvalTripCount(0, 0, 1, false, true), 1); 1133 EXPECT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1); 1134 EXPECT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF); 1135 EXPECT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000); 1136 1137 EXPECT_EQ(EvalTripCount(0, 0, -1, true, false), 0); 1138 EXPECT_EQ(EvalTripCount(0, 1, -1, true, true), 0); 1139 EXPECT_EQ(EvalTripCount(20, 5, -5, true, false), 3); 1140 EXPECT_EQ(EvalTripCount(20, 5, -5, true, true), 4); 1141 EXPECT_EQ(EvalTripCount(-4, -2, 2, true, false), 1); 1142 EXPECT_EQ(EvalTripCount(-4, -3, 2, true, false), 1); 1143 EXPECT_EQ(EvalTripCount(-4, -2, 2, true, true), 2); 1144 1145 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000); 1146 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001); 1147 EXPECT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF); 1148 EXPECT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF); 1149 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2); 1150 EXPECT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF); 1151 EXPECT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000); 1152 EXPECT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800); 1153 EXPECT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF); 1154 EXPECT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1); 1155 EXPECT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2); 1156 1157 // Finalize the function and verify it. 1158 Builder.CreateRetVoid(); 1159 OMPBuilder.finalize(); 1160 EXPECT_FALSE(verifyModule(*M, &errs())); 1161 } 1162 1163 TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) { 1164 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1165 OpenMPIRBuilder OMPBuilder(*M); 1166 OMPBuilder.initialize(); 1167 F->setName("func"); 1168 1169 IRBuilder<> Builder(BB); 1170 1171 Type *LCTy = F->getArg(0)->getType(); 1172 Constant *One = ConstantInt::get(LCTy, 1); 1173 Constant *Two = ConstantInt::get(LCTy, 2); 1174 Value *OuterTripCount = 1175 Builder.CreateAdd(F->getArg(0), Two, "tripcount.outer"); 1176 Value *InnerTripCount = 1177 Builder.CreateAdd(F->getArg(0), One, "tripcount.inner"); 1178 1179 // Fix an insertion point for ComputeIP. 1180 BasicBlock *LoopNextEnter = 1181 BasicBlock::Create(M->getContext(), "loopnest.enter", F, 1182 Builder.GetInsertBlock()->getNextNode()); 1183 BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter); 1184 InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()}; 1185 1186 Builder.SetInsertPoint(LoopNextEnter); 1187 OpenMPIRBuilder::LocationDescription OuterLoc(Builder.saveIP(), DL); 1188 1189 CanonicalLoopInfo *InnerLoop = nullptr; 1190 CallInst *InbetweenLead = nullptr; 1191 CallInst *InbetweenTrail = nullptr; 1192 CallInst *Call = nullptr; 1193 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, Value *OuterLC) { 1194 Builder.restoreIP(OuterCodeGenIP); 1195 InbetweenLead = 1196 createPrintfCall(Builder, "In-between lead i=%d\\n", {OuterLC}); 1197 1198 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1199 Value *InnerLC) { 1200 Builder.restoreIP(InnerCodeGenIP); 1201 Call = createPrintfCall(Builder, "body i=%d j=%d\\n", {OuterLC, InnerLC}); 1202 }; 1203 InnerLoop = OMPBuilder.createCanonicalLoop( 1204 Builder.saveIP(), InnerLoopBodyGenCB, InnerTripCount, "inner"); 1205 1206 Builder.restoreIP(InnerLoop->getAfterIP()); 1207 InbetweenTrail = 1208 createPrintfCall(Builder, "In-between trail i=%d\\n", {OuterLC}); 1209 }; 1210 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1211 OuterLoc, OuterLoopBodyGenCB, OuterTripCount, "outer"); 1212 1213 // Finish the function. 1214 Builder.restoreIP(OuterLoop->getAfterIP()); 1215 Builder.CreateRetVoid(); 1216 1217 CanonicalLoopInfo *Collapsed = 1218 OMPBuilder.collapseLoops(DL, {OuterLoop, InnerLoop}, ComputeIP); 1219 1220 OMPBuilder.finalize(); 1221 EXPECT_FALSE(verifyModule(*M, &errs())); 1222 1223 // Verify control flow and BB order. 1224 BasicBlock *RefOrder[] = { 1225 Collapsed->getPreheader(), Collapsed->getHeader(), 1226 Collapsed->getCond(), Collapsed->getBody(), 1227 InbetweenLead->getParent(), Call->getParent(), 1228 InbetweenTrail->getParent(), Collapsed->getLatch(), 1229 Collapsed->getExit(), Collapsed->getAfter(), 1230 }; 1231 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1232 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1233 1234 // Verify the total trip count. 1235 auto *TripCount = cast<MulOperator>(Collapsed->getTripCount()); 1236 EXPECT_EQ(TripCount->getOperand(0), OuterTripCount); 1237 EXPECT_EQ(TripCount->getOperand(1), InnerTripCount); 1238 1239 // Verify the changed indvar. 1240 auto *OuterIV = cast<BinaryOperator>(Call->getOperand(1)); 1241 EXPECT_EQ(OuterIV->getOpcode(), Instruction::UDiv); 1242 EXPECT_EQ(OuterIV->getParent(), Collapsed->getBody()); 1243 EXPECT_EQ(OuterIV->getOperand(1), InnerTripCount); 1244 EXPECT_EQ(OuterIV->getOperand(0), Collapsed->getIndVar()); 1245 1246 auto *InnerIV = cast<BinaryOperator>(Call->getOperand(2)); 1247 EXPECT_EQ(InnerIV->getOpcode(), Instruction::URem); 1248 EXPECT_EQ(InnerIV->getParent(), Collapsed->getBody()); 1249 EXPECT_EQ(InnerIV->getOperand(0), Collapsed->getIndVar()); 1250 EXPECT_EQ(InnerIV->getOperand(1), InnerTripCount); 1251 1252 EXPECT_EQ(InbetweenLead->getOperand(1), OuterIV); 1253 EXPECT_EQ(InbetweenTrail->getOperand(1), OuterIV); 1254 } 1255 1256 TEST_F(OpenMPIRBuilderTest, TileSingleLoop) { 1257 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1258 OpenMPIRBuilder OMPBuilder(*M); 1259 OMPBuilder.initialize(); 1260 F->setName("func"); 1261 1262 IRBuilder<> Builder(BB); 1263 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1264 Value *TripCount = F->getArg(0); 1265 1266 BasicBlock *BodyCode = nullptr; 1267 Instruction *Call = nullptr; 1268 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) { 1269 Builder.restoreIP(CodeGenIP); 1270 BodyCode = Builder.GetInsertBlock(); 1271 1272 // Add something that consumes the induction variable to the body. 1273 Call = createPrintfCall(Builder, "%d\\n", {LC}); 1274 }; 1275 CanonicalLoopInfo *Loop = 1276 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount); 1277 1278 // Finalize the function. 1279 Builder.restoreIP(Loop->getAfterIP()); 1280 Builder.CreateRetVoid(); 1281 1282 Instruction *OrigIndVar = Loop->getIndVar(); 1283 EXPECT_EQ(Call->getOperand(1), OrigIndVar); 1284 1285 // Tile the loop. 1286 Constant *TileSize = ConstantInt::get(Loop->getIndVarType(), APInt(32, 7)); 1287 std::vector<CanonicalLoopInfo *> GenLoops = 1288 OMPBuilder.tileLoops(DL, {Loop}, {TileSize}); 1289 1290 OMPBuilder.finalize(); 1291 EXPECT_FALSE(verifyModule(*M, &errs())); 1292 1293 EXPECT_EQ(GenLoops.size(), 2u); 1294 CanonicalLoopInfo *Floor = GenLoops[0]; 1295 CanonicalLoopInfo *Tile = GenLoops[1]; 1296 1297 BasicBlock *RefOrder[] = { 1298 Floor->getPreheader(), Floor->getHeader(), Floor->getCond(), 1299 Floor->getBody(), Tile->getPreheader(), Tile->getHeader(), 1300 Tile->getCond(), Tile->getBody(), BodyCode, 1301 Tile->getLatch(), Tile->getExit(), Tile->getAfter(), 1302 Floor->getLatch(), Floor->getExit(), Floor->getAfter(), 1303 }; 1304 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1305 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1306 1307 // Check the induction variable. 1308 EXPECT_EQ(Call->getParent(), BodyCode); 1309 auto *Shift = cast<AddOperator>(Call->getOperand(1)); 1310 EXPECT_EQ(cast<Instruction>(Shift)->getParent(), Tile->getBody()); 1311 EXPECT_EQ(Shift->getOperand(1), Tile->getIndVar()); 1312 auto *Scale = cast<MulOperator>(Shift->getOperand(0)); 1313 EXPECT_EQ(cast<Instruction>(Scale)->getParent(), Tile->getBody()); 1314 EXPECT_EQ(Scale->getOperand(0), TileSize); 1315 EXPECT_EQ(Scale->getOperand(1), Floor->getIndVar()); 1316 } 1317 1318 TEST_F(OpenMPIRBuilderTest, TileNestedLoops) { 1319 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1320 OpenMPIRBuilder OMPBuilder(*M); 1321 OMPBuilder.initialize(); 1322 F->setName("func"); 1323 1324 IRBuilder<> Builder(BB); 1325 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1326 Value *TripCount = F->getArg(0); 1327 Type *LCTy = TripCount->getType(); 1328 1329 BasicBlock *BodyCode = nullptr; 1330 CanonicalLoopInfo *InnerLoop = nullptr; 1331 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, 1332 llvm::Value *OuterLC) { 1333 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1334 llvm::Value *InnerLC) { 1335 Builder.restoreIP(InnerCodeGenIP); 1336 BodyCode = Builder.GetInsertBlock(); 1337 1338 // Add something that consumes the induction variables to the body. 1339 createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC}); 1340 }; 1341 InnerLoop = OMPBuilder.createCanonicalLoop( 1342 OuterCodeGenIP, InnerLoopBodyGenCB, TripCount, "inner"); 1343 }; 1344 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1345 Loc, OuterLoopBodyGenCB, TripCount, "outer"); 1346 1347 // Finalize the function. 1348 Builder.restoreIP(OuterLoop->getAfterIP()); 1349 Builder.CreateRetVoid(); 1350 1351 // Tile to loop nest. 1352 Constant *OuterTileSize = ConstantInt::get(LCTy, APInt(32, 11)); 1353 Constant *InnerTileSize = ConstantInt::get(LCTy, APInt(32, 7)); 1354 std::vector<CanonicalLoopInfo *> GenLoops = OMPBuilder.tileLoops( 1355 DL, {OuterLoop, InnerLoop}, {OuterTileSize, InnerTileSize}); 1356 1357 OMPBuilder.finalize(); 1358 EXPECT_FALSE(verifyModule(*M, &errs())); 1359 1360 EXPECT_EQ(GenLoops.size(), 4u); 1361 CanonicalLoopInfo *Floor1 = GenLoops[0]; 1362 CanonicalLoopInfo *Floor2 = GenLoops[1]; 1363 CanonicalLoopInfo *Tile1 = GenLoops[2]; 1364 CanonicalLoopInfo *Tile2 = GenLoops[3]; 1365 1366 BasicBlock *RefOrder[] = { 1367 Floor1->getPreheader(), 1368 Floor1->getHeader(), 1369 Floor1->getCond(), 1370 Floor1->getBody(), 1371 Floor2->getPreheader(), 1372 Floor2->getHeader(), 1373 Floor2->getCond(), 1374 Floor2->getBody(), 1375 Tile1->getPreheader(), 1376 Tile1->getHeader(), 1377 Tile1->getCond(), 1378 Tile1->getBody(), 1379 Tile2->getPreheader(), 1380 Tile2->getHeader(), 1381 Tile2->getCond(), 1382 Tile2->getBody(), 1383 BodyCode, 1384 Tile2->getLatch(), 1385 Tile2->getExit(), 1386 Tile2->getAfter(), 1387 Tile1->getLatch(), 1388 Tile1->getExit(), 1389 Tile1->getAfter(), 1390 Floor2->getLatch(), 1391 Floor2->getExit(), 1392 Floor2->getAfter(), 1393 Floor1->getLatch(), 1394 Floor1->getExit(), 1395 Floor1->getAfter(), 1396 }; 1397 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1398 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1399 } 1400 1401 TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) { 1402 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1403 OpenMPIRBuilder OMPBuilder(*M); 1404 OMPBuilder.initialize(); 1405 F->setName("func"); 1406 1407 IRBuilder<> Builder(BB); 1408 Value *TripCount = F->getArg(0); 1409 Type *LCTy = TripCount->getType(); 1410 1411 Value *OuterStartVal = ConstantInt::get(LCTy, 2); 1412 Value *OuterStopVal = TripCount; 1413 Value *OuterStep = ConstantInt::get(LCTy, 5); 1414 Value *InnerStartVal = ConstantInt::get(LCTy, 13); 1415 Value *InnerStopVal = TripCount; 1416 Value *InnerStep = ConstantInt::get(LCTy, 3); 1417 1418 // Fix an insertion point for ComputeIP. 1419 BasicBlock *LoopNextEnter = 1420 BasicBlock::Create(M->getContext(), "loopnest.enter", F, 1421 Builder.GetInsertBlock()->getNextNode()); 1422 BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter); 1423 InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()}; 1424 1425 InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()}; 1426 OpenMPIRBuilder::LocationDescription Loc({LoopIP, DL}); 1427 1428 BasicBlock *BodyCode = nullptr; 1429 CanonicalLoopInfo *InnerLoop = nullptr; 1430 CallInst *Call = nullptr; 1431 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, 1432 llvm::Value *OuterLC) { 1433 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1434 llvm::Value *InnerLC) { 1435 Builder.restoreIP(InnerCodeGenIP); 1436 BodyCode = Builder.GetInsertBlock(); 1437 1438 // Add something that consumes the induction variable to the body. 1439 Call = createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC}); 1440 }; 1441 InnerLoop = OMPBuilder.createCanonicalLoop( 1442 OuterCodeGenIP, InnerLoopBodyGenCB, InnerStartVal, InnerStopVal, 1443 InnerStep, false, false, ComputeIP, "inner"); 1444 }; 1445 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1446 Loc, OuterLoopBodyGenCB, OuterStartVal, OuterStopVal, OuterStep, false, 1447 false, ComputeIP, "outer"); 1448 1449 // Finalize the function 1450 Builder.restoreIP(OuterLoop->getAfterIP()); 1451 Builder.CreateRetVoid(); 1452 1453 // Tile the loop nest. 1454 Constant *TileSize0 = ConstantInt::get(LCTy, APInt(32, 11)); 1455 Constant *TileSize1 = ConstantInt::get(LCTy, APInt(32, 7)); 1456 std::vector<CanonicalLoopInfo *> GenLoops = 1457 OMPBuilder.tileLoops(DL, {OuterLoop, InnerLoop}, {TileSize0, TileSize1}); 1458 1459 OMPBuilder.finalize(); 1460 EXPECT_FALSE(verifyModule(*M, &errs())); 1461 1462 EXPECT_EQ(GenLoops.size(), 4u); 1463 CanonicalLoopInfo *Floor0 = GenLoops[0]; 1464 CanonicalLoopInfo *Floor1 = GenLoops[1]; 1465 CanonicalLoopInfo *Tile0 = GenLoops[2]; 1466 CanonicalLoopInfo *Tile1 = GenLoops[3]; 1467 1468 BasicBlock *RefOrder[] = { 1469 Floor0->getPreheader(), 1470 Floor0->getHeader(), 1471 Floor0->getCond(), 1472 Floor0->getBody(), 1473 Floor1->getPreheader(), 1474 Floor1->getHeader(), 1475 Floor1->getCond(), 1476 Floor1->getBody(), 1477 Tile0->getPreheader(), 1478 Tile0->getHeader(), 1479 Tile0->getCond(), 1480 Tile0->getBody(), 1481 Tile1->getPreheader(), 1482 Tile1->getHeader(), 1483 Tile1->getCond(), 1484 Tile1->getBody(), 1485 BodyCode, 1486 Tile1->getLatch(), 1487 Tile1->getExit(), 1488 Tile1->getAfter(), 1489 Tile0->getLatch(), 1490 Tile0->getExit(), 1491 Tile0->getAfter(), 1492 Floor1->getLatch(), 1493 Floor1->getExit(), 1494 Floor1->getAfter(), 1495 Floor0->getLatch(), 1496 Floor0->getExit(), 1497 Floor0->getAfter(), 1498 }; 1499 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1500 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1501 1502 EXPECT_EQ(Call->getParent(), BodyCode); 1503 1504 auto *RangeShift0 = cast<AddOperator>(Call->getOperand(1)); 1505 EXPECT_EQ(RangeShift0->getOperand(1), OuterStartVal); 1506 auto *RangeScale0 = cast<MulOperator>(RangeShift0->getOperand(0)); 1507 EXPECT_EQ(RangeScale0->getOperand(1), OuterStep); 1508 auto *TileShift0 = cast<AddOperator>(RangeScale0->getOperand(0)); 1509 EXPECT_EQ(cast<Instruction>(TileShift0)->getParent(), Tile1->getBody()); 1510 EXPECT_EQ(TileShift0->getOperand(1), Tile0->getIndVar()); 1511 auto *TileScale0 = cast<MulOperator>(TileShift0->getOperand(0)); 1512 EXPECT_EQ(cast<Instruction>(TileScale0)->getParent(), Tile1->getBody()); 1513 EXPECT_EQ(TileScale0->getOperand(0), TileSize0); 1514 EXPECT_EQ(TileScale0->getOperand(1), Floor0->getIndVar()); 1515 1516 auto *RangeShift1 = cast<AddOperator>(Call->getOperand(2)); 1517 EXPECT_EQ(cast<Instruction>(RangeShift1)->getParent(), BodyCode); 1518 EXPECT_EQ(RangeShift1->getOperand(1), InnerStartVal); 1519 auto *RangeScale1 = cast<MulOperator>(RangeShift1->getOperand(0)); 1520 EXPECT_EQ(cast<Instruction>(RangeScale1)->getParent(), BodyCode); 1521 EXPECT_EQ(RangeScale1->getOperand(1), InnerStep); 1522 auto *TileShift1 = cast<AddOperator>(RangeScale1->getOperand(0)); 1523 EXPECT_EQ(cast<Instruction>(TileShift1)->getParent(), Tile1->getBody()); 1524 EXPECT_EQ(TileShift1->getOperand(1), Tile1->getIndVar()); 1525 auto *TileScale1 = cast<MulOperator>(TileShift1->getOperand(0)); 1526 EXPECT_EQ(cast<Instruction>(TileScale1)->getParent(), Tile1->getBody()); 1527 EXPECT_EQ(TileScale1->getOperand(0), TileSize1); 1528 EXPECT_EQ(TileScale1->getOperand(1), Floor1->getIndVar()); 1529 } 1530 1531 TEST_F(OpenMPIRBuilderTest, TileSingleLoopCounts) { 1532 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1533 OpenMPIRBuilder OMPBuilder(*M); 1534 OMPBuilder.initialize(); 1535 IRBuilder<> Builder(BB); 1536 1537 // Create a loop, tile it, and extract its trip count. All input values are 1538 // constant and IRBuilder evaluates all-constant arithmetic inplace, such that 1539 // the floor trip count itself will be a ConstantInt. Unfortunately we cannot 1540 // do the same for the tile loop. 1541 auto GetFloorCount = [&](int64_t Start, int64_t Stop, int64_t Step, 1542 bool IsSigned, bool InclusiveStop, 1543 int64_t TileSize) -> uint64_t { 1544 OpenMPIRBuilder::LocationDescription Loc(Builder.saveIP(), DL); 1545 Type *LCTy = Type::getInt16Ty(Ctx); 1546 Value *StartVal = ConstantInt::get(LCTy, Start); 1547 Value *StopVal = ConstantInt::get(LCTy, Stop); 1548 Value *StepVal = ConstantInt::get(LCTy, Step); 1549 1550 // Generate a loop. 1551 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {}; 1552 CanonicalLoopInfo *Loop = 1553 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal, 1554 StepVal, IsSigned, InclusiveStop); 1555 1556 // Tile the loop. 1557 Value *TileSizeVal = ConstantInt::get(LCTy, TileSize); 1558 std::vector<CanonicalLoopInfo *> GenLoops = 1559 OMPBuilder.tileLoops(Loc.DL, {Loop}, {TileSizeVal}); 1560 1561 // Set the insertion pointer to after loop, where the next loop will be 1562 // emitted. 1563 Builder.restoreIP(Loop->getAfterIP()); 1564 1565 // Extract the trip count. 1566 CanonicalLoopInfo *FloorLoop = GenLoops[0]; 1567 Value *FloorTripCount = FloorLoop->getTripCount(); 1568 return cast<ConstantInt>(FloorTripCount)->getValue().getZExtValue(); 1569 }; 1570 1571 // Empty iteration domain. 1572 EXPECT_EQ(GetFloorCount(0, 0, 1, false, false, 7), 0u); 1573 EXPECT_EQ(GetFloorCount(0, -1, 1, false, true, 7), 0u); 1574 EXPECT_EQ(GetFloorCount(-1, -1, -1, true, false, 7), 0u); 1575 EXPECT_EQ(GetFloorCount(-1, 0, -1, true, true, 7), 0u); 1576 EXPECT_EQ(GetFloorCount(-1, -1, 3, true, false, 7), 0u); 1577 1578 // Only complete tiles. 1579 EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u); 1580 EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u); 1581 EXPECT_EQ(GetFloorCount(1, 15, 1, false, false, 7), 2u); 1582 EXPECT_EQ(GetFloorCount(0, -14, -1, true, false, 7), 2u); 1583 EXPECT_EQ(GetFloorCount(-1, -14, -1, true, true, 7), 2u); 1584 EXPECT_EQ(GetFloorCount(0, 3 * 7 * 2, 3, false, false, 7), 2u); 1585 1586 // Only a partial tile. 1587 EXPECT_EQ(GetFloorCount(0, 1, 1, false, false, 7), 1u); 1588 EXPECT_EQ(GetFloorCount(0, 6, 1, false, false, 7), 1u); 1589 EXPECT_EQ(GetFloorCount(-1, 1, 3, true, false, 7), 1u); 1590 EXPECT_EQ(GetFloorCount(-1, -2, -1, true, false, 7), 1u); 1591 EXPECT_EQ(GetFloorCount(0, 2, 3, false, false, 7), 1u); 1592 1593 // Complete and partial tiles. 1594 EXPECT_EQ(GetFloorCount(0, 13, 1, false, false, 7), 2u); 1595 EXPECT_EQ(GetFloorCount(0, 15, 1, false, false, 7), 3u); 1596 EXPECT_EQ(GetFloorCount(-1, -14, -1, true, false, 7), 2u); 1597 EXPECT_EQ(GetFloorCount(0, 3 * 7 * 5 - 1, 3, false, false, 7), 5u); 1598 EXPECT_EQ(GetFloorCount(-1, -3 * 7 * 5, -3, true, false, 7), 5u); 1599 1600 // Close to 16-bit integer range. 1601 EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 1), 0xFFFFu); 1602 EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 7), 0xFFFFu / 7 + 1); 1603 EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, true, 7), 0xFFFFu / 7 + 1); 1604 EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 7), 0xFFFFu / 7 + 1); 1605 EXPECT_EQ(GetFloorCount(-0x7FFF, 0x7FFF, 1, true, true, 7), 0xFFFFu / 7 + 1); 1606 EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, false, 0xFFFF), 1u); 1607 EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 0xFFFF), 1u); 1608 1609 // Finalize the function. 1610 Builder.CreateRetVoid(); 1611 OMPBuilder.finalize(); 1612 1613 EXPECT_FALSE(verifyModule(*M, &errs())); 1614 } 1615 1616 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) { 1617 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1618 OpenMPIRBuilder OMPBuilder(*M); 1619 OMPBuilder.initialize(); 1620 IRBuilder<> Builder(BB); 1621 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1622 1623 Type *LCTy = Type::getInt32Ty(Ctx); 1624 Value *StartVal = ConstantInt::get(LCTy, 10); 1625 Value *StopVal = ConstantInt::get(LCTy, 52); 1626 Value *StepVal = ConstantInt::get(LCTy, 2); 1627 auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {}; 1628 1629 CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop( 1630 Loc, LoopBodyGen, StartVal, StopVal, StepVal, 1631 /*IsSigned=*/false, /*InclusiveStop=*/false); 1632 1633 Builder.SetInsertPoint(BB, BB->getFirstInsertionPt()); 1634 InsertPointTy AllocaIP = Builder.saveIP(); 1635 1636 CLI = OMPBuilder.createStaticWorkshareLoop(Loc, CLI, AllocaIP, 1637 /*NeedsBarrier=*/true); 1638 auto AllocaIter = BB->begin(); 1639 ASSERT_GE(std::distance(BB->begin(), BB->end()), 4); 1640 AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1641 AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1642 AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1643 AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1644 EXPECT_NE(PLastIter, nullptr); 1645 EXPECT_NE(PLowerBound, nullptr); 1646 EXPECT_NE(PUpperBound, nullptr); 1647 EXPECT_NE(PStride, nullptr); 1648 1649 auto PreheaderIter = CLI->getPreheader()->begin(); 1650 ASSERT_GE( 1651 std::distance(CLI->getPreheader()->begin(), CLI->getPreheader()->end()), 1652 7); 1653 StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1654 StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1655 StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1656 ASSERT_NE(LowerBoundStore, nullptr); 1657 ASSERT_NE(UpperBoundStore, nullptr); 1658 ASSERT_NE(StrideStore, nullptr); 1659 1660 auto *OrigLowerBound = 1661 dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand()); 1662 auto *OrigUpperBound = 1663 dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand()); 1664 auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand()); 1665 ASSERT_NE(OrigLowerBound, nullptr); 1666 ASSERT_NE(OrigUpperBound, nullptr); 1667 ASSERT_NE(OrigStride, nullptr); 1668 EXPECT_EQ(OrigLowerBound->getValue(), 0); 1669 EXPECT_EQ(OrigUpperBound->getValue(), 20); 1670 EXPECT_EQ(OrigStride->getValue(), 1); 1671 1672 // Check that the loop IV is updated to account for the lower bound returned 1673 // by the OpenMP runtime call. 1674 BinaryOperator *Add = dyn_cast<BinaryOperator>(&CLI->getBody()->front()); 1675 EXPECT_EQ(Add->getOperand(0), CLI->getIndVar()); 1676 auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1)); 1677 ASSERT_NE(LoadedLowerBound, nullptr); 1678 EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound); 1679 1680 // Check that the trip count is updated to account for the lower and upper 1681 // bounds return by the OpenMP runtime call. 1682 auto *AddOne = dyn_cast<Instruction>(CLI->getTripCount()); 1683 ASSERT_NE(AddOne, nullptr); 1684 ASSERT_TRUE(AddOne->isBinaryOp()); 1685 auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1)); 1686 ASSERT_NE(One, nullptr); 1687 EXPECT_EQ(One->getValue(), 1); 1688 auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0)); 1689 ASSERT_NE(Difference, nullptr); 1690 ASSERT_TRUE(Difference->isBinaryOp()); 1691 EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound); 1692 auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0)); 1693 ASSERT_NE(LoadedUpperBound, nullptr); 1694 EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound); 1695 1696 // The original loop iterator should only be used in the condition, in the 1697 // increment and in the statement that adds the lower bound to it. 1698 Value *IV = CLI->getIndVar(); 1699 EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3); 1700 1701 // The exit block should contain the "fini" call and the barrier call, 1702 // plus the call to obtain the thread ID. 1703 BasicBlock *ExitBlock = CLI->getExit(); 1704 size_t NumCallsInExitBlock = 1705 count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); }); 1706 EXPECT_EQ(NumCallsInExitBlock, 3u); 1707 } 1708 1709 TEST_F(OpenMPIRBuilderTest, MasterDirective) { 1710 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1711 OpenMPIRBuilder OMPBuilder(*M); 1712 OMPBuilder.initialize(); 1713 F->setName("func"); 1714 IRBuilder<> Builder(BB); 1715 1716 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1717 1718 AllocaInst *PrivAI = nullptr; 1719 1720 BasicBlock *EntryBB = nullptr; 1721 BasicBlock *ExitBB = nullptr; 1722 BasicBlock *ThenBB = nullptr; 1723 1724 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1725 BasicBlock &FiniBB) { 1726 if (AllocaIP.isSet()) 1727 Builder.restoreIP(AllocaIP); 1728 else 1729 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 1730 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1731 Builder.CreateStore(F->arg_begin(), PrivAI); 1732 1733 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1734 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1735 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1736 1737 Builder.restoreIP(CodeGenIP); 1738 1739 // collect some info for checks later 1740 ExitBB = FiniBB.getUniqueSuccessor(); 1741 ThenBB = Builder.GetInsertBlock(); 1742 EntryBB = ThenBB->getUniquePredecessor(); 1743 1744 // simple instructions for body 1745 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 1746 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1747 }; 1748 1749 auto FiniCB = [&](InsertPointTy IP) { 1750 BasicBlock *IPBB = IP.getBlock(); 1751 EXPECT_NE(IPBB->end(), IP.getPoint()); 1752 }; 1753 1754 Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB)); 1755 Value *EntryBBTI = EntryBB->getTerminator(); 1756 EXPECT_NE(EntryBBTI, nullptr); 1757 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 1758 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 1759 EXPECT_TRUE(EntryBr->isConditional()); 1760 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 1761 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 1762 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 1763 1764 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 1765 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 1766 1767 CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0)); 1768 EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U); 1769 EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master"); 1770 EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0))); 1771 1772 CallInst *MasterEndCI = nullptr; 1773 for (auto &FI : *ThenBB) { 1774 Instruction *cur = &FI; 1775 if (isa<CallInst>(cur)) { 1776 MasterEndCI = cast<CallInst>(cur); 1777 if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master") 1778 break; 1779 MasterEndCI = nullptr; 1780 } 1781 } 1782 EXPECT_NE(MasterEndCI, nullptr); 1783 EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U); 1784 EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0))); 1785 EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1)); 1786 } 1787 1788 TEST_F(OpenMPIRBuilderTest, CriticalDirective) { 1789 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1790 OpenMPIRBuilder OMPBuilder(*M); 1791 OMPBuilder.initialize(); 1792 F->setName("func"); 1793 IRBuilder<> Builder(BB); 1794 1795 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1796 1797 AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1798 1799 BasicBlock *EntryBB = nullptr; 1800 1801 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1802 BasicBlock &FiniBB) { 1803 // collect some info for checks later 1804 EntryBB = FiniBB.getUniquePredecessor(); 1805 1806 // actual start for bodyCB 1807 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1808 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1809 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1810 EXPECT_EQ(EntryBB, CodeGenIPBB); 1811 1812 // body begin 1813 Builder.restoreIP(CodeGenIP); 1814 Builder.CreateStore(F->arg_begin(), PrivAI); 1815 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 1816 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1817 }; 1818 1819 auto FiniCB = [&](InsertPointTy IP) { 1820 BasicBlock *IPBB = IP.getBlock(); 1821 EXPECT_NE(IPBB->end(), IP.getPoint()); 1822 }; 1823 1824 Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB, 1825 "testCRT", nullptr)); 1826 1827 Value *EntryBBTI = EntryBB->getTerminator(); 1828 EXPECT_EQ(EntryBBTI, nullptr); 1829 1830 CallInst *CriticalEntryCI = nullptr; 1831 for (auto &EI : *EntryBB) { 1832 Instruction *cur = &EI; 1833 if (isa<CallInst>(cur)) { 1834 CriticalEntryCI = cast<CallInst>(cur); 1835 if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical") 1836 break; 1837 CriticalEntryCI = nullptr; 1838 } 1839 } 1840 EXPECT_NE(CriticalEntryCI, nullptr); 1841 EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U); 1842 EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical"); 1843 EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0))); 1844 1845 CallInst *CriticalEndCI = nullptr; 1846 for (auto &FI : *EntryBB) { 1847 Instruction *cur = &FI; 1848 if (isa<CallInst>(cur)) { 1849 CriticalEndCI = cast<CallInst>(cur); 1850 if (CriticalEndCI->getCalledFunction()->getName() == 1851 "__kmpc_end_critical") 1852 break; 1853 CriticalEndCI = nullptr; 1854 } 1855 } 1856 EXPECT_NE(CriticalEndCI, nullptr); 1857 EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U); 1858 EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0))); 1859 EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1)); 1860 PointerType *CriticalNamePtrTy = 1861 PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8)); 1862 EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2)); 1863 EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy); 1864 } 1865 1866 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) { 1867 OpenMPIRBuilder OMPBuilder(*M); 1868 OMPBuilder.initialize(); 1869 F->setName("func"); 1870 IRBuilder<> Builder(BB); 1871 1872 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1873 1874 IntegerType* Int32 = Type::getInt32Ty(M->getContext()); 1875 AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo()); 1876 AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo()); 1877 1878 BasicBlock *EntryBB = BB; 1879 1880 OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress, 1881 PrivAddress, Int32, /*BranchtoEnd*/ true); 1882 1883 BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator()); 1884 1885 EXPECT_NE(EntryBr, nullptr); 1886 EXPECT_TRUE(EntryBr->isConditional()); 1887 1888 BasicBlock* NotMasterBB = EntryBr->getSuccessor(0); 1889 BasicBlock* CopyinEnd = EntryBr->getSuccessor(1); 1890 CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition()); 1891 1892 EXPECT_NE(CMP, nullptr); 1893 EXPECT_NE(NotMasterBB, nullptr); 1894 EXPECT_NE(CopyinEnd, nullptr); 1895 1896 BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator()); 1897 EXPECT_NE(NotMasterBr, nullptr); 1898 EXPECT_FALSE(NotMasterBr->isConditional()); 1899 EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0)); 1900 } 1901 1902 TEST_F(OpenMPIRBuilderTest, SingleDirective) { 1903 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1904 OpenMPIRBuilder OMPBuilder(*M); 1905 OMPBuilder.initialize(); 1906 F->setName("func"); 1907 IRBuilder<> Builder(BB); 1908 1909 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1910 1911 AllocaInst *PrivAI = nullptr; 1912 1913 BasicBlock *EntryBB = nullptr; 1914 BasicBlock *ExitBB = nullptr; 1915 BasicBlock *ThenBB = nullptr; 1916 1917 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1918 BasicBlock &FiniBB) { 1919 if (AllocaIP.isSet()) 1920 Builder.restoreIP(AllocaIP); 1921 else 1922 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 1923 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1924 Builder.CreateStore(F->arg_begin(), PrivAI); 1925 1926 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1927 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1928 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1929 1930 Builder.restoreIP(CodeGenIP); 1931 1932 // collect some info for checks later 1933 ExitBB = FiniBB.getUniqueSuccessor(); 1934 ThenBB = Builder.GetInsertBlock(); 1935 EntryBB = ThenBB->getUniquePredecessor(); 1936 1937 // simple instructions for body 1938 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use"); 1939 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1940 }; 1941 1942 auto FiniCB = [&](InsertPointTy IP) { 1943 BasicBlock *IPBB = IP.getBlock(); 1944 EXPECT_NE(IPBB->end(), IP.getPoint()); 1945 }; 1946 1947 Builder.restoreIP( 1948 OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr)); 1949 Value *EntryBBTI = EntryBB->getTerminator(); 1950 EXPECT_NE(EntryBBTI, nullptr); 1951 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 1952 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 1953 EXPECT_TRUE(EntryBr->isConditional()); 1954 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 1955 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 1956 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 1957 1958 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 1959 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 1960 1961 CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0)); 1962 EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U); 1963 EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single"); 1964 EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0))); 1965 1966 CallInst *SingleEndCI = nullptr; 1967 for (auto &FI : *ThenBB) { 1968 Instruction *cur = &FI; 1969 if (isa<CallInst>(cur)) { 1970 SingleEndCI = cast<CallInst>(cur); 1971 if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single") 1972 break; 1973 SingleEndCI = nullptr; 1974 } 1975 } 1976 EXPECT_NE(SingleEndCI, nullptr); 1977 EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U); 1978 EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0))); 1979 EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1)); 1980 } 1981 1982 } // namespace 1983