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->getAllocatedType(), PrivAI, 441 "local.use"); 442 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 443 Instruction *ThenTerm, *ElseTerm; 444 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 445 &ThenTerm, &ElseTerm); 446 447 Builder.SetInsertPoint(ThenTerm); 448 Builder.CreateBr(&ContinuationIP); 449 ThenTerm->eraseFromParent(); 450 }; 451 452 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 453 Value &Orig, Value &Inner, 454 Value *&ReplacementValue) -> InsertPointTy { 455 ++NumPrivatizedVars; 456 457 if (!isa<AllocaInst>(Orig)) { 458 EXPECT_EQ(&Orig, F->arg_begin()); 459 ReplacementValue = &Inner; 460 return CodeGenIP; 461 } 462 463 // Since the original value is an allocation, it has a pointer type and 464 // therefore no additional wrapping should happen. 465 EXPECT_EQ(&Orig, &Inner); 466 467 // Trivial copy (=firstprivate). 468 Builder.restoreIP(AllocaIP); 469 Type *VTy = Inner.getType()->getPointerElementType(); 470 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 471 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 472 Builder.restoreIP(CodeGenIP); 473 Builder.CreateStore(V, ReplacementValue); 474 return CodeGenIP; 475 }; 476 477 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 478 479 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 480 F->getEntryBlock().getFirstInsertionPt()); 481 IRBuilder<>::InsertPoint AfterIP = 482 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 483 nullptr, nullptr, OMP_PROC_BIND_default, false); 484 EXPECT_EQ(NumBodiesGenerated, 1U); 485 EXPECT_EQ(NumPrivatizedVars, 1U); 486 EXPECT_EQ(NumFinalizationPoints, 1U); 487 488 Builder.restoreIP(AfterIP); 489 Builder.CreateRetVoid(); 490 491 OMPBuilder.finalize(); 492 493 EXPECT_NE(PrivAI, nullptr); 494 Function *OutlinedFn = PrivAI->getFunction(); 495 EXPECT_NE(F, OutlinedFn); 496 EXPECT_FALSE(verifyModule(*M, &errs())); 497 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind)); 498 EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse)); 499 EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias)); 500 EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias)); 501 502 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 503 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 504 505 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 506 EXPECT_EQ(OutlinedFn->getNumUses(), 1U); 507 User *Usr = OutlinedFn->user_back(); 508 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 509 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 510 ASSERT_NE(ForkCI, nullptr); 511 512 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 513 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 514 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 515 EXPECT_EQ(ForkCI->getArgOperand(1), 516 ConstantInt::get(Type::getInt32Ty(Ctx), 1U)); 517 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 518 EXPECT_EQ(findStoredValue(ForkCI->getArgOperand(3)), F->arg_begin()); 519 } 520 521 TEST_F(OpenMPIRBuilderTest, ParallelNested) { 522 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 523 OpenMPIRBuilder OMPBuilder(*M); 524 OMPBuilder.initialize(); 525 F->setName("func"); 526 IRBuilder<> Builder(BB); 527 528 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 529 530 unsigned NumInnerBodiesGenerated = 0; 531 unsigned NumOuterBodiesGenerated = 0; 532 unsigned NumFinalizationPoints = 0; 533 534 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 535 BasicBlock &ContinuationIP) { 536 ++NumInnerBodiesGenerated; 537 }; 538 539 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 540 Value &Orig, Value &Inner, 541 Value *&ReplacementValue) -> InsertPointTy { 542 // Trivial copy (=firstprivate). 543 Builder.restoreIP(AllocaIP); 544 Type *VTy = Inner.getType()->getPointerElementType(); 545 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 546 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 547 Builder.restoreIP(CodeGenIP); 548 Builder.CreateStore(V, ReplacementValue); 549 return CodeGenIP; 550 }; 551 552 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 553 554 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 555 BasicBlock &ContinuationIP) { 556 ++NumOuterBodiesGenerated; 557 Builder.restoreIP(CodeGenIP); 558 BasicBlock *CGBB = CodeGenIP.getBlock(); 559 BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 560 CGBB->getTerminator()->eraseFromParent(); 561 ; 562 563 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel( 564 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 565 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 566 567 Builder.restoreIP(AfterIP); 568 Builder.CreateBr(NewBB); 569 }; 570 571 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 572 F->getEntryBlock().getFirstInsertionPt()); 573 IRBuilder<>::InsertPoint AfterIP = 574 OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 575 nullptr, nullptr, OMP_PROC_BIND_default, false); 576 577 EXPECT_EQ(NumInnerBodiesGenerated, 1U); 578 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 579 EXPECT_EQ(NumFinalizationPoints, 2U); 580 581 Builder.restoreIP(AfterIP); 582 Builder.CreateRetVoid(); 583 584 OMPBuilder.finalize(); 585 586 EXPECT_EQ(M->size(), 5U); 587 for (Function &OutlinedFn : *M) { 588 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 589 continue; 590 EXPECT_FALSE(verifyModule(*M, &errs())); 591 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 592 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 593 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 594 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 595 596 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 597 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 598 599 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 600 User *Usr = OutlinedFn.user_back(); 601 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 602 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 603 ASSERT_NE(ForkCI, nullptr); 604 605 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 606 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 607 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 608 EXPECT_EQ(ForkCI->getArgOperand(1), 609 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 610 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 611 } 612 } 613 614 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) { 615 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 616 OpenMPIRBuilder OMPBuilder(*M); 617 OMPBuilder.initialize(); 618 F->setName("func"); 619 IRBuilder<> Builder(BB); 620 621 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 622 623 unsigned NumInnerBodiesGenerated = 0; 624 unsigned NumOuterBodiesGenerated = 0; 625 unsigned NumFinalizationPoints = 0; 626 627 auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 628 BasicBlock &ContinuationIP) { 629 ++NumInnerBodiesGenerated; 630 }; 631 632 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 633 Value &Orig, Value &Inner, 634 Value *&ReplacementValue) -> InsertPointTy { 635 // Trivial copy (=firstprivate). 636 Builder.restoreIP(AllocaIP); 637 Type *VTy = Inner.getType()->getPointerElementType(); 638 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 639 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 640 Builder.restoreIP(CodeGenIP); 641 Builder.CreateStore(V, ReplacementValue); 642 return CodeGenIP; 643 }; 644 645 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; }; 646 647 auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 648 BasicBlock &ContinuationIP) { 649 ++NumOuterBodiesGenerated; 650 Builder.restoreIP(CodeGenIP); 651 BasicBlock *CGBB = CodeGenIP.getBlock(); 652 BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint()); 653 BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt()); 654 CGBB->getTerminator()->eraseFromParent(); 655 ; 656 NewBB1->getTerminator()->eraseFromParent(); 657 ; 658 659 IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel( 660 InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB, 661 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 662 663 Builder.restoreIP(AfterIP1); 664 Builder.CreateBr(NewBB1); 665 666 IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel( 667 InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB, 668 FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false); 669 670 Builder.restoreIP(AfterIP2); 671 Builder.CreateBr(NewBB2); 672 }; 673 674 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 675 F->getEntryBlock().getFirstInsertionPt()); 676 IRBuilder<>::InsertPoint AfterIP = 677 OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB, 678 nullptr, nullptr, OMP_PROC_BIND_default, false); 679 680 EXPECT_EQ(NumInnerBodiesGenerated, 2U); 681 EXPECT_EQ(NumOuterBodiesGenerated, 1U); 682 EXPECT_EQ(NumFinalizationPoints, 3U); 683 684 Builder.restoreIP(AfterIP); 685 Builder.CreateRetVoid(); 686 687 OMPBuilder.finalize(); 688 689 EXPECT_EQ(M->size(), 6U); 690 for (Function &OutlinedFn : *M) { 691 if (F == &OutlinedFn || OutlinedFn.isDeclaration()) 692 continue; 693 EXPECT_FALSE(verifyModule(*M, &errs())); 694 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind)); 695 EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse)); 696 EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias)); 697 EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias)); 698 699 EXPECT_TRUE(OutlinedFn.hasInternalLinkage()); 700 EXPECT_EQ(OutlinedFn.arg_size(), 2U); 701 702 unsigned NumAllocas = 0; 703 for (Instruction &I : instructions(OutlinedFn)) 704 NumAllocas += isa<AllocaInst>(I); 705 EXPECT_EQ(NumAllocas, 1U); 706 707 EXPECT_EQ(OutlinedFn.getNumUses(), 1U); 708 User *Usr = OutlinedFn.user_back(); 709 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 710 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back()); 711 ASSERT_NE(ForkCI, nullptr); 712 713 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 714 EXPECT_EQ(ForkCI->getNumArgOperands(), 3U); 715 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 716 EXPECT_EQ(ForkCI->getArgOperand(1), 717 ConstantInt::get(Type::getInt32Ty(Ctx), 0U)); 718 EXPECT_EQ(ForkCI->getArgOperand(2), Usr); 719 } 720 } 721 722 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) { 723 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 724 OpenMPIRBuilder OMPBuilder(*M); 725 OMPBuilder.initialize(); 726 F->setName("func"); 727 IRBuilder<> Builder(BB); 728 729 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 730 731 AllocaInst *PrivAI = nullptr; 732 733 unsigned NumBodiesGenerated = 0; 734 unsigned NumPrivatizedVars = 0; 735 unsigned NumFinalizationPoints = 0; 736 737 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 738 BasicBlock &ContinuationIP) { 739 ++NumBodiesGenerated; 740 741 Builder.restoreIP(AllocaIP); 742 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 743 Builder.CreateStore(F->arg_begin(), PrivAI); 744 745 Builder.restoreIP(CodeGenIP); 746 Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, 747 "local.use"); 748 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 749 Instruction *ThenTerm, *ElseTerm; 750 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 751 &ThenTerm, &ElseTerm); 752 753 Builder.SetInsertPoint(ThenTerm); 754 Builder.CreateBr(&ContinuationIP); 755 ThenTerm->eraseFromParent(); 756 }; 757 758 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 759 Value &Orig, Value &Inner, 760 Value *&ReplacementValue) -> InsertPointTy { 761 ++NumPrivatizedVars; 762 763 if (!isa<AllocaInst>(Orig)) { 764 EXPECT_EQ(&Orig, F->arg_begin()); 765 ReplacementValue = &Inner; 766 return CodeGenIP; 767 } 768 769 // Since the original value is an allocation, it has a pointer type and 770 // therefore no additional wrapping should happen. 771 EXPECT_EQ(&Orig, &Inner); 772 773 // Trivial copy (=firstprivate). 774 Builder.restoreIP(AllocaIP); 775 Type *VTy = Inner.getType()->getPointerElementType(); 776 Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload"); 777 ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy"); 778 Builder.restoreIP(CodeGenIP); 779 Builder.CreateStore(V, ReplacementValue); 780 return CodeGenIP; 781 }; 782 783 auto FiniCB = [&](InsertPointTy CodeGenIP) { 784 ++NumFinalizationPoints; 785 // No destructors. 786 }; 787 788 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 789 F->getEntryBlock().getFirstInsertionPt()); 790 IRBuilder<>::InsertPoint AfterIP = 791 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 792 Builder.CreateIsNotNull(F->arg_begin()), 793 nullptr, OMP_PROC_BIND_default, false); 794 795 EXPECT_EQ(NumBodiesGenerated, 1U); 796 EXPECT_EQ(NumPrivatizedVars, 1U); 797 EXPECT_EQ(NumFinalizationPoints, 1U); 798 799 Builder.restoreIP(AfterIP); 800 Builder.CreateRetVoid(); 801 OMPBuilder.finalize(); 802 803 EXPECT_NE(PrivAI, nullptr); 804 Function *OutlinedFn = PrivAI->getFunction(); 805 EXPECT_NE(F, OutlinedFn); 806 EXPECT_FALSE(verifyModule(*M, &errs())); 807 808 EXPECT_TRUE(OutlinedFn->hasInternalLinkage()); 809 EXPECT_EQ(OutlinedFn->arg_size(), 3U); 810 811 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent()); 812 ASSERT_EQ(OutlinedFn->getNumUses(), 2U); 813 814 CallInst *DirectCI = nullptr; 815 CallInst *ForkCI = nullptr; 816 for (User *Usr : OutlinedFn->users()) { 817 if (isa<CallInst>(Usr)) { 818 ASSERT_EQ(DirectCI, nullptr); 819 DirectCI = cast<CallInst>(Usr); 820 } else { 821 ASSERT_TRUE(isa<ConstantExpr>(Usr)); 822 ASSERT_EQ(Usr->getNumUses(), 1U); 823 ASSERT_TRUE(isa<CallInst>(Usr->user_back())); 824 ForkCI = cast<CallInst>(Usr->user_back()); 825 } 826 } 827 828 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call"); 829 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U); 830 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0))); 831 EXPECT_EQ(ForkCI->getArgOperand(1), 832 ConstantInt::get(Type::getInt32Ty(Ctx), 1)); 833 Value *StoredForkArg = findStoredValue(ForkCI->getArgOperand(3)); 834 EXPECT_EQ(StoredForkArg, F->arg_begin()); 835 836 EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn); 837 EXPECT_EQ(DirectCI->getNumArgOperands(), 3U); 838 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0))); 839 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1))); 840 Value *StoredDirectArg = findStoredValue(DirectCI->getArgOperand(2)); 841 EXPECT_EQ(StoredDirectArg, F->arg_begin()); 842 } 843 844 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) { 845 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 846 OpenMPIRBuilder OMPBuilder(*M); 847 OMPBuilder.initialize(); 848 F->setName("func"); 849 IRBuilder<> Builder(BB); 850 851 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 852 853 unsigned NumBodiesGenerated = 0; 854 unsigned NumPrivatizedVars = 0; 855 unsigned NumFinalizationPoints = 0; 856 857 CallInst *CheckedBarrier = nullptr; 858 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 859 BasicBlock &ContinuationIP) { 860 ++NumBodiesGenerated; 861 862 Builder.restoreIP(CodeGenIP); 863 864 // Create three barriers, two cancel barriers but only one checked. 865 Function *CBFn, *BFn; 866 867 Builder.restoreIP( 868 OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel)); 869 870 CBFn = M->getFunction("__kmpc_cancel_barrier"); 871 BFn = M->getFunction("__kmpc_barrier"); 872 ASSERT_NE(CBFn, nullptr); 873 ASSERT_EQ(BFn, nullptr); 874 ASSERT_EQ(CBFn->getNumUses(), 1U); 875 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 876 ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U); 877 CheckedBarrier = cast<CallInst>(CBFn->user_back()); 878 879 Builder.restoreIP( 880 OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true)); 881 CBFn = M->getFunction("__kmpc_cancel_barrier"); 882 BFn = M->getFunction("__kmpc_barrier"); 883 ASSERT_NE(CBFn, nullptr); 884 ASSERT_NE(BFn, nullptr); 885 ASSERT_EQ(CBFn->getNumUses(), 1U); 886 ASSERT_EQ(BFn->getNumUses(), 1U); 887 ASSERT_TRUE(isa<CallInst>(BFn->user_back())); 888 ASSERT_EQ(BFn->user_back()->getNumUses(), 0U); 889 890 Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, 891 false, false)); 892 ASSERT_EQ(CBFn->getNumUses(), 2U); 893 ASSERT_EQ(BFn->getNumUses(), 1U); 894 ASSERT_TRUE(CBFn->user_back() != CheckedBarrier); 895 ASSERT_TRUE(isa<CallInst>(CBFn->user_back())); 896 ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U); 897 }; 898 899 auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &, 900 Value *&) -> InsertPointTy { 901 ++NumPrivatizedVars; 902 llvm_unreachable("No privatization callback call expected!"); 903 }; 904 905 FunctionType *FakeDestructorTy = 906 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, 907 /*isVarArg=*/false); 908 auto *FakeDestructor = Function::Create( 909 FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get()); 910 911 auto FiniCB = [&](InsertPointTy IP) { 912 ++NumFinalizationPoints; 913 Builder.restoreIP(IP); 914 Builder.CreateCall(FakeDestructor, 915 {Builder.getInt32(NumFinalizationPoints)}); 916 }; 917 918 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 919 F->getEntryBlock().getFirstInsertionPt()); 920 IRBuilder<>::InsertPoint AfterIP = 921 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 922 Builder.CreateIsNotNull(F->arg_begin()), 923 nullptr, OMP_PROC_BIND_default, true); 924 925 EXPECT_EQ(NumBodiesGenerated, 1U); 926 EXPECT_EQ(NumPrivatizedVars, 0U); 927 EXPECT_EQ(NumFinalizationPoints, 2U); 928 EXPECT_EQ(FakeDestructor->getNumUses(), 2U); 929 930 Builder.restoreIP(AfterIP); 931 Builder.CreateRetVoid(); 932 OMPBuilder.finalize(); 933 934 EXPECT_FALSE(verifyModule(*M, &errs())); 935 936 BasicBlock *ExitBB = nullptr; 937 for (const User *Usr : FakeDestructor->users()) { 938 const CallInst *CI = dyn_cast<CallInst>(Usr); 939 ASSERT_EQ(CI->getCalledFunction(), FakeDestructor); 940 ASSERT_TRUE(isa<BranchInst>(CI->getNextNode())); 941 ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U); 942 if (ExitBB) 943 ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB); 944 else 945 ExitBB = CI->getNextNode()->getSuccessor(0); 946 ASSERT_EQ(ExitBB->size(), 1U); 947 if (!isa<ReturnInst>(ExitBB->front())) { 948 ASSERT_TRUE(isa<BranchInst>(ExitBB->front())); 949 ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U); 950 ASSERT_TRUE(isa<ReturnInst>( 951 cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front())); 952 } 953 } 954 } 955 956 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) { 957 OpenMPIRBuilder OMPBuilder(*M); 958 OMPBuilder.initialize(); 959 F->setName("func"); 960 IRBuilder<> Builder(BB); 961 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 962 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 963 964 Type *I32Ty = Type::getInt32Ty(M->getContext()); 965 Type *I32PtrTy = Type::getInt32PtrTy(M->getContext()); 966 Type *StructTy = StructType::get(I32Ty, I32PtrTy); 967 Type *StructPtrTy = StructTy->getPointerTo(); 968 Type *VoidTy = Type::getVoidTy(M->getContext()); 969 FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty); 970 FunctionCallee TakeI32Func = 971 M->getOrInsertFunction("take_i32", VoidTy, I32Ty); 972 FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy); 973 FunctionCallee TakeI32PtrFunc = 974 M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy); 975 FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy); 976 FunctionCallee TakeStructFunc = 977 M->getOrInsertFunction("take_struct", VoidTy, StructTy); 978 FunctionCallee RetStructPtrFunc = 979 M->getOrInsertFunction("ret_structptr", StructPtrTy); 980 FunctionCallee TakeStructPtrFunc = 981 M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy); 982 Value *I32Val = Builder.CreateCall(RetI32Func); 983 Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc); 984 Value *StructVal = Builder.CreateCall(RetStructFunc); 985 Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc); 986 987 Instruction *Internal; 988 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 989 BasicBlock &ContinuationBB) { 990 IRBuilder<>::InsertPointGuard Guard(Builder); 991 Builder.restoreIP(CodeGenIP); 992 Internal = Builder.CreateCall(TakeI32Func, I32Val); 993 Builder.CreateCall(TakeI32PtrFunc, I32PtrVal); 994 Builder.CreateCall(TakeStructFunc, StructVal); 995 Builder.CreateCall(TakeStructPtrFunc, StructPtrVal); 996 }; 997 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &, 998 Value &Inner, Value *&ReplacementValue) { 999 ReplacementValue = &Inner; 1000 return CodeGenIP; 1001 }; 1002 auto FiniCB = [](InsertPointTy) {}; 1003 1004 IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(), 1005 F->getEntryBlock().getFirstInsertionPt()); 1006 IRBuilder<>::InsertPoint AfterIP = 1007 OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB, 1008 nullptr, nullptr, OMP_PROC_BIND_default, false); 1009 Builder.restoreIP(AfterIP); 1010 Builder.CreateRetVoid(); 1011 1012 OMPBuilder.finalize(); 1013 1014 EXPECT_FALSE(verifyModule(*M, &errs())); 1015 Function *OutlinedFn = Internal->getFunction(); 1016 1017 Type *Arg2Type = OutlinedFn->getArg(2)->getType(); 1018 EXPECT_TRUE(Arg2Type->isPointerTy()); 1019 EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty); 1020 1021 // Arguments that need to be passed through pointers and reloaded will get 1022 // used earlier in the functions and therefore will appear first in the 1023 // argument list after outlining. 1024 Type *Arg3Type = OutlinedFn->getArg(3)->getType(); 1025 EXPECT_TRUE(Arg3Type->isPointerTy()); 1026 EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy); 1027 1028 Type *Arg4Type = OutlinedFn->getArg(4)->getType(); 1029 EXPECT_EQ(Arg4Type, I32PtrTy); 1030 1031 Type *Arg5Type = OutlinedFn->getArg(5)->getType(); 1032 EXPECT_EQ(Arg5Type, StructPtrTy); 1033 } 1034 1035 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) { 1036 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1037 OpenMPIRBuilder OMPBuilder(*M); 1038 OMPBuilder.initialize(); 1039 IRBuilder<> Builder(BB); 1040 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1041 Value *TripCount = F->getArg(0); 1042 1043 unsigned NumBodiesGenerated = 0; 1044 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) { 1045 NumBodiesGenerated += 1; 1046 1047 Builder.restoreIP(CodeGenIP); 1048 1049 Value *Cmp = Builder.CreateICmpEQ(LC, TripCount); 1050 Instruction *ThenTerm, *ElseTerm; 1051 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(), 1052 &ThenTerm, &ElseTerm); 1053 }; 1054 1055 CanonicalLoopInfo *Loop = 1056 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount); 1057 1058 Builder.restoreIP(Loop->getAfterIP()); 1059 ReturnInst *RetInst = Builder.CreateRetVoid(); 1060 OMPBuilder.finalize(); 1061 1062 Loop->assertOK(); 1063 EXPECT_FALSE(verifyModule(*M, &errs())); 1064 1065 EXPECT_EQ(NumBodiesGenerated, 1U); 1066 1067 // Verify control flow structure (in addition to Loop->assertOK()). 1068 EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock()); 1069 EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock()); 1070 1071 Instruction *IndVar = Loop->getIndVar(); 1072 EXPECT_TRUE(isa<PHINode>(IndVar)); 1073 EXPECT_EQ(IndVar->getType(), TripCount->getType()); 1074 EXPECT_EQ(IndVar->getParent(), Loop->getHeader()); 1075 1076 EXPECT_EQ(Loop->getTripCount(), TripCount); 1077 1078 BasicBlock *Body = Loop->getBody(); 1079 Instruction *CmpInst = &Body->getInstList().front(); 1080 EXPECT_TRUE(isa<ICmpInst>(CmpInst)); 1081 EXPECT_EQ(CmpInst->getOperand(0), IndVar); 1082 1083 BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor(); 1084 EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) { 1085 return SuccBB->getSingleSuccessor() == LatchPred; 1086 })); 1087 1088 EXPECT_EQ(&Loop->getAfter()->front(), RetInst); 1089 } 1090 1091 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) { 1092 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1093 OpenMPIRBuilder OMPBuilder(*M); 1094 OMPBuilder.initialize(); 1095 IRBuilder<> Builder(BB); 1096 1097 // Check the trip count is computed correctly. We generate the canonical loop 1098 // but rely on the IRBuilder's constant folder to compute the final result 1099 // since all inputs are constant. To verify overflow situations, limit the 1100 // trip count / loop counter widths to 16 bits. 1101 auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step, 1102 bool IsSigned, bool InclusiveStop) -> int64_t { 1103 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1104 Type *LCTy = Type::getInt16Ty(Ctx); 1105 Value *StartVal = ConstantInt::get(LCTy, Start); 1106 Value *StopVal = ConstantInt::get(LCTy, Stop); 1107 Value *StepVal = ConstantInt::get(LCTy, Step); 1108 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {}; 1109 CanonicalLoopInfo *Loop = 1110 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal, 1111 StepVal, IsSigned, InclusiveStop); 1112 Loop->assertOK(); 1113 Builder.restoreIP(Loop->getAfterIP()); 1114 Value *TripCount = Loop->getTripCount(); 1115 return cast<ConstantInt>(TripCount)->getValue().getZExtValue(); 1116 }; 1117 1118 EXPECT_EQ(EvalTripCount(0, 0, 1, false, false), 0); 1119 EXPECT_EQ(EvalTripCount(0, 1, 2, false, false), 1); 1120 EXPECT_EQ(EvalTripCount(0, 42, 1, false, false), 42); 1121 EXPECT_EQ(EvalTripCount(0, 42, 2, false, false), 21); 1122 EXPECT_EQ(EvalTripCount(21, 42, 1, false, false), 21); 1123 EXPECT_EQ(EvalTripCount(0, 5, 5, false, false), 1); 1124 EXPECT_EQ(EvalTripCount(0, 9, 5, false, false), 2); 1125 EXPECT_EQ(EvalTripCount(0, 11, 5, false, false), 3); 1126 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF); 1127 EXPECT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0); 1128 EXPECT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1); 1129 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100); 1130 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1); 1131 1132 EXPECT_EQ(EvalTripCount(0, 6, 5, false, false), 2); 1133 EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2); 1134 EXPECT_EQ(EvalTripCount(0, 0, 1, false, true), 1); 1135 EXPECT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1); 1136 EXPECT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF); 1137 EXPECT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000); 1138 1139 EXPECT_EQ(EvalTripCount(0, 0, -1, true, false), 0); 1140 EXPECT_EQ(EvalTripCount(0, 1, -1, true, true), 0); 1141 EXPECT_EQ(EvalTripCount(20, 5, -5, true, false), 3); 1142 EXPECT_EQ(EvalTripCount(20, 5, -5, true, true), 4); 1143 EXPECT_EQ(EvalTripCount(-4, -2, 2, true, false), 1); 1144 EXPECT_EQ(EvalTripCount(-4, -3, 2, true, false), 1); 1145 EXPECT_EQ(EvalTripCount(-4, -2, 2, true, true), 2); 1146 1147 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000); 1148 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001); 1149 EXPECT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF); 1150 EXPECT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF); 1151 EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2); 1152 EXPECT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF); 1153 EXPECT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000); 1154 EXPECT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800); 1155 EXPECT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF); 1156 EXPECT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1); 1157 EXPECT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2); 1158 1159 // Finalize the function and verify it. 1160 Builder.CreateRetVoid(); 1161 OMPBuilder.finalize(); 1162 EXPECT_FALSE(verifyModule(*M, &errs())); 1163 } 1164 1165 TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) { 1166 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1167 OpenMPIRBuilder OMPBuilder(*M); 1168 OMPBuilder.initialize(); 1169 F->setName("func"); 1170 1171 IRBuilder<> Builder(BB); 1172 1173 Type *LCTy = F->getArg(0)->getType(); 1174 Constant *One = ConstantInt::get(LCTy, 1); 1175 Constant *Two = ConstantInt::get(LCTy, 2); 1176 Value *OuterTripCount = 1177 Builder.CreateAdd(F->getArg(0), Two, "tripcount.outer"); 1178 Value *InnerTripCount = 1179 Builder.CreateAdd(F->getArg(0), One, "tripcount.inner"); 1180 1181 // Fix an insertion point for ComputeIP. 1182 BasicBlock *LoopNextEnter = 1183 BasicBlock::Create(M->getContext(), "loopnest.enter", F, 1184 Builder.GetInsertBlock()->getNextNode()); 1185 BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter); 1186 InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()}; 1187 1188 Builder.SetInsertPoint(LoopNextEnter); 1189 OpenMPIRBuilder::LocationDescription OuterLoc(Builder.saveIP(), DL); 1190 1191 CanonicalLoopInfo *InnerLoop = nullptr; 1192 CallInst *InbetweenLead = nullptr; 1193 CallInst *InbetweenTrail = nullptr; 1194 CallInst *Call = nullptr; 1195 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, Value *OuterLC) { 1196 Builder.restoreIP(OuterCodeGenIP); 1197 InbetweenLead = 1198 createPrintfCall(Builder, "In-between lead i=%d\\n", {OuterLC}); 1199 1200 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1201 Value *InnerLC) { 1202 Builder.restoreIP(InnerCodeGenIP); 1203 Call = createPrintfCall(Builder, "body i=%d j=%d\\n", {OuterLC, InnerLC}); 1204 }; 1205 InnerLoop = OMPBuilder.createCanonicalLoop( 1206 Builder.saveIP(), InnerLoopBodyGenCB, InnerTripCount, "inner"); 1207 1208 Builder.restoreIP(InnerLoop->getAfterIP()); 1209 InbetweenTrail = 1210 createPrintfCall(Builder, "In-between trail i=%d\\n", {OuterLC}); 1211 }; 1212 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1213 OuterLoc, OuterLoopBodyGenCB, OuterTripCount, "outer"); 1214 1215 // Finish the function. 1216 Builder.restoreIP(OuterLoop->getAfterIP()); 1217 Builder.CreateRetVoid(); 1218 1219 CanonicalLoopInfo *Collapsed = 1220 OMPBuilder.collapseLoops(DL, {OuterLoop, InnerLoop}, ComputeIP); 1221 1222 OMPBuilder.finalize(); 1223 EXPECT_FALSE(verifyModule(*M, &errs())); 1224 1225 // Verify control flow and BB order. 1226 BasicBlock *RefOrder[] = { 1227 Collapsed->getPreheader(), Collapsed->getHeader(), 1228 Collapsed->getCond(), Collapsed->getBody(), 1229 InbetweenLead->getParent(), Call->getParent(), 1230 InbetweenTrail->getParent(), Collapsed->getLatch(), 1231 Collapsed->getExit(), Collapsed->getAfter(), 1232 }; 1233 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1234 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1235 1236 // Verify the total trip count. 1237 auto *TripCount = cast<MulOperator>(Collapsed->getTripCount()); 1238 EXPECT_EQ(TripCount->getOperand(0), OuterTripCount); 1239 EXPECT_EQ(TripCount->getOperand(1), InnerTripCount); 1240 1241 // Verify the changed indvar. 1242 auto *OuterIV = cast<BinaryOperator>(Call->getOperand(1)); 1243 EXPECT_EQ(OuterIV->getOpcode(), Instruction::UDiv); 1244 EXPECT_EQ(OuterIV->getParent(), Collapsed->getBody()); 1245 EXPECT_EQ(OuterIV->getOperand(1), InnerTripCount); 1246 EXPECT_EQ(OuterIV->getOperand(0), Collapsed->getIndVar()); 1247 1248 auto *InnerIV = cast<BinaryOperator>(Call->getOperand(2)); 1249 EXPECT_EQ(InnerIV->getOpcode(), Instruction::URem); 1250 EXPECT_EQ(InnerIV->getParent(), Collapsed->getBody()); 1251 EXPECT_EQ(InnerIV->getOperand(0), Collapsed->getIndVar()); 1252 EXPECT_EQ(InnerIV->getOperand(1), InnerTripCount); 1253 1254 EXPECT_EQ(InbetweenLead->getOperand(1), OuterIV); 1255 EXPECT_EQ(InbetweenTrail->getOperand(1), OuterIV); 1256 } 1257 1258 TEST_F(OpenMPIRBuilderTest, TileSingleLoop) { 1259 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1260 OpenMPIRBuilder OMPBuilder(*M); 1261 OMPBuilder.initialize(); 1262 F->setName("func"); 1263 1264 IRBuilder<> Builder(BB); 1265 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1266 Value *TripCount = F->getArg(0); 1267 1268 BasicBlock *BodyCode = nullptr; 1269 Instruction *Call = nullptr; 1270 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) { 1271 Builder.restoreIP(CodeGenIP); 1272 BodyCode = Builder.GetInsertBlock(); 1273 1274 // Add something that consumes the induction variable to the body. 1275 Call = createPrintfCall(Builder, "%d\\n", {LC}); 1276 }; 1277 CanonicalLoopInfo *Loop = 1278 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount); 1279 1280 // Finalize the function. 1281 Builder.restoreIP(Loop->getAfterIP()); 1282 Builder.CreateRetVoid(); 1283 1284 Instruction *OrigIndVar = Loop->getIndVar(); 1285 EXPECT_EQ(Call->getOperand(1), OrigIndVar); 1286 1287 // Tile the loop. 1288 Constant *TileSize = ConstantInt::get(Loop->getIndVarType(), APInt(32, 7)); 1289 std::vector<CanonicalLoopInfo *> GenLoops = 1290 OMPBuilder.tileLoops(DL, {Loop}, {TileSize}); 1291 1292 OMPBuilder.finalize(); 1293 EXPECT_FALSE(verifyModule(*M, &errs())); 1294 1295 EXPECT_EQ(GenLoops.size(), 2u); 1296 CanonicalLoopInfo *Floor = GenLoops[0]; 1297 CanonicalLoopInfo *Tile = GenLoops[1]; 1298 1299 BasicBlock *RefOrder[] = { 1300 Floor->getPreheader(), Floor->getHeader(), Floor->getCond(), 1301 Floor->getBody(), Tile->getPreheader(), Tile->getHeader(), 1302 Tile->getCond(), Tile->getBody(), BodyCode, 1303 Tile->getLatch(), Tile->getExit(), Tile->getAfter(), 1304 Floor->getLatch(), Floor->getExit(), Floor->getAfter(), 1305 }; 1306 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1307 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1308 1309 // Check the induction variable. 1310 EXPECT_EQ(Call->getParent(), BodyCode); 1311 auto *Shift = cast<AddOperator>(Call->getOperand(1)); 1312 EXPECT_EQ(cast<Instruction>(Shift)->getParent(), Tile->getBody()); 1313 EXPECT_EQ(Shift->getOperand(1), Tile->getIndVar()); 1314 auto *Scale = cast<MulOperator>(Shift->getOperand(0)); 1315 EXPECT_EQ(cast<Instruction>(Scale)->getParent(), Tile->getBody()); 1316 EXPECT_EQ(Scale->getOperand(0), TileSize); 1317 EXPECT_EQ(Scale->getOperand(1), Floor->getIndVar()); 1318 } 1319 1320 TEST_F(OpenMPIRBuilderTest, TileNestedLoops) { 1321 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1322 OpenMPIRBuilder OMPBuilder(*M); 1323 OMPBuilder.initialize(); 1324 F->setName("func"); 1325 1326 IRBuilder<> Builder(BB); 1327 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1328 Value *TripCount = F->getArg(0); 1329 Type *LCTy = TripCount->getType(); 1330 1331 BasicBlock *BodyCode = nullptr; 1332 CanonicalLoopInfo *InnerLoop = nullptr; 1333 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, 1334 llvm::Value *OuterLC) { 1335 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1336 llvm::Value *InnerLC) { 1337 Builder.restoreIP(InnerCodeGenIP); 1338 BodyCode = Builder.GetInsertBlock(); 1339 1340 // Add something that consumes the induction variables to the body. 1341 createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC}); 1342 }; 1343 InnerLoop = OMPBuilder.createCanonicalLoop( 1344 OuterCodeGenIP, InnerLoopBodyGenCB, TripCount, "inner"); 1345 }; 1346 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1347 Loc, OuterLoopBodyGenCB, TripCount, "outer"); 1348 1349 // Finalize the function. 1350 Builder.restoreIP(OuterLoop->getAfterIP()); 1351 Builder.CreateRetVoid(); 1352 1353 // Tile to loop nest. 1354 Constant *OuterTileSize = ConstantInt::get(LCTy, APInt(32, 11)); 1355 Constant *InnerTileSize = ConstantInt::get(LCTy, APInt(32, 7)); 1356 std::vector<CanonicalLoopInfo *> GenLoops = OMPBuilder.tileLoops( 1357 DL, {OuterLoop, InnerLoop}, {OuterTileSize, InnerTileSize}); 1358 1359 OMPBuilder.finalize(); 1360 EXPECT_FALSE(verifyModule(*M, &errs())); 1361 1362 EXPECT_EQ(GenLoops.size(), 4u); 1363 CanonicalLoopInfo *Floor1 = GenLoops[0]; 1364 CanonicalLoopInfo *Floor2 = GenLoops[1]; 1365 CanonicalLoopInfo *Tile1 = GenLoops[2]; 1366 CanonicalLoopInfo *Tile2 = GenLoops[3]; 1367 1368 BasicBlock *RefOrder[] = { 1369 Floor1->getPreheader(), 1370 Floor1->getHeader(), 1371 Floor1->getCond(), 1372 Floor1->getBody(), 1373 Floor2->getPreheader(), 1374 Floor2->getHeader(), 1375 Floor2->getCond(), 1376 Floor2->getBody(), 1377 Tile1->getPreheader(), 1378 Tile1->getHeader(), 1379 Tile1->getCond(), 1380 Tile1->getBody(), 1381 Tile2->getPreheader(), 1382 Tile2->getHeader(), 1383 Tile2->getCond(), 1384 Tile2->getBody(), 1385 BodyCode, 1386 Tile2->getLatch(), 1387 Tile2->getExit(), 1388 Tile2->getAfter(), 1389 Tile1->getLatch(), 1390 Tile1->getExit(), 1391 Tile1->getAfter(), 1392 Floor2->getLatch(), 1393 Floor2->getExit(), 1394 Floor2->getAfter(), 1395 Floor1->getLatch(), 1396 Floor1->getExit(), 1397 Floor1->getAfter(), 1398 }; 1399 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1400 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1401 } 1402 1403 TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) { 1404 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1405 OpenMPIRBuilder OMPBuilder(*M); 1406 OMPBuilder.initialize(); 1407 F->setName("func"); 1408 1409 IRBuilder<> Builder(BB); 1410 Value *TripCount = F->getArg(0); 1411 Type *LCTy = TripCount->getType(); 1412 1413 Value *OuterStartVal = ConstantInt::get(LCTy, 2); 1414 Value *OuterStopVal = TripCount; 1415 Value *OuterStep = ConstantInt::get(LCTy, 5); 1416 Value *InnerStartVal = ConstantInt::get(LCTy, 13); 1417 Value *InnerStopVal = TripCount; 1418 Value *InnerStep = ConstantInt::get(LCTy, 3); 1419 1420 // Fix an insertion point for ComputeIP. 1421 BasicBlock *LoopNextEnter = 1422 BasicBlock::Create(M->getContext(), "loopnest.enter", F, 1423 Builder.GetInsertBlock()->getNextNode()); 1424 BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter); 1425 InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()}; 1426 1427 InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()}; 1428 OpenMPIRBuilder::LocationDescription Loc({LoopIP, DL}); 1429 1430 BasicBlock *BodyCode = nullptr; 1431 CanonicalLoopInfo *InnerLoop = nullptr; 1432 CallInst *Call = nullptr; 1433 auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, 1434 llvm::Value *OuterLC) { 1435 auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP, 1436 llvm::Value *InnerLC) { 1437 Builder.restoreIP(InnerCodeGenIP); 1438 BodyCode = Builder.GetInsertBlock(); 1439 1440 // Add something that consumes the induction variable to the body. 1441 Call = createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC}); 1442 }; 1443 InnerLoop = OMPBuilder.createCanonicalLoop( 1444 OuterCodeGenIP, InnerLoopBodyGenCB, InnerStartVal, InnerStopVal, 1445 InnerStep, false, false, ComputeIP, "inner"); 1446 }; 1447 CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop( 1448 Loc, OuterLoopBodyGenCB, OuterStartVal, OuterStopVal, OuterStep, false, 1449 false, ComputeIP, "outer"); 1450 1451 // Finalize the function 1452 Builder.restoreIP(OuterLoop->getAfterIP()); 1453 Builder.CreateRetVoid(); 1454 1455 // Tile the loop nest. 1456 Constant *TileSize0 = ConstantInt::get(LCTy, APInt(32, 11)); 1457 Constant *TileSize1 = ConstantInt::get(LCTy, APInt(32, 7)); 1458 std::vector<CanonicalLoopInfo *> GenLoops = 1459 OMPBuilder.tileLoops(DL, {OuterLoop, InnerLoop}, {TileSize0, TileSize1}); 1460 1461 OMPBuilder.finalize(); 1462 EXPECT_FALSE(verifyModule(*M, &errs())); 1463 1464 EXPECT_EQ(GenLoops.size(), 4u); 1465 CanonicalLoopInfo *Floor0 = GenLoops[0]; 1466 CanonicalLoopInfo *Floor1 = GenLoops[1]; 1467 CanonicalLoopInfo *Tile0 = GenLoops[2]; 1468 CanonicalLoopInfo *Tile1 = GenLoops[3]; 1469 1470 BasicBlock *RefOrder[] = { 1471 Floor0->getPreheader(), 1472 Floor0->getHeader(), 1473 Floor0->getCond(), 1474 Floor0->getBody(), 1475 Floor1->getPreheader(), 1476 Floor1->getHeader(), 1477 Floor1->getCond(), 1478 Floor1->getBody(), 1479 Tile0->getPreheader(), 1480 Tile0->getHeader(), 1481 Tile0->getCond(), 1482 Tile0->getBody(), 1483 Tile1->getPreheader(), 1484 Tile1->getHeader(), 1485 Tile1->getCond(), 1486 Tile1->getBody(), 1487 BodyCode, 1488 Tile1->getLatch(), 1489 Tile1->getExit(), 1490 Tile1->getAfter(), 1491 Tile0->getLatch(), 1492 Tile0->getExit(), 1493 Tile0->getAfter(), 1494 Floor1->getLatch(), 1495 Floor1->getExit(), 1496 Floor1->getAfter(), 1497 Floor0->getLatch(), 1498 Floor0->getExit(), 1499 Floor0->getAfter(), 1500 }; 1501 EXPECT_TRUE(verifyDFSOrder(F, RefOrder)); 1502 EXPECT_TRUE(verifyListOrder(F, RefOrder)); 1503 1504 EXPECT_EQ(Call->getParent(), BodyCode); 1505 1506 auto *RangeShift0 = cast<AddOperator>(Call->getOperand(1)); 1507 EXPECT_EQ(RangeShift0->getOperand(1), OuterStartVal); 1508 auto *RangeScale0 = cast<MulOperator>(RangeShift0->getOperand(0)); 1509 EXPECT_EQ(RangeScale0->getOperand(1), OuterStep); 1510 auto *TileShift0 = cast<AddOperator>(RangeScale0->getOperand(0)); 1511 EXPECT_EQ(cast<Instruction>(TileShift0)->getParent(), Tile1->getBody()); 1512 EXPECT_EQ(TileShift0->getOperand(1), Tile0->getIndVar()); 1513 auto *TileScale0 = cast<MulOperator>(TileShift0->getOperand(0)); 1514 EXPECT_EQ(cast<Instruction>(TileScale0)->getParent(), Tile1->getBody()); 1515 EXPECT_EQ(TileScale0->getOperand(0), TileSize0); 1516 EXPECT_EQ(TileScale0->getOperand(1), Floor0->getIndVar()); 1517 1518 auto *RangeShift1 = cast<AddOperator>(Call->getOperand(2)); 1519 EXPECT_EQ(cast<Instruction>(RangeShift1)->getParent(), BodyCode); 1520 EXPECT_EQ(RangeShift1->getOperand(1), InnerStartVal); 1521 auto *RangeScale1 = cast<MulOperator>(RangeShift1->getOperand(0)); 1522 EXPECT_EQ(cast<Instruction>(RangeScale1)->getParent(), BodyCode); 1523 EXPECT_EQ(RangeScale1->getOperand(1), InnerStep); 1524 auto *TileShift1 = cast<AddOperator>(RangeScale1->getOperand(0)); 1525 EXPECT_EQ(cast<Instruction>(TileShift1)->getParent(), Tile1->getBody()); 1526 EXPECT_EQ(TileShift1->getOperand(1), Tile1->getIndVar()); 1527 auto *TileScale1 = cast<MulOperator>(TileShift1->getOperand(0)); 1528 EXPECT_EQ(cast<Instruction>(TileScale1)->getParent(), Tile1->getBody()); 1529 EXPECT_EQ(TileScale1->getOperand(0), TileSize1); 1530 EXPECT_EQ(TileScale1->getOperand(1), Floor1->getIndVar()); 1531 } 1532 1533 TEST_F(OpenMPIRBuilderTest, TileSingleLoopCounts) { 1534 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1535 OpenMPIRBuilder OMPBuilder(*M); 1536 OMPBuilder.initialize(); 1537 IRBuilder<> Builder(BB); 1538 1539 // Create a loop, tile it, and extract its trip count. All input values are 1540 // constant and IRBuilder evaluates all-constant arithmetic inplace, such that 1541 // the floor trip count itself will be a ConstantInt. Unfortunately we cannot 1542 // do the same for the tile loop. 1543 auto GetFloorCount = [&](int64_t Start, int64_t Stop, int64_t Step, 1544 bool IsSigned, bool InclusiveStop, 1545 int64_t TileSize) -> uint64_t { 1546 OpenMPIRBuilder::LocationDescription Loc(Builder.saveIP(), DL); 1547 Type *LCTy = Type::getInt16Ty(Ctx); 1548 Value *StartVal = ConstantInt::get(LCTy, Start); 1549 Value *StopVal = ConstantInt::get(LCTy, Stop); 1550 Value *StepVal = ConstantInt::get(LCTy, Step); 1551 1552 // Generate a loop. 1553 auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {}; 1554 CanonicalLoopInfo *Loop = 1555 OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal, 1556 StepVal, IsSigned, InclusiveStop); 1557 1558 // Tile the loop. 1559 Value *TileSizeVal = ConstantInt::get(LCTy, TileSize); 1560 std::vector<CanonicalLoopInfo *> GenLoops = 1561 OMPBuilder.tileLoops(Loc.DL, {Loop}, {TileSizeVal}); 1562 1563 // Set the insertion pointer to after loop, where the next loop will be 1564 // emitted. 1565 Builder.restoreIP(Loop->getAfterIP()); 1566 1567 // Extract the trip count. 1568 CanonicalLoopInfo *FloorLoop = GenLoops[0]; 1569 Value *FloorTripCount = FloorLoop->getTripCount(); 1570 return cast<ConstantInt>(FloorTripCount)->getValue().getZExtValue(); 1571 }; 1572 1573 // Empty iteration domain. 1574 EXPECT_EQ(GetFloorCount(0, 0, 1, false, false, 7), 0u); 1575 EXPECT_EQ(GetFloorCount(0, -1, 1, false, true, 7), 0u); 1576 EXPECT_EQ(GetFloorCount(-1, -1, -1, true, false, 7), 0u); 1577 EXPECT_EQ(GetFloorCount(-1, 0, -1, true, true, 7), 0u); 1578 EXPECT_EQ(GetFloorCount(-1, -1, 3, true, false, 7), 0u); 1579 1580 // Only complete tiles. 1581 EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u); 1582 EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u); 1583 EXPECT_EQ(GetFloorCount(1, 15, 1, false, false, 7), 2u); 1584 EXPECT_EQ(GetFloorCount(0, -14, -1, true, false, 7), 2u); 1585 EXPECT_EQ(GetFloorCount(-1, -14, -1, true, true, 7), 2u); 1586 EXPECT_EQ(GetFloorCount(0, 3 * 7 * 2, 3, false, false, 7), 2u); 1587 1588 // Only a partial tile. 1589 EXPECT_EQ(GetFloorCount(0, 1, 1, false, false, 7), 1u); 1590 EXPECT_EQ(GetFloorCount(0, 6, 1, false, false, 7), 1u); 1591 EXPECT_EQ(GetFloorCount(-1, 1, 3, true, false, 7), 1u); 1592 EXPECT_EQ(GetFloorCount(-1, -2, -1, true, false, 7), 1u); 1593 EXPECT_EQ(GetFloorCount(0, 2, 3, false, false, 7), 1u); 1594 1595 // Complete and partial tiles. 1596 EXPECT_EQ(GetFloorCount(0, 13, 1, false, false, 7), 2u); 1597 EXPECT_EQ(GetFloorCount(0, 15, 1, false, false, 7), 3u); 1598 EXPECT_EQ(GetFloorCount(-1, -14, -1, true, false, 7), 2u); 1599 EXPECT_EQ(GetFloorCount(0, 3 * 7 * 5 - 1, 3, false, false, 7), 5u); 1600 EXPECT_EQ(GetFloorCount(-1, -3 * 7 * 5, -3, true, false, 7), 5u); 1601 1602 // Close to 16-bit integer range. 1603 EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 1), 0xFFFFu); 1604 EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 7), 0xFFFFu / 7 + 1); 1605 EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, true, 7), 0xFFFFu / 7 + 1); 1606 EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 7), 0xFFFFu / 7 + 1); 1607 EXPECT_EQ(GetFloorCount(-0x7FFF, 0x7FFF, 1, true, true, 7), 0xFFFFu / 7 + 1); 1608 EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, false, 0xFFFF), 1u); 1609 EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 0xFFFF), 1u); 1610 1611 // Finalize the function. 1612 Builder.CreateRetVoid(); 1613 OMPBuilder.finalize(); 1614 1615 EXPECT_FALSE(verifyModule(*M, &errs())); 1616 } 1617 1618 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) { 1619 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1620 OpenMPIRBuilder OMPBuilder(*M); 1621 OMPBuilder.initialize(); 1622 IRBuilder<> Builder(BB); 1623 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1624 1625 Type *LCTy = Type::getInt32Ty(Ctx); 1626 Value *StartVal = ConstantInt::get(LCTy, 10); 1627 Value *StopVal = ConstantInt::get(LCTy, 52); 1628 Value *StepVal = ConstantInt::get(LCTy, 2); 1629 auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {}; 1630 1631 CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop( 1632 Loc, LoopBodyGen, StartVal, StopVal, StepVal, 1633 /*IsSigned=*/false, /*InclusiveStop=*/false); 1634 1635 Builder.SetInsertPoint(BB, BB->getFirstInsertionPt()); 1636 InsertPointTy AllocaIP = Builder.saveIP(); 1637 1638 CLI = OMPBuilder.createStaticWorkshareLoop(Loc, CLI, AllocaIP, 1639 /*NeedsBarrier=*/true); 1640 auto AllocaIter = BB->begin(); 1641 ASSERT_GE(std::distance(BB->begin(), BB->end()), 4); 1642 AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1643 AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1644 AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1645 AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++)); 1646 EXPECT_NE(PLastIter, nullptr); 1647 EXPECT_NE(PLowerBound, nullptr); 1648 EXPECT_NE(PUpperBound, nullptr); 1649 EXPECT_NE(PStride, nullptr); 1650 1651 auto PreheaderIter = CLI->getPreheader()->begin(); 1652 ASSERT_GE( 1653 std::distance(CLI->getPreheader()->begin(), CLI->getPreheader()->end()), 1654 7); 1655 StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1656 StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1657 StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++)); 1658 ASSERT_NE(LowerBoundStore, nullptr); 1659 ASSERT_NE(UpperBoundStore, nullptr); 1660 ASSERT_NE(StrideStore, nullptr); 1661 1662 auto *OrigLowerBound = 1663 dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand()); 1664 auto *OrigUpperBound = 1665 dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand()); 1666 auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand()); 1667 ASSERT_NE(OrigLowerBound, nullptr); 1668 ASSERT_NE(OrigUpperBound, nullptr); 1669 ASSERT_NE(OrigStride, nullptr); 1670 EXPECT_EQ(OrigLowerBound->getValue(), 0); 1671 EXPECT_EQ(OrigUpperBound->getValue(), 20); 1672 EXPECT_EQ(OrigStride->getValue(), 1); 1673 1674 // Check that the loop IV is updated to account for the lower bound returned 1675 // by the OpenMP runtime call. 1676 BinaryOperator *Add = dyn_cast<BinaryOperator>(&CLI->getBody()->front()); 1677 EXPECT_EQ(Add->getOperand(0), CLI->getIndVar()); 1678 auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1)); 1679 ASSERT_NE(LoadedLowerBound, nullptr); 1680 EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound); 1681 1682 // Check that the trip count is updated to account for the lower and upper 1683 // bounds return by the OpenMP runtime call. 1684 auto *AddOne = dyn_cast<Instruction>(CLI->getTripCount()); 1685 ASSERT_NE(AddOne, nullptr); 1686 ASSERT_TRUE(AddOne->isBinaryOp()); 1687 auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1)); 1688 ASSERT_NE(One, nullptr); 1689 EXPECT_EQ(One->getValue(), 1); 1690 auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0)); 1691 ASSERT_NE(Difference, nullptr); 1692 ASSERT_TRUE(Difference->isBinaryOp()); 1693 EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound); 1694 auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0)); 1695 ASSERT_NE(LoadedUpperBound, nullptr); 1696 EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound); 1697 1698 // The original loop iterator should only be used in the condition, in the 1699 // increment and in the statement that adds the lower bound to it. 1700 Value *IV = CLI->getIndVar(); 1701 EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3); 1702 1703 // The exit block should contain the "fini" call and the barrier call, 1704 // plus the call to obtain the thread ID. 1705 BasicBlock *ExitBlock = CLI->getExit(); 1706 size_t NumCallsInExitBlock = 1707 count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); }); 1708 EXPECT_EQ(NumCallsInExitBlock, 3u); 1709 } 1710 1711 TEST_F(OpenMPIRBuilderTest, MasterDirective) { 1712 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1713 OpenMPIRBuilder OMPBuilder(*M); 1714 OMPBuilder.initialize(); 1715 F->setName("func"); 1716 IRBuilder<> Builder(BB); 1717 1718 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1719 1720 AllocaInst *PrivAI = nullptr; 1721 1722 BasicBlock *EntryBB = nullptr; 1723 BasicBlock *ExitBB = nullptr; 1724 BasicBlock *ThenBB = nullptr; 1725 1726 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1727 BasicBlock &FiniBB) { 1728 if (AllocaIP.isSet()) 1729 Builder.restoreIP(AllocaIP); 1730 else 1731 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 1732 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1733 Builder.CreateStore(F->arg_begin(), PrivAI); 1734 1735 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1736 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1737 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1738 1739 Builder.restoreIP(CodeGenIP); 1740 1741 // collect some info for checks later 1742 ExitBB = FiniBB.getUniqueSuccessor(); 1743 ThenBB = Builder.GetInsertBlock(); 1744 EntryBB = ThenBB->getUniquePredecessor(); 1745 1746 // simple instructions for body 1747 Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, 1748 "local.use"); 1749 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1750 }; 1751 1752 auto FiniCB = [&](InsertPointTy IP) { 1753 BasicBlock *IPBB = IP.getBlock(); 1754 EXPECT_NE(IPBB->end(), IP.getPoint()); 1755 }; 1756 1757 Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB)); 1758 Value *EntryBBTI = EntryBB->getTerminator(); 1759 EXPECT_NE(EntryBBTI, nullptr); 1760 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 1761 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 1762 EXPECT_TRUE(EntryBr->isConditional()); 1763 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 1764 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 1765 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 1766 1767 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 1768 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 1769 1770 CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0)); 1771 EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U); 1772 EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master"); 1773 EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0))); 1774 1775 CallInst *MasterEndCI = nullptr; 1776 for (auto &FI : *ThenBB) { 1777 Instruction *cur = &FI; 1778 if (isa<CallInst>(cur)) { 1779 MasterEndCI = cast<CallInst>(cur); 1780 if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master") 1781 break; 1782 MasterEndCI = nullptr; 1783 } 1784 } 1785 EXPECT_NE(MasterEndCI, nullptr); 1786 EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U); 1787 EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0))); 1788 EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1)); 1789 } 1790 1791 TEST_F(OpenMPIRBuilderTest, CriticalDirective) { 1792 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1793 OpenMPIRBuilder OMPBuilder(*M); 1794 OMPBuilder.initialize(); 1795 F->setName("func"); 1796 IRBuilder<> Builder(BB); 1797 1798 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1799 1800 AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1801 1802 BasicBlock *EntryBB = nullptr; 1803 1804 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1805 BasicBlock &FiniBB) { 1806 // collect some info for checks later 1807 EntryBB = FiniBB.getUniquePredecessor(); 1808 1809 // actual start for bodyCB 1810 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1811 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1812 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1813 EXPECT_EQ(EntryBB, CodeGenIPBB); 1814 1815 // body begin 1816 Builder.restoreIP(CodeGenIP); 1817 Builder.CreateStore(F->arg_begin(), PrivAI); 1818 Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, 1819 "local.use"); 1820 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1821 }; 1822 1823 auto FiniCB = [&](InsertPointTy IP) { 1824 BasicBlock *IPBB = IP.getBlock(); 1825 EXPECT_NE(IPBB->end(), IP.getPoint()); 1826 }; 1827 1828 Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB, 1829 "testCRT", nullptr)); 1830 1831 Value *EntryBBTI = EntryBB->getTerminator(); 1832 EXPECT_EQ(EntryBBTI, nullptr); 1833 1834 CallInst *CriticalEntryCI = nullptr; 1835 for (auto &EI : *EntryBB) { 1836 Instruction *cur = &EI; 1837 if (isa<CallInst>(cur)) { 1838 CriticalEntryCI = cast<CallInst>(cur); 1839 if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical") 1840 break; 1841 CriticalEntryCI = nullptr; 1842 } 1843 } 1844 EXPECT_NE(CriticalEntryCI, nullptr); 1845 EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U); 1846 EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical"); 1847 EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0))); 1848 1849 CallInst *CriticalEndCI = nullptr; 1850 for (auto &FI : *EntryBB) { 1851 Instruction *cur = &FI; 1852 if (isa<CallInst>(cur)) { 1853 CriticalEndCI = cast<CallInst>(cur); 1854 if (CriticalEndCI->getCalledFunction()->getName() == 1855 "__kmpc_end_critical") 1856 break; 1857 CriticalEndCI = nullptr; 1858 } 1859 } 1860 EXPECT_NE(CriticalEndCI, nullptr); 1861 EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U); 1862 EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0))); 1863 EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1)); 1864 PointerType *CriticalNamePtrTy = 1865 PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8)); 1866 EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2)); 1867 EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy); 1868 } 1869 1870 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) { 1871 OpenMPIRBuilder OMPBuilder(*M); 1872 OMPBuilder.initialize(); 1873 F->setName("func"); 1874 IRBuilder<> Builder(BB); 1875 1876 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1877 1878 IntegerType* Int32 = Type::getInt32Ty(M->getContext()); 1879 AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo()); 1880 AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo()); 1881 1882 BasicBlock *EntryBB = BB; 1883 1884 OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress, 1885 PrivAddress, Int32, /*BranchtoEnd*/ true); 1886 1887 BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator()); 1888 1889 EXPECT_NE(EntryBr, nullptr); 1890 EXPECT_TRUE(EntryBr->isConditional()); 1891 1892 BasicBlock* NotMasterBB = EntryBr->getSuccessor(0); 1893 BasicBlock* CopyinEnd = EntryBr->getSuccessor(1); 1894 CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition()); 1895 1896 EXPECT_NE(CMP, nullptr); 1897 EXPECT_NE(NotMasterBB, nullptr); 1898 EXPECT_NE(CopyinEnd, nullptr); 1899 1900 BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator()); 1901 EXPECT_NE(NotMasterBr, nullptr); 1902 EXPECT_FALSE(NotMasterBr->isConditional()); 1903 EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0)); 1904 } 1905 1906 TEST_F(OpenMPIRBuilderTest, SingleDirective) { 1907 using InsertPointTy = OpenMPIRBuilder::InsertPointTy; 1908 OpenMPIRBuilder OMPBuilder(*M); 1909 OMPBuilder.initialize(); 1910 F->setName("func"); 1911 IRBuilder<> Builder(BB); 1912 1913 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL}); 1914 1915 AllocaInst *PrivAI = nullptr; 1916 1917 BasicBlock *EntryBB = nullptr; 1918 BasicBlock *ExitBB = nullptr; 1919 BasicBlock *ThenBB = nullptr; 1920 1921 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1922 BasicBlock &FiniBB) { 1923 if (AllocaIP.isSet()) 1924 Builder.restoreIP(AllocaIP); 1925 else 1926 Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt())); 1927 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType()); 1928 Builder.CreateStore(F->arg_begin(), PrivAI); 1929 1930 llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock(); 1931 llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint(); 1932 EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst); 1933 1934 Builder.restoreIP(CodeGenIP); 1935 1936 // collect some info for checks later 1937 ExitBB = FiniBB.getUniqueSuccessor(); 1938 ThenBB = Builder.GetInsertBlock(); 1939 EntryBB = ThenBB->getUniquePredecessor(); 1940 1941 // simple instructions for body 1942 Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, 1943 "local.use"); 1944 Builder.CreateICmpNE(F->arg_begin(), PrivLoad); 1945 }; 1946 1947 auto FiniCB = [&](InsertPointTy IP) { 1948 BasicBlock *IPBB = IP.getBlock(); 1949 EXPECT_NE(IPBB->end(), IP.getPoint()); 1950 }; 1951 1952 Builder.restoreIP( 1953 OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr)); 1954 Value *EntryBBTI = EntryBB->getTerminator(); 1955 EXPECT_NE(EntryBBTI, nullptr); 1956 EXPECT_TRUE(isa<BranchInst>(EntryBBTI)); 1957 BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator()); 1958 EXPECT_TRUE(EntryBr->isConditional()); 1959 EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB); 1960 EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB); 1961 EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB); 1962 1963 CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition()); 1964 EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0))); 1965 1966 CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0)); 1967 EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U); 1968 EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single"); 1969 EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0))); 1970 1971 CallInst *SingleEndCI = nullptr; 1972 for (auto &FI : *ThenBB) { 1973 Instruction *cur = &FI; 1974 if (isa<CallInst>(cur)) { 1975 SingleEndCI = cast<CallInst>(cur); 1976 if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single") 1977 break; 1978 SingleEndCI = nullptr; 1979 } 1980 } 1981 EXPECT_NE(SingleEndCI, nullptr); 1982 EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U); 1983 EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0))); 1984 EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1)); 1985 } 1986 1987 } // namespace 1988