1 //===- OpenMPIRBuilder.cpp - Builder for LLVM-IR for OpenMP directives ----===// 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 /// \file 9 /// 10 /// This file implements the OpenMPIRBuilder class, which is used as a 11 /// convenient way to create LLVM instructions for OpenMP directives. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 16 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/StringSwitch.h" 19 #include "llvm/ADT/Triple.h" 20 #include "llvm/IR/CFG.h" 21 #include "llvm/IR/DebugInfo.h" 22 #include "llvm/IR/IRBuilder.h" 23 #include "llvm/IR/MDBuilder.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/Error.h" 26 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 27 #include "llvm/Transforms/Utils/CodeExtractor.h" 28 29 #include <sstream> 30 31 #define DEBUG_TYPE "openmp-ir-builder" 32 33 using namespace llvm; 34 using namespace omp; 35 36 static cl::opt<bool> 37 OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, 38 cl::desc("Use optimistic attributes describing " 39 "'as-if' properties of runtime calls."), 40 cl::init(false)); 41 42 void OpenMPIRBuilder::addAttributes(omp::RuntimeFunction FnID, Function &Fn) { 43 LLVMContext &Ctx = Fn.getContext(); 44 45 #define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet; 46 #include "llvm/Frontend/OpenMP/OMPKinds.def" 47 48 // Add attributes to the new declaration. 49 switch (FnID) { 50 #define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \ 51 case Enum: \ 52 Fn.setAttributes( \ 53 AttributeList::get(Ctx, FnAttrSet, RetAttrSet, ArgAttrSets)); \ 54 break; 55 #include "llvm/Frontend/OpenMP/OMPKinds.def" 56 default: 57 // Attributes are optional. 58 break; 59 } 60 } 61 62 FunctionCallee 63 OpenMPIRBuilder::getOrCreateRuntimeFunction(Module &M, RuntimeFunction FnID) { 64 FunctionType *FnTy = nullptr; 65 Function *Fn = nullptr; 66 67 // Try to find the declation in the module first. 68 switch (FnID) { 69 #define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \ 70 case Enum: \ 71 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \ 72 IsVarArg); \ 73 Fn = M.getFunction(Str); \ 74 break; 75 #include "llvm/Frontend/OpenMP/OMPKinds.def" 76 } 77 78 if (!Fn) { 79 // Create a new declaration if we need one. 80 switch (FnID) { 81 #define OMP_RTL(Enum, Str, ...) \ 82 case Enum: \ 83 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \ 84 break; 85 #include "llvm/Frontend/OpenMP/OMPKinds.def" 86 } 87 88 // Add information if the runtime function takes a callback function 89 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) { 90 if (!Fn->hasMetadata(LLVMContext::MD_callback)) { 91 LLVMContext &Ctx = Fn->getContext(); 92 MDBuilder MDB(Ctx); 93 // Annotate the callback behavior of the runtime function: 94 // - The callback callee is argument number 2 (microtask). 95 // - The first two arguments of the callback callee are unknown (-1). 96 // - All variadic arguments to the runtime function are passed to the 97 // callback callee. 98 Fn->addMetadata( 99 LLVMContext::MD_callback, 100 *MDNode::get(Ctx, {MDB.createCallbackEncoding( 101 2, {-1, -1}, /* VarArgsArePassed */ true)})); 102 } 103 } 104 105 LLVM_DEBUG(dbgs() << "Created OpenMP runtime function " << Fn->getName() 106 << " with type " << *Fn->getFunctionType() << "\n"); 107 addAttributes(FnID, *Fn); 108 109 } else { 110 LLVM_DEBUG(dbgs() << "Found OpenMP runtime function " << Fn->getName() 111 << " with type " << *Fn->getFunctionType() << "\n"); 112 } 113 114 assert(Fn && "Failed to create OpenMP runtime function"); 115 116 // Cast the function to the expected type if necessary 117 Constant *C = ConstantExpr::getBitCast(Fn, FnTy->getPointerTo()); 118 return {FnTy, C}; 119 } 120 121 Function *OpenMPIRBuilder::getOrCreateRuntimeFunctionPtr(RuntimeFunction FnID) { 122 FunctionCallee RTLFn = getOrCreateRuntimeFunction(M, FnID); 123 auto *Fn = dyn_cast<llvm::Function>(RTLFn.getCallee()); 124 assert(Fn && "Failed to create OpenMP runtime function pointer"); 125 return Fn; 126 } 127 128 void OpenMPIRBuilder::initialize() { initializeTypes(M); } 129 130 void OpenMPIRBuilder::finalize() { 131 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet; 132 SmallVector<BasicBlock *, 32> Blocks; 133 for (OutlineInfo &OI : OutlineInfos) { 134 ParallelRegionBlockSet.clear(); 135 Blocks.clear(); 136 OI.collectBlocks(ParallelRegionBlockSet, Blocks); 137 138 Function *OuterFn = OI.EntryBB->getParent(); 139 CodeExtractorAnalysisCache CEAC(*OuterFn); 140 CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr, 141 /* AggregateArgs */ false, 142 /* BlockFrequencyInfo */ nullptr, 143 /* BranchProbabilityInfo */ nullptr, 144 /* AssumptionCache */ nullptr, 145 /* AllowVarArgs */ true, 146 /* AllowAlloca */ true, 147 /* Suffix */ ".omp_par"); 148 149 LLVM_DEBUG(dbgs() << "Before outlining: " << *OuterFn << "\n"); 150 LLVM_DEBUG(dbgs() << "Entry " << OI.EntryBB->getName() 151 << " Exit: " << OI.ExitBB->getName() << "\n"); 152 assert(Extractor.isEligible() && 153 "Expected OpenMP outlining to be possible!"); 154 155 Function *OutlinedFn = Extractor.extractCodeRegion(CEAC); 156 157 LLVM_DEBUG(dbgs() << "After outlining: " << *OuterFn << "\n"); 158 LLVM_DEBUG(dbgs() << " Outlined function: " << *OutlinedFn << "\n"); 159 assert(OutlinedFn->getReturnType()->isVoidTy() && 160 "OpenMP outlined functions should not return a value!"); 161 162 // For compability with the clang CG we move the outlined function after the 163 // one with the parallel region. 164 OutlinedFn->removeFromParent(); 165 M.getFunctionList().insertAfter(OuterFn->getIterator(), OutlinedFn); 166 167 // Remove the artificial entry introduced by the extractor right away, we 168 // made our own entry block after all. 169 { 170 BasicBlock &ArtificialEntry = OutlinedFn->getEntryBlock(); 171 assert(ArtificialEntry.getUniqueSuccessor() == OI.EntryBB); 172 assert(OI.EntryBB->getUniquePredecessor() == &ArtificialEntry); 173 OI.EntryBB->moveBefore(&ArtificialEntry); 174 ArtificialEntry.eraseFromParent(); 175 } 176 assert(&OutlinedFn->getEntryBlock() == OI.EntryBB); 177 assert(OutlinedFn && OutlinedFn->getNumUses() == 1); 178 179 // Run a user callback, e.g. to add attributes. 180 if (OI.PostOutlineCB) 181 OI.PostOutlineCB(*OutlinedFn); 182 } 183 184 // Allow finalize to be called multiple times. 185 OutlineInfos.clear(); 186 } 187 188 Value *OpenMPIRBuilder::getOrCreateIdent(Constant *SrcLocStr, 189 IdentFlag LocFlags, 190 unsigned Reserve2Flags) { 191 // Enable "C-mode". 192 LocFlags |= OMP_IDENT_FLAG_KMPC; 193 194 Value *&Ident = 195 IdentMap[{SrcLocStr, uint64_t(LocFlags) << 31 | Reserve2Flags}]; 196 if (!Ident) { 197 Constant *I32Null = ConstantInt::getNullValue(Int32); 198 Constant *IdentData[] = { 199 I32Null, ConstantInt::get(Int32, uint32_t(LocFlags)), 200 ConstantInt::get(Int32, Reserve2Flags), I32Null, SrcLocStr}; 201 Constant *Initializer = ConstantStruct::get( 202 cast<StructType>(IdentPtr->getPointerElementType()), IdentData); 203 204 // Look for existing encoding of the location + flags, not needed but 205 // minimizes the difference to the existing solution while we transition. 206 for (GlobalVariable &GV : M.getGlobalList()) 207 if (GV.getType() == IdentPtr && GV.hasInitializer()) 208 if (GV.getInitializer() == Initializer) 209 return Ident = &GV; 210 211 auto *GV = new GlobalVariable(M, IdentPtr->getPointerElementType(), 212 /* isConstant = */ true, 213 GlobalValue::PrivateLinkage, Initializer); 214 GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 215 GV->setAlignment(Align(8)); 216 Ident = GV; 217 } 218 return Builder.CreatePointerCast(Ident, IdentPtr); 219 } 220 221 Type *OpenMPIRBuilder::getLanemaskType() { 222 LLVMContext &Ctx = M.getContext(); 223 Triple triple(M.getTargetTriple()); 224 225 // This test is adequate until deviceRTL has finer grained lane widths 226 return triple.isAMDGCN() ? Type::getInt64Ty(Ctx) : Type::getInt32Ty(Ctx); 227 } 228 229 Constant *OpenMPIRBuilder::getOrCreateSrcLocStr(StringRef LocStr) { 230 Constant *&SrcLocStr = SrcLocStrMap[LocStr]; 231 if (!SrcLocStr) { 232 Constant *Initializer = 233 ConstantDataArray::getString(M.getContext(), LocStr); 234 235 // Look for existing encoding of the location, not needed but minimizes the 236 // difference to the existing solution while we transition. 237 for (GlobalVariable &GV : M.getGlobalList()) 238 if (GV.isConstant() && GV.hasInitializer() && 239 GV.getInitializer() == Initializer) 240 return SrcLocStr = ConstantExpr::getPointerCast(&GV, Int8Ptr); 241 242 SrcLocStr = Builder.CreateGlobalStringPtr(LocStr, /* Name */ "", 243 /* AddressSpace */ 0, &M); 244 } 245 return SrcLocStr; 246 } 247 248 Constant *OpenMPIRBuilder::getOrCreateSrcLocStr(StringRef FunctionName, 249 StringRef FileName, 250 unsigned Line, 251 unsigned Column) { 252 SmallString<128> Buffer; 253 Buffer.push_back(';'); 254 Buffer.append(FileName); 255 Buffer.push_back(';'); 256 Buffer.append(FunctionName); 257 Buffer.push_back(';'); 258 Buffer.append(std::to_string(Line)); 259 Buffer.push_back(';'); 260 Buffer.append(std::to_string(Column)); 261 Buffer.push_back(';'); 262 Buffer.push_back(';'); 263 return getOrCreateSrcLocStr(Buffer.str()); 264 } 265 266 Constant *OpenMPIRBuilder::getOrCreateDefaultSrcLocStr() { 267 return getOrCreateSrcLocStr(";unknown;unknown;0;0;;"); 268 } 269 270 Constant * 271 OpenMPIRBuilder::getOrCreateSrcLocStr(const LocationDescription &Loc) { 272 DILocation *DIL = Loc.DL.get(); 273 if (!DIL) 274 return getOrCreateDefaultSrcLocStr(); 275 StringRef FileName = M.getName(); 276 if (DIFile *DIF = DIL->getFile()) 277 if (Optional<StringRef> Source = DIF->getSource()) 278 FileName = *Source; 279 StringRef Function = DIL->getScope()->getSubprogram()->getName(); 280 Function = 281 !Function.empty() ? Function : Loc.IP.getBlock()->getParent()->getName(); 282 return getOrCreateSrcLocStr(Function, FileName, DIL->getLine(), 283 DIL->getColumn()); 284 } 285 286 Value *OpenMPIRBuilder::getOrCreateThreadID(Value *Ident) { 287 return Builder.CreateCall( 288 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_global_thread_num), Ident, 289 "omp_global_thread_num"); 290 } 291 292 OpenMPIRBuilder::InsertPointTy 293 OpenMPIRBuilder::createBarrier(const LocationDescription &Loc, Directive DK, 294 bool ForceSimpleCall, bool CheckCancelFlag) { 295 if (!updateToLocation(Loc)) 296 return Loc.IP; 297 return emitBarrierImpl(Loc, DK, ForceSimpleCall, CheckCancelFlag); 298 } 299 300 OpenMPIRBuilder::InsertPointTy 301 OpenMPIRBuilder::emitBarrierImpl(const LocationDescription &Loc, Directive Kind, 302 bool ForceSimpleCall, bool CheckCancelFlag) { 303 // Build call __kmpc_cancel_barrier(loc, thread_id) or 304 // __kmpc_barrier(loc, thread_id); 305 306 IdentFlag BarrierLocFlags; 307 switch (Kind) { 308 case OMPD_for: 309 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR; 310 break; 311 case OMPD_sections: 312 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS; 313 break; 314 case OMPD_single: 315 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE; 316 break; 317 case OMPD_barrier: 318 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL; 319 break; 320 default: 321 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL; 322 break; 323 } 324 325 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 326 Value *Args[] = {getOrCreateIdent(SrcLocStr, BarrierLocFlags), 327 getOrCreateThreadID(getOrCreateIdent(SrcLocStr))}; 328 329 // If we are in a cancellable parallel region, barriers are cancellation 330 // points. 331 // TODO: Check why we would force simple calls or to ignore the cancel flag. 332 bool UseCancelBarrier = 333 !ForceSimpleCall && isLastFinalizationInfoCancellable(OMPD_parallel); 334 335 Value *Result = 336 Builder.CreateCall(getOrCreateRuntimeFunctionPtr( 337 UseCancelBarrier ? OMPRTL___kmpc_cancel_barrier 338 : OMPRTL___kmpc_barrier), 339 Args); 340 341 if (UseCancelBarrier && CheckCancelFlag) 342 emitCancelationCheckImpl(Result, OMPD_parallel); 343 344 return Builder.saveIP(); 345 } 346 347 OpenMPIRBuilder::InsertPointTy 348 OpenMPIRBuilder::createCancel(const LocationDescription &Loc, 349 Value *IfCondition, 350 omp::Directive CanceledDirective) { 351 if (!updateToLocation(Loc)) 352 return Loc.IP; 353 354 // LLVM utilities like blocks with terminators. 355 auto *UI = Builder.CreateUnreachable(); 356 357 Instruction *ThenTI = UI, *ElseTI = nullptr; 358 if (IfCondition) 359 SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI); 360 Builder.SetInsertPoint(ThenTI); 361 362 Value *CancelKind = nullptr; 363 switch (CanceledDirective) { 364 #define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \ 365 case DirectiveEnum: \ 366 CancelKind = Builder.getInt32(Value); \ 367 break; 368 #include "llvm/Frontend/OpenMP/OMPKinds.def" 369 default: 370 llvm_unreachable("Unknown cancel kind!"); 371 } 372 373 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 374 Value *Ident = getOrCreateIdent(SrcLocStr); 375 Value *Args[] = {Ident, getOrCreateThreadID(Ident), CancelKind}; 376 Value *Result = Builder.CreateCall( 377 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_cancel), Args); 378 379 // The actual cancel logic is shared with others, e.g., cancel_barriers. 380 emitCancelationCheckImpl(Result, CanceledDirective); 381 382 // Update the insertion point and remove the terminator we introduced. 383 Builder.SetInsertPoint(UI->getParent()); 384 UI->eraseFromParent(); 385 386 return Builder.saveIP(); 387 } 388 389 void OpenMPIRBuilder::emitCancelationCheckImpl( 390 Value *CancelFlag, omp::Directive CanceledDirective) { 391 assert(isLastFinalizationInfoCancellable(CanceledDirective) && 392 "Unexpected cancellation!"); 393 394 // For a cancel barrier we create two new blocks. 395 BasicBlock *BB = Builder.GetInsertBlock(); 396 BasicBlock *NonCancellationBlock; 397 if (Builder.GetInsertPoint() == BB->end()) { 398 // TODO: This branch will not be needed once we moved to the 399 // OpenMPIRBuilder codegen completely. 400 NonCancellationBlock = BasicBlock::Create( 401 BB->getContext(), BB->getName() + ".cont", BB->getParent()); 402 } else { 403 NonCancellationBlock = SplitBlock(BB, &*Builder.GetInsertPoint()); 404 BB->getTerminator()->eraseFromParent(); 405 Builder.SetInsertPoint(BB); 406 } 407 BasicBlock *CancellationBlock = BasicBlock::Create( 408 BB->getContext(), BB->getName() + ".cncl", BB->getParent()); 409 410 // Jump to them based on the return value. 411 Value *Cmp = Builder.CreateIsNull(CancelFlag); 412 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock, 413 /* TODO weight */ nullptr, nullptr); 414 415 // From the cancellation block we finalize all variables and go to the 416 // post finalization block that is known to the FiniCB callback. 417 Builder.SetInsertPoint(CancellationBlock); 418 auto &FI = FinalizationStack.back(); 419 FI.FiniCB(Builder.saveIP()); 420 421 // The continuation block is where code generation continues. 422 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->begin()); 423 } 424 425 IRBuilder<>::InsertPoint OpenMPIRBuilder::createParallel( 426 const LocationDescription &Loc, InsertPointTy OuterAllocaIP, 427 BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, 428 FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, 429 omp::ProcBindKind ProcBind, bool IsCancellable) { 430 if (!updateToLocation(Loc)) 431 return Loc.IP; 432 433 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 434 Value *Ident = getOrCreateIdent(SrcLocStr); 435 Value *ThreadID = getOrCreateThreadID(Ident); 436 437 if (NumThreads) { 438 // Build call __kmpc_push_num_threads(&Ident, global_tid, num_threads) 439 Value *Args[] = { 440 Ident, ThreadID, 441 Builder.CreateIntCast(NumThreads, Int32, /*isSigned*/ false)}; 442 Builder.CreateCall( 443 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_num_threads), Args); 444 } 445 446 if (ProcBind != OMP_PROC_BIND_default) { 447 // Build call __kmpc_push_proc_bind(&Ident, global_tid, proc_bind) 448 Value *Args[] = { 449 Ident, ThreadID, 450 ConstantInt::get(Int32, unsigned(ProcBind), /*isSigned=*/true)}; 451 Builder.CreateCall( 452 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_proc_bind), Args); 453 } 454 455 BasicBlock *InsertBB = Builder.GetInsertBlock(); 456 Function *OuterFn = InsertBB->getParent(); 457 458 // Save the outer alloca block because the insertion iterator may get 459 // invalidated and we still need this later. 460 BasicBlock *OuterAllocaBlock = OuterAllocaIP.getBlock(); 461 462 // Vector to remember instructions we used only during the modeling but which 463 // we want to delete at the end. 464 SmallVector<Instruction *, 4> ToBeDeleted; 465 466 // Change the location to the outer alloca insertion point to create and 467 // initialize the allocas we pass into the parallel region. 468 Builder.restoreIP(OuterAllocaIP); 469 AllocaInst *TIDAddr = Builder.CreateAlloca(Int32, nullptr, "tid.addr"); 470 AllocaInst *ZeroAddr = Builder.CreateAlloca(Int32, nullptr, "zero.addr"); 471 472 // If there is an if condition we actually use the TIDAddr and ZeroAddr in the 473 // program, otherwise we only need them for modeling purposes to get the 474 // associated arguments in the outlined function. In the former case, 475 // initialize the allocas properly, in the latter case, delete them later. 476 if (IfCondition) { 477 Builder.CreateStore(Constant::getNullValue(Int32), TIDAddr); 478 Builder.CreateStore(Constant::getNullValue(Int32), ZeroAddr); 479 } else { 480 ToBeDeleted.push_back(TIDAddr); 481 ToBeDeleted.push_back(ZeroAddr); 482 } 483 484 // Create an artificial insertion point that will also ensure the blocks we 485 // are about to split are not degenerated. 486 auto *UI = new UnreachableInst(Builder.getContext(), InsertBB); 487 488 Instruction *ThenTI = UI, *ElseTI = nullptr; 489 if (IfCondition) 490 SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI); 491 492 BasicBlock *ThenBB = ThenTI->getParent(); 493 BasicBlock *PRegEntryBB = ThenBB->splitBasicBlock(ThenTI, "omp.par.entry"); 494 BasicBlock *PRegBodyBB = 495 PRegEntryBB->splitBasicBlock(ThenTI, "omp.par.region"); 496 BasicBlock *PRegPreFiniBB = 497 PRegBodyBB->splitBasicBlock(ThenTI, "omp.par.pre_finalize"); 498 BasicBlock *PRegExitBB = 499 PRegPreFiniBB->splitBasicBlock(ThenTI, "omp.par.exit"); 500 501 auto FiniCBWrapper = [&](InsertPointTy IP) { 502 // Hide "open-ended" blocks from the given FiniCB by setting the right jump 503 // target to the region exit block. 504 if (IP.getBlock()->end() == IP.getPoint()) { 505 IRBuilder<>::InsertPointGuard IPG(Builder); 506 Builder.restoreIP(IP); 507 Instruction *I = Builder.CreateBr(PRegExitBB); 508 IP = InsertPointTy(I->getParent(), I->getIterator()); 509 } 510 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 && 511 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB && 512 "Unexpected insertion point for finalization call!"); 513 return FiniCB(IP); 514 }; 515 516 FinalizationStack.push_back({FiniCBWrapper, OMPD_parallel, IsCancellable}); 517 518 // Generate the privatization allocas in the block that will become the entry 519 // of the outlined function. 520 Builder.SetInsertPoint(PRegEntryBB->getTerminator()); 521 InsertPointTy InnerAllocaIP = Builder.saveIP(); 522 523 AllocaInst *PrivTIDAddr = 524 Builder.CreateAlloca(Int32, nullptr, "tid.addr.local"); 525 Instruction *PrivTID = Builder.CreateLoad(PrivTIDAddr, "tid"); 526 527 // Add some fake uses for OpenMP provided arguments. 528 ToBeDeleted.push_back(Builder.CreateLoad(TIDAddr, "tid.addr.use")); 529 Instruction *ZeroAddrUse = Builder.CreateLoad(ZeroAddr, "zero.addr.use"); 530 ToBeDeleted.push_back(ZeroAddrUse); 531 532 // ThenBB 533 // | 534 // V 535 // PRegionEntryBB <- Privatization allocas are placed here. 536 // | 537 // V 538 // PRegionBodyBB <- BodeGen is invoked here. 539 // | 540 // V 541 // PRegPreFiniBB <- The block we will start finalization from. 542 // | 543 // V 544 // PRegionExitBB <- A common exit to simplify block collection. 545 // 546 547 LLVM_DEBUG(dbgs() << "Before body codegen: " << *OuterFn << "\n"); 548 549 // Let the caller create the body. 550 assert(BodyGenCB && "Expected body generation callback!"); 551 InsertPointTy CodeGenIP(PRegBodyBB, PRegBodyBB->begin()); 552 BodyGenCB(InnerAllocaIP, CodeGenIP, *PRegPreFiniBB); 553 554 LLVM_DEBUG(dbgs() << "After body codegen: " << *OuterFn << "\n"); 555 556 FunctionCallee RTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_fork_call); 557 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 558 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 559 llvm::LLVMContext &Ctx = F->getContext(); 560 MDBuilder MDB(Ctx); 561 // Annotate the callback behavior of the __kmpc_fork_call: 562 // - The callback callee is argument number 2 (microtask). 563 // - The first two arguments of the callback callee are unknown (-1). 564 // - All variadic arguments to the __kmpc_fork_call are passed to the 565 // callback callee. 566 F->addMetadata( 567 llvm::LLVMContext::MD_callback, 568 *llvm::MDNode::get( 569 Ctx, {MDB.createCallbackEncoding(2, {-1, -1}, 570 /* VarArgsArePassed */ true)})); 571 } 572 } 573 574 OutlineInfo OI; 575 OI.PostOutlineCB = [=](Function &OutlinedFn) { 576 // Add some known attributes. 577 OutlinedFn.addParamAttr(0, Attribute::NoAlias); 578 OutlinedFn.addParamAttr(1, Attribute::NoAlias); 579 OutlinedFn.addFnAttr(Attribute::NoUnwind); 580 OutlinedFn.addFnAttr(Attribute::NoRecurse); 581 582 assert(OutlinedFn.arg_size() >= 2 && 583 "Expected at least tid and bounded tid as arguments"); 584 unsigned NumCapturedVars = 585 OutlinedFn.arg_size() - /* tid & bounded tid */ 2; 586 587 CallInst *CI = cast<CallInst>(OutlinedFn.user_back()); 588 CI->getParent()->setName("omp_parallel"); 589 Builder.SetInsertPoint(CI); 590 591 // Build call __kmpc_fork_call(Ident, n, microtask, var1, .., varn); 592 Value *ForkCallArgs[] = { 593 Ident, Builder.getInt32(NumCapturedVars), 594 Builder.CreateBitCast(&OutlinedFn, ParallelTaskPtr)}; 595 596 SmallVector<Value *, 16> RealArgs; 597 RealArgs.append(std::begin(ForkCallArgs), std::end(ForkCallArgs)); 598 RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end()); 599 600 Builder.CreateCall(RTLFn, RealArgs); 601 602 LLVM_DEBUG(dbgs() << "With fork_call placed: " 603 << *Builder.GetInsertBlock()->getParent() << "\n"); 604 605 InsertPointTy ExitIP(PRegExitBB, PRegExitBB->end()); 606 607 // Initialize the local TID stack location with the argument value. 608 Builder.SetInsertPoint(PrivTID); 609 Function::arg_iterator OutlinedAI = OutlinedFn.arg_begin(); 610 Builder.CreateStore(Builder.CreateLoad(OutlinedAI), PrivTIDAddr); 611 612 // If no "if" clause was present we do not need the call created during 613 // outlining, otherwise we reuse it in the serialized parallel region. 614 if (!ElseTI) { 615 CI->eraseFromParent(); 616 } else { 617 618 // If an "if" clause was present we are now generating the serialized 619 // version into the "else" branch. 620 Builder.SetInsertPoint(ElseTI); 621 622 // Build calls __kmpc_serialized_parallel(&Ident, GTid); 623 Value *SerializedParallelCallArgs[] = {Ident, ThreadID}; 624 Builder.CreateCall( 625 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_serialized_parallel), 626 SerializedParallelCallArgs); 627 628 // OutlinedFn(>id, &zero, CapturedStruct); 629 CI->removeFromParent(); 630 Builder.Insert(CI); 631 632 // __kmpc_end_serialized_parallel(&Ident, GTid); 633 Value *EndArgs[] = {Ident, ThreadID}; 634 Builder.CreateCall( 635 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_serialized_parallel), 636 EndArgs); 637 638 LLVM_DEBUG(dbgs() << "With serialized parallel region: " 639 << *Builder.GetInsertBlock()->getParent() << "\n"); 640 } 641 642 for (Instruction *I : ToBeDeleted) 643 I->eraseFromParent(); 644 }; 645 646 // Adjust the finalization stack, verify the adjustment, and call the 647 // finalize function a last time to finalize values between the pre-fini 648 // block and the exit block if we left the parallel "the normal way". 649 auto FiniInfo = FinalizationStack.pop_back_val(); 650 (void)FiniInfo; 651 assert(FiniInfo.DK == OMPD_parallel && 652 "Unexpected finalization stack state!"); 653 654 Instruction *PRegPreFiniTI = PRegPreFiniBB->getTerminator(); 655 656 InsertPointTy PreFiniIP(PRegPreFiniBB, PRegPreFiniTI->getIterator()); 657 FiniCB(PreFiniIP); 658 659 OI.EntryBB = PRegEntryBB; 660 OI.ExitBB = PRegExitBB; 661 662 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet; 663 SmallVector<BasicBlock *, 32> Blocks; 664 OI.collectBlocks(ParallelRegionBlockSet, Blocks); 665 666 // Ensure a single exit node for the outlined region by creating one. 667 // We might have multiple incoming edges to the exit now due to finalizations, 668 // e.g., cancel calls that cause the control flow to leave the region. 669 BasicBlock *PRegOutlinedExitBB = PRegExitBB; 670 PRegExitBB = SplitBlock(PRegExitBB, &*PRegExitBB->getFirstInsertionPt()); 671 PRegOutlinedExitBB->setName("omp.par.outlined.exit"); 672 Blocks.push_back(PRegOutlinedExitBB); 673 674 CodeExtractorAnalysisCache CEAC(*OuterFn); 675 CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr, 676 /* AggregateArgs */ false, 677 /* BlockFrequencyInfo */ nullptr, 678 /* BranchProbabilityInfo */ nullptr, 679 /* AssumptionCache */ nullptr, 680 /* AllowVarArgs */ true, 681 /* AllowAlloca */ true, 682 /* Suffix */ ".omp_par"); 683 684 // Find inputs to, outputs from the code region. 685 BasicBlock *CommonExit = nullptr; 686 SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands; 687 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit); 688 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands); 689 690 LLVM_DEBUG(dbgs() << "Before privatization: " << *OuterFn << "\n"); 691 692 FunctionCallee TIDRTLFn = 693 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_global_thread_num); 694 695 auto PrivHelper = [&](Value &V) { 696 if (&V == TIDAddr || &V == ZeroAddr) 697 return; 698 699 SetVector<Use *> Uses; 700 for (Use &U : V.uses()) 701 if (auto *UserI = dyn_cast<Instruction>(U.getUser())) 702 if (ParallelRegionBlockSet.count(UserI->getParent())) 703 Uses.insert(&U); 704 705 // __kmpc_fork_call expects extra arguments as pointers. If the input 706 // already has a pointer type, everything is fine. Otherwise, store the 707 // value onto stack and load it back inside the to-be-outlined region. This 708 // will ensure only the pointer will be passed to the function. 709 // FIXME: if there are more than 15 trailing arguments, they must be 710 // additionally packed in a struct. 711 Value *Inner = &V; 712 if (!V.getType()->isPointerTy()) { 713 IRBuilder<>::InsertPointGuard Guard(Builder); 714 LLVM_DEBUG(llvm::dbgs() << "Forwarding input as pointer: " << V << "\n"); 715 716 Builder.restoreIP(OuterAllocaIP); 717 Value *Ptr = 718 Builder.CreateAlloca(V.getType(), nullptr, V.getName() + ".reloaded"); 719 720 // Store to stack at end of the block that currently branches to the entry 721 // block of the to-be-outlined region. 722 Builder.SetInsertPoint(InsertBB, 723 InsertBB->getTerminator()->getIterator()); 724 Builder.CreateStore(&V, Ptr); 725 726 // Load back next to allocations in the to-be-outlined region. 727 Builder.restoreIP(InnerAllocaIP); 728 Inner = Builder.CreateLoad(Ptr); 729 } 730 731 Value *ReplacementValue = nullptr; 732 CallInst *CI = dyn_cast<CallInst>(&V); 733 if (CI && CI->getCalledFunction() == TIDRTLFn.getCallee()) { 734 ReplacementValue = PrivTID; 735 } else { 736 Builder.restoreIP( 737 PrivCB(InnerAllocaIP, Builder.saveIP(), V, *Inner, ReplacementValue)); 738 assert(ReplacementValue && 739 "Expected copy/create callback to set replacement value!"); 740 if (ReplacementValue == &V) 741 return; 742 } 743 744 for (Use *UPtr : Uses) 745 UPtr->set(ReplacementValue); 746 }; 747 748 // Reset the inner alloca insertion as it will be used for loading the values 749 // wrapped into pointers before passing them into the to-be-outlined region. 750 // Configure it to insert immediately after the fake use of zero address so 751 // that they are available in the generated body and so that the 752 // OpenMP-related values (thread ID and zero address pointers) remain leading 753 // in the argument list. 754 InnerAllocaIP = IRBuilder<>::InsertPoint( 755 ZeroAddrUse->getParent(), ZeroAddrUse->getNextNode()->getIterator()); 756 757 // Reset the outer alloca insertion point to the entry of the relevant block 758 // in case it was invalidated. 759 OuterAllocaIP = IRBuilder<>::InsertPoint( 760 OuterAllocaBlock, OuterAllocaBlock->getFirstInsertionPt()); 761 762 for (Value *Input : Inputs) { 763 LLVM_DEBUG(dbgs() << "Captured input: " << *Input << "\n"); 764 PrivHelper(*Input); 765 } 766 LLVM_DEBUG({ 767 for (Value *Output : Outputs) 768 LLVM_DEBUG(dbgs() << "Captured output: " << *Output << "\n"); 769 }); 770 assert(Outputs.empty() && 771 "OpenMP outlining should not produce live-out values!"); 772 773 LLVM_DEBUG(dbgs() << "After privatization: " << *OuterFn << "\n"); 774 LLVM_DEBUG({ 775 for (auto *BB : Blocks) 776 dbgs() << " PBR: " << BB->getName() << "\n"; 777 }); 778 779 // Register the outlined info. 780 addOutlineInfo(std::move(OI)); 781 782 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end()); 783 UI->eraseFromParent(); 784 785 return AfterIP; 786 } 787 788 void OpenMPIRBuilder::emitFlush(const LocationDescription &Loc) { 789 // Build call void __kmpc_flush(ident_t *loc) 790 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 791 Value *Args[] = {getOrCreateIdent(SrcLocStr)}; 792 793 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_flush), Args); 794 } 795 796 void OpenMPIRBuilder::createFlush(const LocationDescription &Loc) { 797 if (!updateToLocation(Loc)) 798 return; 799 emitFlush(Loc); 800 } 801 802 void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) { 803 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 804 // global_tid); 805 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 806 Value *Ident = getOrCreateIdent(SrcLocStr); 807 Value *Args[] = {Ident, getOrCreateThreadID(Ident)}; 808 809 // Ignore return result until untied tasks are supported. 810 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait), 811 Args); 812 } 813 814 void OpenMPIRBuilder::createTaskwait(const LocationDescription &Loc) { 815 if (!updateToLocation(Loc)) 816 return; 817 emitTaskwaitImpl(Loc); 818 } 819 820 void OpenMPIRBuilder::emitTaskyieldImpl(const LocationDescription &Loc) { 821 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 822 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 823 Value *Ident = getOrCreateIdent(SrcLocStr); 824 Constant *I32Null = ConstantInt::getNullValue(Int32); 825 Value *Args[] = {Ident, getOrCreateThreadID(Ident), I32Null}; 826 827 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskyield), 828 Args); 829 } 830 831 void OpenMPIRBuilder::createTaskyield(const LocationDescription &Loc) { 832 if (!updateToLocation(Loc)) 833 return; 834 emitTaskyieldImpl(Loc); 835 } 836 837 OpenMPIRBuilder::InsertPointTy 838 OpenMPIRBuilder::createMaster(const LocationDescription &Loc, 839 BodyGenCallbackTy BodyGenCB, 840 FinalizeCallbackTy FiniCB) { 841 842 if (!updateToLocation(Loc)) 843 return Loc.IP; 844 845 Directive OMPD = Directive::OMPD_master; 846 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 847 Value *Ident = getOrCreateIdent(SrcLocStr); 848 Value *ThreadId = getOrCreateThreadID(Ident); 849 Value *Args[] = {Ident, ThreadId}; 850 851 Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_master); 852 Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args); 853 854 Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_master); 855 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 856 857 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 858 /*Conditional*/ true, /*hasFinalize*/ true); 859 } 860 861 CanonicalLoopInfo *OpenMPIRBuilder::createLoopSkeleton( 862 DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, 863 BasicBlock *PostInsertBefore, const Twine &Name) { 864 Module *M = F->getParent(); 865 LLVMContext &Ctx = M->getContext(); 866 Type *IndVarTy = TripCount->getType(); 867 868 // Create the basic block structure. 869 BasicBlock *Preheader = 870 BasicBlock::Create(Ctx, "omp_" + Name + ".preheader", F, PreInsertBefore); 871 BasicBlock *Header = 872 BasicBlock::Create(Ctx, "omp_" + Name + ".header", F, PreInsertBefore); 873 BasicBlock *Cond = 874 BasicBlock::Create(Ctx, "omp_" + Name + ".cond", F, PreInsertBefore); 875 BasicBlock *Body = 876 BasicBlock::Create(Ctx, "omp_" + Name + ".body", F, PreInsertBefore); 877 BasicBlock *Latch = 878 BasicBlock::Create(Ctx, "omp_" + Name + ".inc", F, PostInsertBefore); 879 BasicBlock *Exit = 880 BasicBlock::Create(Ctx, "omp_" + Name + ".exit", F, PostInsertBefore); 881 BasicBlock *After = 882 BasicBlock::Create(Ctx, "omp_" + Name + ".after", F, PostInsertBefore); 883 884 // Use specified DebugLoc for new instructions. 885 Builder.SetCurrentDebugLocation(DL); 886 887 Builder.SetInsertPoint(Preheader); 888 Builder.CreateBr(Header); 889 890 Builder.SetInsertPoint(Header); 891 PHINode *IndVarPHI = Builder.CreatePHI(IndVarTy, 2, "omp_" + Name + ".iv"); 892 IndVarPHI->addIncoming(ConstantInt::get(IndVarTy, 0), Preheader); 893 Builder.CreateBr(Cond); 894 895 Builder.SetInsertPoint(Cond); 896 Value *Cmp = 897 Builder.CreateICmpULT(IndVarPHI, TripCount, "omp_" + Name + ".cmp"); 898 Builder.CreateCondBr(Cmp, Body, Exit); 899 900 Builder.SetInsertPoint(Body); 901 Builder.CreateBr(Latch); 902 903 Builder.SetInsertPoint(Latch); 904 Value *Next = Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1), 905 "omp_" + Name + ".next", /*HasNUW=*/true); 906 Builder.CreateBr(Header); 907 IndVarPHI->addIncoming(Next, Latch); 908 909 Builder.SetInsertPoint(Exit); 910 Builder.CreateBr(After); 911 912 // Remember and return the canonical control flow. 913 LoopInfos.emplace_front(); 914 CanonicalLoopInfo *CL = &LoopInfos.front(); 915 916 CL->Preheader = Preheader; 917 CL->Header = Header; 918 CL->Cond = Cond; 919 CL->Body = Body; 920 CL->Latch = Latch; 921 CL->Exit = Exit; 922 CL->After = After; 923 924 CL->IsValid = true; 925 926 #ifndef NDEBUG 927 CL->assertOK(); 928 #endif 929 return CL; 930 } 931 932 CanonicalLoopInfo * 933 OpenMPIRBuilder::createCanonicalLoop(const LocationDescription &Loc, 934 LoopBodyGenCallbackTy BodyGenCB, 935 Value *TripCount, const Twine &Name) { 936 BasicBlock *BB = Loc.IP.getBlock(); 937 BasicBlock *NextBB = BB->getNextNode(); 938 939 CanonicalLoopInfo *CL = createLoopSkeleton(Loc.DL, TripCount, BB->getParent(), 940 NextBB, NextBB, Name); 941 BasicBlock *After = CL->getAfter(); 942 943 // If location is not set, don't connect the loop. 944 if (updateToLocation(Loc)) { 945 // Split the loop at the insertion point: Branch to the preheader and move 946 // every following instruction to after the loop (the After BB). Also, the 947 // new successor is the loop's after block. 948 Builder.CreateBr(CL->Preheader); 949 After->getInstList().splice(After->begin(), BB->getInstList(), 950 Builder.GetInsertPoint(), BB->end()); 951 After->replaceSuccessorsPhiUsesWith(BB, After); 952 } 953 954 // Emit the body content. We do it after connecting the loop to the CFG to 955 // avoid that the callback encounters degenerate BBs. 956 BodyGenCB(CL->getBodyIP(), CL->getIndVar()); 957 958 #ifndef NDEBUG 959 CL->assertOK(); 960 #endif 961 return CL; 962 } 963 964 CanonicalLoopInfo *OpenMPIRBuilder::createCanonicalLoop( 965 const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, 966 Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, 967 InsertPointTy ComputeIP, const Twine &Name) { 968 969 // Consider the following difficulties (assuming 8-bit signed integers): 970 // * Adding \p Step to the loop counter which passes \p Stop may overflow: 971 // DO I = 1, 100, 50 972 /// * A \p Step of INT_MIN cannot not be normalized to a positive direction: 973 // DO I = 100, 0, -128 974 975 // Start, Stop and Step must be of the same integer type. 976 auto *IndVarTy = cast<IntegerType>(Start->getType()); 977 assert(IndVarTy == Stop->getType() && "Stop type mismatch"); 978 assert(IndVarTy == Step->getType() && "Step type mismatch"); 979 980 LocationDescription ComputeLoc = 981 ComputeIP.isSet() ? LocationDescription(ComputeIP, Loc.DL) : Loc; 982 updateToLocation(ComputeLoc); 983 984 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0); 985 ConstantInt *One = ConstantInt::get(IndVarTy, 1); 986 987 // Like Step, but always positive. 988 Value *Incr = Step; 989 990 // Distance between Start and Stop; always positive. 991 Value *Span; 992 993 // Condition whether there are no iterations are executed at all, e.g. because 994 // UB < LB. 995 Value *ZeroCmp; 996 997 if (IsSigned) { 998 // Ensure that increment is positive. If not, negate and invert LB and UB. 999 Value *IsNeg = Builder.CreateICmpSLT(Step, Zero); 1000 Incr = Builder.CreateSelect(IsNeg, Builder.CreateNeg(Step), Step); 1001 Value *LB = Builder.CreateSelect(IsNeg, Stop, Start); 1002 Value *UB = Builder.CreateSelect(IsNeg, Start, Stop); 1003 Span = Builder.CreateSub(UB, LB, "", false, true); 1004 ZeroCmp = Builder.CreateICmp( 1005 InclusiveStop ? CmpInst::ICMP_SLT : CmpInst::ICMP_SLE, UB, LB); 1006 } else { 1007 Span = Builder.CreateSub(Stop, Start, "", true); 1008 ZeroCmp = Builder.CreateICmp( 1009 InclusiveStop ? CmpInst::ICMP_ULT : CmpInst::ICMP_ULE, Stop, Start); 1010 } 1011 1012 Value *CountIfLooping; 1013 if (InclusiveStop) { 1014 CountIfLooping = Builder.CreateAdd(Builder.CreateUDiv(Span, Incr), One); 1015 } else { 1016 // Avoid incrementing past stop since it could overflow. 1017 Value *CountIfTwo = Builder.CreateAdd( 1018 Builder.CreateUDiv(Builder.CreateSub(Span, One), Incr), One); 1019 Value *OneCmp = Builder.CreateICmp( 1020 InclusiveStop ? CmpInst::ICMP_ULT : CmpInst::ICMP_ULE, Span, Incr); 1021 CountIfLooping = Builder.CreateSelect(OneCmp, One, CountIfTwo); 1022 } 1023 Value *TripCount = Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping, 1024 "omp_" + Name + ".tripcount"); 1025 1026 auto BodyGen = [=](InsertPointTy CodeGenIP, Value *IV) { 1027 Builder.restoreIP(CodeGenIP); 1028 Value *Span = Builder.CreateMul(IV, Step); 1029 Value *IndVar = Builder.CreateAdd(Span, Start); 1030 BodyGenCB(Builder.saveIP(), IndVar); 1031 }; 1032 LocationDescription LoopLoc = ComputeIP.isSet() ? Loc.IP : Builder.saveIP(); 1033 return createCanonicalLoop(LoopLoc, BodyGen, TripCount, Name); 1034 } 1035 1036 // Returns an LLVM function to call for initializing loop bounds using OpenMP 1037 // static scheduling depending on `type`. Only i32 and i64 are supported by the 1038 // runtime. Always interpret integers as unsigned similarly to 1039 // CanonicalLoopInfo. 1040 static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, 1041 OpenMPIRBuilder &OMPBuilder) { 1042 unsigned Bitwidth = Ty->getIntegerBitWidth(); 1043 if (Bitwidth == 32) 1044 return OMPBuilder.getOrCreateRuntimeFunction( 1045 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u); 1046 if (Bitwidth == 64) 1047 return OMPBuilder.getOrCreateRuntimeFunction( 1048 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u); 1049 llvm_unreachable("unknown OpenMP loop iterator bitwidth"); 1050 } 1051 1052 // Sets the number of loop iterations to the given value. This value must be 1053 // valid in the condition block (i.e., defined in the preheader) and is 1054 // interpreted as an unsigned integer. 1055 void setCanonicalLoopTripCount(CanonicalLoopInfo *CLI, Value *TripCount) { 1056 Instruction *CmpI = &CLI->getCond()->front(); 1057 assert(isa<CmpInst>(CmpI) && "First inst must compare IV with TripCount"); 1058 CmpI->setOperand(1, TripCount); 1059 CLI->assertOK(); 1060 } 1061 1062 CanonicalLoopInfo *OpenMPIRBuilder::createStaticWorkshareLoop( 1063 const LocationDescription &Loc, CanonicalLoopInfo *CLI, 1064 InsertPointTy AllocaIP, bool NeedsBarrier, Value *Chunk) { 1065 // Set up the source location value for OpenMP runtime. 1066 if (!updateToLocation(Loc)) 1067 return nullptr; 1068 1069 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1070 Value *SrcLoc = getOrCreateIdent(SrcLocStr); 1071 1072 // Declare useful OpenMP runtime functions. 1073 Value *IV = CLI->getIndVar(); 1074 Type *IVTy = IV->getType(); 1075 FunctionCallee StaticInit = getKmpcForStaticInitForType(IVTy, M, *this); 1076 FunctionCallee StaticFini = 1077 getOrCreateRuntimeFunction(M, omp::OMPRTL___kmpc_for_static_fini); 1078 1079 // Allocate space for computed loop bounds as expected by the "init" function. 1080 Builder.restoreIP(AllocaIP); 1081 Type *I32Type = Type::getInt32Ty(M.getContext()); 1082 Value *PLastIter = Builder.CreateAlloca(I32Type, nullptr, "p.lastiter"); 1083 Value *PLowerBound = Builder.CreateAlloca(IVTy, nullptr, "p.lowerbound"); 1084 Value *PUpperBound = Builder.CreateAlloca(IVTy, nullptr, "p.upperbound"); 1085 Value *PStride = Builder.CreateAlloca(IVTy, nullptr, "p.stride"); 1086 1087 // At the end of the preheader, prepare for calling the "init" function by 1088 // storing the current loop bounds into the allocated space. A canonical loop 1089 // always iterates from 0 to trip-count with step 1. Note that "init" expects 1090 // and produces an inclusive upper bound. 1091 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator()); 1092 Constant *Zero = ConstantInt::get(IVTy, 0); 1093 Constant *One = ConstantInt::get(IVTy, 1); 1094 Builder.CreateStore(Zero, PLowerBound); 1095 Value *UpperBound = Builder.CreateSub(CLI->getTripCount(), One); 1096 Builder.CreateStore(UpperBound, PUpperBound); 1097 Builder.CreateStore(One, PStride); 1098 1099 if (!Chunk) 1100 Chunk = One; 1101 1102 Value *ThreadNum = getOrCreateThreadID(SrcLoc); 1103 1104 // TODO: extract scheduling type and map it to OMP constant. This is curently 1105 // happening in kmp.h and its ilk and needs to be moved to OpenMP.td first. 1106 constexpr int StaticSchedType = 34; 1107 Constant *SchedulingType = ConstantInt::get(I32Type, StaticSchedType); 1108 1109 // Call the "init" function and update the trip count of the loop with the 1110 // value it produced. 1111 Builder.CreateCall(StaticInit, 1112 {SrcLoc, ThreadNum, SchedulingType, PLastIter, PLowerBound, 1113 PUpperBound, PStride, One, Chunk}); 1114 Value *LowerBound = Builder.CreateLoad(PLowerBound); 1115 Value *InclusiveUpperBound = Builder.CreateLoad(PUpperBound); 1116 Value *TripCountMinusOne = Builder.CreateSub(InclusiveUpperBound, LowerBound); 1117 Value *TripCount = Builder.CreateAdd(TripCountMinusOne, One); 1118 setCanonicalLoopTripCount(CLI, TripCount); 1119 1120 // Update all uses of the induction variable except the one in the condition 1121 // block that compares it with the actual upper bound, and the increment in 1122 // the latch block. 1123 // TODO: this can eventually move to CanonicalLoopInfo or to a new 1124 // CanonicalLoopInfoUpdater interface. 1125 Builder.SetInsertPoint(CLI->getBody(), CLI->getBody()->getFirstInsertionPt()); 1126 Value *UpdatedIV = Builder.CreateAdd(IV, LowerBound); 1127 IV->replaceUsesWithIf(UpdatedIV, [&](Use &U) { 1128 auto *Instr = dyn_cast<Instruction>(U.getUser()); 1129 return !Instr || 1130 (Instr->getParent() != CLI->getCond() && 1131 Instr->getParent() != CLI->getLatch() && Instr != UpdatedIV); 1132 }); 1133 1134 // In the "exit" block, call the "fini" function. 1135 Builder.SetInsertPoint(CLI->getExit(), 1136 CLI->getExit()->getTerminator()->getIterator()); 1137 Builder.CreateCall(StaticFini, {SrcLoc, ThreadNum}); 1138 1139 // Add the barrier if requested. 1140 if (NeedsBarrier) 1141 createBarrier(LocationDescription(Builder.saveIP(), Loc.DL), 1142 omp::Directive::OMPD_for, /* ForceSimpleCall */ false, 1143 /* CheckCancelFlag */ false); 1144 1145 CLI->assertOK(); 1146 return CLI; 1147 } 1148 1149 OpenMPIRBuilder::InsertPointTy 1150 OpenMPIRBuilder::createCopyPrivate(const LocationDescription &Loc, 1151 llvm::Value *BufSize, llvm::Value *CpyBuf, 1152 llvm::Value *CpyFn, llvm::Value *DidIt) { 1153 if (!updateToLocation(Loc)) 1154 return Loc.IP; 1155 1156 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1157 Value *Ident = getOrCreateIdent(SrcLocStr); 1158 Value *ThreadId = getOrCreateThreadID(Ident); 1159 1160 llvm::Value *DidItLD = Builder.CreateLoad(DidIt); 1161 1162 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD}; 1163 1164 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_copyprivate); 1165 Builder.CreateCall(Fn, Args); 1166 1167 return Builder.saveIP(); 1168 } 1169 1170 OpenMPIRBuilder::InsertPointTy 1171 OpenMPIRBuilder::createSingle(const LocationDescription &Loc, 1172 BodyGenCallbackTy BodyGenCB, 1173 FinalizeCallbackTy FiniCB, llvm::Value *DidIt) { 1174 1175 if (!updateToLocation(Loc)) 1176 return Loc.IP; 1177 1178 // If needed (i.e. not null), initialize `DidIt` with 0 1179 if (DidIt) { 1180 Builder.CreateStore(Builder.getInt32(0), DidIt); 1181 } 1182 1183 Directive OMPD = Directive::OMPD_single; 1184 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1185 Value *Ident = getOrCreateIdent(SrcLocStr); 1186 Value *ThreadId = getOrCreateThreadID(Ident); 1187 Value *Args[] = {Ident, ThreadId}; 1188 1189 Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_single); 1190 Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args); 1191 1192 Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_single); 1193 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 1194 1195 // generates the following: 1196 // if (__kmpc_single()) { 1197 // .... single region ... 1198 // __kmpc_end_single 1199 // } 1200 1201 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 1202 /*Conditional*/ true, /*hasFinalize*/ true); 1203 } 1204 1205 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCritical( 1206 const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, 1207 FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) { 1208 1209 if (!updateToLocation(Loc)) 1210 return Loc.IP; 1211 1212 Directive OMPD = Directive::OMPD_critical; 1213 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1214 Value *Ident = getOrCreateIdent(SrcLocStr); 1215 Value *ThreadId = getOrCreateThreadID(Ident); 1216 Value *LockVar = getOMPCriticalRegionLock(CriticalName); 1217 Value *Args[] = {Ident, ThreadId, LockVar}; 1218 1219 SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args)); 1220 Function *RTFn = nullptr; 1221 if (HintInst) { 1222 // Add Hint to entry Args and create call 1223 EnterArgs.push_back(HintInst); 1224 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical_with_hint); 1225 } else { 1226 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical); 1227 } 1228 Instruction *EntryCall = Builder.CreateCall(RTFn, EnterArgs); 1229 1230 Function *ExitRTLFn = 1231 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_critical); 1232 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 1233 1234 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 1235 /*Conditional*/ false, /*hasFinalize*/ true); 1236 } 1237 1238 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion( 1239 Directive OMPD, Instruction *EntryCall, Instruction *ExitCall, 1240 BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool Conditional, 1241 bool HasFinalize) { 1242 1243 if (HasFinalize) 1244 FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false}); 1245 1246 // Create inlined region's entry and body blocks, in preparation 1247 // for conditional creation 1248 BasicBlock *EntryBB = Builder.GetInsertBlock(); 1249 Instruction *SplitPos = EntryBB->getTerminator(); 1250 if (!isa_and_nonnull<BranchInst>(SplitPos)) 1251 SplitPos = new UnreachableInst(Builder.getContext(), EntryBB); 1252 BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end"); 1253 BasicBlock *FiniBB = 1254 EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize"); 1255 1256 Builder.SetInsertPoint(EntryBB->getTerminator()); 1257 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional); 1258 1259 // generate body 1260 BodyGenCB(/* AllocaIP */ InsertPointTy(), 1261 /* CodeGenIP */ Builder.saveIP(), *FiniBB); 1262 1263 // If we didn't emit a branch to FiniBB during body generation, it means 1264 // FiniBB is unreachable (e.g. while(1);). stop generating all the 1265 // unreachable blocks, and remove anything we are not going to use. 1266 auto SkipEmittingRegion = FiniBB->hasNPredecessors(0); 1267 if (SkipEmittingRegion) { 1268 FiniBB->eraseFromParent(); 1269 ExitCall->eraseFromParent(); 1270 // Discard finalization if we have it. 1271 if (HasFinalize) { 1272 assert(!FinalizationStack.empty() && 1273 "Unexpected finalization stack state!"); 1274 FinalizationStack.pop_back(); 1275 } 1276 } else { 1277 // emit exit call and do any needed finalization. 1278 auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt()); 1279 assert(FiniBB->getTerminator()->getNumSuccessors() == 1 && 1280 FiniBB->getTerminator()->getSuccessor(0) == ExitBB && 1281 "Unexpected control flow graph state!!"); 1282 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize); 1283 assert(FiniBB->getUniquePredecessor()->getUniqueSuccessor() == FiniBB && 1284 "Unexpected Control Flow State!"); 1285 MergeBlockIntoPredecessor(FiniBB); 1286 } 1287 1288 // If we are skipping the region of a non conditional, remove the exit 1289 // block, and clear the builder's insertion point. 1290 assert(SplitPos->getParent() == ExitBB && 1291 "Unexpected Insertion point location!"); 1292 if (!Conditional && SkipEmittingRegion) { 1293 ExitBB->eraseFromParent(); 1294 Builder.ClearInsertionPoint(); 1295 } else { 1296 auto merged = MergeBlockIntoPredecessor(ExitBB); 1297 BasicBlock *ExitPredBB = SplitPos->getParent(); 1298 auto InsertBB = merged ? ExitPredBB : ExitBB; 1299 if (!isa_and_nonnull<BranchInst>(SplitPos)) 1300 SplitPos->eraseFromParent(); 1301 Builder.SetInsertPoint(InsertBB); 1302 } 1303 1304 return Builder.saveIP(); 1305 } 1306 1307 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry( 1308 Directive OMPD, Value *EntryCall, BasicBlock *ExitBB, bool Conditional) { 1309 1310 // if nothing to do, Return current insertion point. 1311 if (!Conditional) 1312 return Builder.saveIP(); 1313 1314 BasicBlock *EntryBB = Builder.GetInsertBlock(); 1315 Value *CallBool = Builder.CreateIsNotNull(EntryCall); 1316 auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body"); 1317 auto *UI = new UnreachableInst(Builder.getContext(), ThenBB); 1318 1319 // Emit thenBB and set the Builder's insertion point there for 1320 // body generation next. Place the block after the current block. 1321 Function *CurFn = EntryBB->getParent(); 1322 CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB); 1323 1324 // Move Entry branch to end of ThenBB, and replace with conditional 1325 // branch (If-stmt) 1326 Instruction *EntryBBTI = EntryBB->getTerminator(); 1327 Builder.CreateCondBr(CallBool, ThenBB, ExitBB); 1328 EntryBBTI->removeFromParent(); 1329 Builder.SetInsertPoint(UI); 1330 Builder.Insert(EntryBBTI); 1331 UI->eraseFromParent(); 1332 Builder.SetInsertPoint(ThenBB->getTerminator()); 1333 1334 // return an insertion point to ExitBB. 1335 return IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt()); 1336 } 1337 1338 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit( 1339 omp::Directive OMPD, InsertPointTy FinIP, Instruction *ExitCall, 1340 bool HasFinalize) { 1341 1342 Builder.restoreIP(FinIP); 1343 1344 // If there is finalization to do, emit it before the exit call 1345 if (HasFinalize) { 1346 assert(!FinalizationStack.empty() && 1347 "Unexpected finalization stack state!"); 1348 1349 FinalizationInfo Fi = FinalizationStack.pop_back_val(); 1350 assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!"); 1351 1352 Fi.FiniCB(FinIP); 1353 1354 BasicBlock *FiniBB = FinIP.getBlock(); 1355 Instruction *FiniBBTI = FiniBB->getTerminator(); 1356 1357 // set Builder IP for call creation 1358 Builder.SetInsertPoint(FiniBBTI); 1359 } 1360 1361 // place the Exitcall as last instruction before Finalization block terminator 1362 ExitCall->removeFromParent(); 1363 Builder.Insert(ExitCall); 1364 1365 return IRBuilder<>::InsertPoint(ExitCall->getParent(), 1366 ExitCall->getIterator()); 1367 } 1368 1369 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCopyinClauseBlocks( 1370 InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, 1371 llvm::IntegerType *IntPtrTy, bool BranchtoEnd) { 1372 if (!IP.isSet()) 1373 return IP; 1374 1375 IRBuilder<>::InsertPointGuard IPG(Builder); 1376 1377 // creates the following CFG structure 1378 // OMP_Entry : (MasterAddr != PrivateAddr)? 1379 // F T 1380 // | \ 1381 // | copin.not.master 1382 // | / 1383 // v / 1384 // copyin.not.master.end 1385 // | 1386 // v 1387 // OMP.Entry.Next 1388 1389 BasicBlock *OMP_Entry = IP.getBlock(); 1390 Function *CurFn = OMP_Entry->getParent(); 1391 BasicBlock *CopyBegin = 1392 BasicBlock::Create(M.getContext(), "copyin.not.master", CurFn); 1393 BasicBlock *CopyEnd = nullptr; 1394 1395 // If entry block is terminated, split to preserve the branch to following 1396 // basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is. 1397 if (isa_and_nonnull<BranchInst>(OMP_Entry->getTerminator())) { 1398 CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(), 1399 "copyin.not.master.end"); 1400 OMP_Entry->getTerminator()->eraseFromParent(); 1401 } else { 1402 CopyEnd = 1403 BasicBlock::Create(M.getContext(), "copyin.not.master.end", CurFn); 1404 } 1405 1406 Builder.SetInsertPoint(OMP_Entry); 1407 Value *MasterPtr = Builder.CreatePtrToInt(MasterAddr, IntPtrTy); 1408 Value *PrivatePtr = Builder.CreatePtrToInt(PrivateAddr, IntPtrTy); 1409 Value *cmp = Builder.CreateICmpNE(MasterPtr, PrivatePtr); 1410 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd); 1411 1412 Builder.SetInsertPoint(CopyBegin); 1413 if (BranchtoEnd) 1414 Builder.SetInsertPoint(Builder.CreateBr(CopyEnd)); 1415 1416 return Builder.saveIP(); 1417 } 1418 1419 CallInst *OpenMPIRBuilder::createOMPAlloc(const LocationDescription &Loc, 1420 Value *Size, Value *Allocator, 1421 std::string Name) { 1422 IRBuilder<>::InsertPointGuard IPG(Builder); 1423 Builder.restoreIP(Loc.IP); 1424 1425 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1426 Value *Ident = getOrCreateIdent(SrcLocStr); 1427 Value *ThreadId = getOrCreateThreadID(Ident); 1428 Value *Args[] = {ThreadId, Size, Allocator}; 1429 1430 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_alloc); 1431 1432 return Builder.CreateCall(Fn, Args, Name); 1433 } 1434 1435 CallInst *OpenMPIRBuilder::createOMPFree(const LocationDescription &Loc, 1436 Value *Addr, Value *Allocator, 1437 std::string Name) { 1438 IRBuilder<>::InsertPointGuard IPG(Builder); 1439 Builder.restoreIP(Loc.IP); 1440 1441 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1442 Value *Ident = getOrCreateIdent(SrcLocStr); 1443 Value *ThreadId = getOrCreateThreadID(Ident); 1444 Value *Args[] = {ThreadId, Addr, Allocator}; 1445 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_free); 1446 return Builder.CreateCall(Fn, Args, Name); 1447 } 1448 1449 CallInst *OpenMPIRBuilder::createCachedThreadPrivate( 1450 const LocationDescription &Loc, llvm::Value *Pointer, 1451 llvm::ConstantInt *Size, const llvm::Twine &Name) { 1452 IRBuilder<>::InsertPointGuard IPG(Builder); 1453 Builder.restoreIP(Loc.IP); 1454 1455 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1456 Value *Ident = getOrCreateIdent(SrcLocStr); 1457 Value *ThreadId = getOrCreateThreadID(Ident); 1458 Constant *ThreadPrivateCache = 1459 getOrCreateOMPInternalVariable(Int8PtrPtr, Name); 1460 llvm::Value *Args[] = {Ident, ThreadId, Pointer, Size, ThreadPrivateCache}; 1461 1462 Function *Fn = 1463 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_threadprivate_cached); 1464 1465 return Builder.CreateCall(Fn, Args); 1466 } 1467 1468 std::string OpenMPIRBuilder::getNameWithSeparators(ArrayRef<StringRef> Parts, 1469 StringRef FirstSeparator, 1470 StringRef Separator) { 1471 SmallString<128> Buffer; 1472 llvm::raw_svector_ostream OS(Buffer); 1473 StringRef Sep = FirstSeparator; 1474 for (StringRef Part : Parts) { 1475 OS << Sep << Part; 1476 Sep = Separator; 1477 } 1478 return OS.str().str(); 1479 } 1480 1481 Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable( 1482 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 1483 // TODO: Replace the twine arg with stringref to get rid of the conversion 1484 // logic. However This is taken from current implementation in clang as is. 1485 // Since this method is used in many places exclusively for OMP internal use 1486 // we will keep it as is for temporarily until we move all users to the 1487 // builder and then, if possible, fix it everywhere in one go. 1488 SmallString<256> Buffer; 1489 llvm::raw_svector_ostream Out(Buffer); 1490 Out << Name; 1491 StringRef RuntimeName = Out.str(); 1492 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 1493 if (Elem.second) { 1494 assert(Elem.second->getType()->getPointerElementType() == Ty && 1495 "OMP internal variable has different type than requested"); 1496 } else { 1497 // TODO: investigate the appropriate linkage type used for the global 1498 // variable for possibly changing that to internal or private, or maybe 1499 // create different versions of the function for different OMP internal 1500 // variables. 1501 Elem.second = new llvm::GlobalVariable( 1502 M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage, 1503 llvm::Constant::getNullValue(Ty), Elem.first(), 1504 /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, 1505 AddressSpace); 1506 } 1507 1508 return Elem.second; 1509 } 1510 1511 Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) { 1512 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 1513 std::string Name = getNameWithSeparators({Prefix, "var"}, ".", "."); 1514 return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name); 1515 } 1516 1517 // Create all simple and struct types exposed by the runtime and remember 1518 // the llvm::PointerTypes of them for easy access later. 1519 void OpenMPIRBuilder::initializeTypes(Module &M) { 1520 LLVMContext &Ctx = M.getContext(); 1521 StructType *T; 1522 #define OMP_TYPE(VarName, InitValue) VarName = InitValue; 1523 #define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ 1524 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \ 1525 VarName##PtrTy = PointerType::getUnqual(VarName##Ty); 1526 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \ 1527 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \ 1528 VarName##Ptr = PointerType::getUnqual(VarName); 1529 #define OMP_STRUCT_TYPE(VarName, StructName, ...) \ 1530 T = StructType::getTypeByName(Ctx, StructName); \ 1531 if (!T) \ 1532 T = StructType::create(Ctx, {__VA_ARGS__}, StructName); \ 1533 VarName = T; \ 1534 VarName##Ptr = PointerType::getUnqual(T); 1535 #include "llvm/Frontend/OpenMP/OMPKinds.def" 1536 } 1537 1538 void OpenMPIRBuilder::OutlineInfo::collectBlocks( 1539 SmallPtrSetImpl<BasicBlock *> &BlockSet, 1540 SmallVectorImpl<BasicBlock *> &BlockVector) { 1541 SmallVector<BasicBlock *, 32> Worklist; 1542 BlockSet.insert(EntryBB); 1543 BlockSet.insert(ExitBB); 1544 1545 Worklist.push_back(EntryBB); 1546 while (!Worklist.empty()) { 1547 BasicBlock *BB = Worklist.pop_back_val(); 1548 BlockVector.push_back(BB); 1549 for (BasicBlock *SuccBB : successors(BB)) 1550 if (BlockSet.insert(SuccBB).second) 1551 Worklist.push_back(SuccBB); 1552 } 1553 } 1554 1555 void CanonicalLoopInfo::assertOK() const { 1556 #ifndef NDEBUG 1557 if (!IsValid) 1558 return; 1559 1560 // Verify standard control-flow we use for OpenMP loops. 1561 assert(Preheader); 1562 assert(isa<BranchInst>(Preheader->getTerminator()) && 1563 "Preheader must terminate with unconditional branch"); 1564 assert(Preheader->getSingleSuccessor() == Header && 1565 "Preheader must jump to header"); 1566 1567 assert(Header); 1568 assert(isa<BranchInst>(Header->getTerminator()) && 1569 "Header must terminate with unconditional branch"); 1570 assert(Header->getSingleSuccessor() == Cond && 1571 "Header must jump to exiting block"); 1572 1573 assert(Cond); 1574 assert(Cond->getSinglePredecessor() == Header && 1575 "Exiting block only reachable from header"); 1576 1577 assert(isa<BranchInst>(Cond->getTerminator()) && 1578 "Exiting block must terminate with conditional branch"); 1579 assert(size(successors(Cond)) == 2 && 1580 "Exiting block must have two successors"); 1581 assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(0) == Body && 1582 "Exiting block's first successor jump to the body"); 1583 assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(1) == Exit && 1584 "Exiting block's second successor must exit the loop"); 1585 1586 assert(Body); 1587 assert(Body->getSinglePredecessor() == Cond && 1588 "Body only reachable from exiting block"); 1589 1590 assert(Latch); 1591 assert(isa<BranchInst>(Latch->getTerminator()) && 1592 "Latch must terminate with unconditional branch"); 1593 assert(Latch->getSingleSuccessor() == Header && "Latch must jump to header"); 1594 1595 assert(Exit); 1596 assert(isa<BranchInst>(Exit->getTerminator()) && 1597 "Exit block must terminate with unconditional branch"); 1598 assert(Exit->getSingleSuccessor() == After && 1599 "Exit block must jump to after block"); 1600 1601 assert(After); 1602 assert(After->getSinglePredecessor() == Exit && 1603 "After block only reachable from exit block"); 1604 1605 Instruction *IndVar = getIndVar(); 1606 assert(IndVar && "Canonical induction variable not found?"); 1607 assert(isa<IntegerType>(IndVar->getType()) && 1608 "Induction variable must be an integer"); 1609 assert(cast<PHINode>(IndVar)->getParent() == Header && 1610 "Induction variable must be a PHI in the loop header"); 1611 1612 Value *TripCount = getTripCount(); 1613 assert(TripCount && "Loop trip count not found?"); 1614 assert(IndVar->getType() == TripCount->getType() && 1615 "Trip count and induction variable must have the same type"); 1616 1617 auto *CmpI = cast<CmpInst>(&Cond->front()); 1618 assert(CmpI->getPredicate() == CmpInst::ICMP_ULT && 1619 "Exit condition must be a signed less-than comparison"); 1620 assert(CmpI->getOperand(0) == IndVar && 1621 "Exit condition must compare the induction variable"); 1622 assert(CmpI->getOperand(1) == TripCount && 1623 "Exit condition must compare with the trip count"); 1624 #endif 1625 } 1626