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/IR/CFG.h" 20 #include "llvm/IR/DebugInfo.h" 21 #include "llvm/IR/IRBuilder.h" 22 #include "llvm/IR/MDBuilder.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 26 #include "llvm/Transforms/Utils/CodeExtractor.h" 27 28 #include <sstream> 29 30 #define DEBUG_TYPE "openmp-ir-builder" 31 32 using namespace llvm; 33 using namespace omp; 34 35 static cl::opt<bool> 36 OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, 37 cl::desc("Use optimistic attributes describing " 38 "'as-if' properties of runtime calls."), 39 cl::init(false)); 40 41 void OpenMPIRBuilder::addAttributes(omp::RuntimeFunction FnID, Function &Fn) { 42 LLVMContext &Ctx = Fn.getContext(); 43 44 #define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet; 45 #include "llvm/Frontend/OpenMP/OMPKinds.def" 46 47 // Add attributes to the new declaration. 48 switch (FnID) { 49 #define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \ 50 case Enum: \ 51 Fn.setAttributes( \ 52 AttributeList::get(Ctx, FnAttrSet, RetAttrSet, ArgAttrSets)); \ 53 break; 54 #include "llvm/Frontend/OpenMP/OMPKinds.def" 55 default: 56 // Attributes are optional. 57 break; 58 } 59 } 60 61 FunctionCallee 62 OpenMPIRBuilder::getOrCreateRuntimeFunction(Module &M, RuntimeFunction FnID) { 63 FunctionType *FnTy = nullptr; 64 Function *Fn = nullptr; 65 66 // Try to find the declation in the module first. 67 switch (FnID) { 68 #define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \ 69 case Enum: \ 70 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \ 71 IsVarArg); \ 72 Fn = M.getFunction(Str); \ 73 break; 74 #include "llvm/Frontend/OpenMP/OMPKinds.def" 75 } 76 77 if (!Fn) { 78 // Create a new declaration if we need one. 79 switch (FnID) { 80 #define OMP_RTL(Enum, Str, ...) \ 81 case Enum: \ 82 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \ 83 break; 84 #include "llvm/Frontend/OpenMP/OMPKinds.def" 85 } 86 87 // Add information if the runtime function takes a callback function 88 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) { 89 if (!Fn->hasMetadata(LLVMContext::MD_callback)) { 90 LLVMContext &Ctx = Fn->getContext(); 91 MDBuilder MDB(Ctx); 92 // Annotate the callback behavior of the runtime function: 93 // - The callback callee is argument number 2 (microtask). 94 // - The first two arguments of the callback callee are unknown (-1). 95 // - All variadic arguments to the runtime function are passed to the 96 // callback callee. 97 Fn->addMetadata( 98 LLVMContext::MD_callback, 99 *MDNode::get(Ctx, {MDB.createCallbackEncoding( 100 2, {-1, -1}, /* VarArgsArePassed */ true)})); 101 } 102 } 103 104 LLVM_DEBUG(dbgs() << "Created OpenMP runtime function " << Fn->getName() 105 << " with type " << *Fn->getFunctionType() << "\n"); 106 addAttributes(FnID, *Fn); 107 108 } else { 109 LLVM_DEBUG(dbgs() << "Found OpenMP runtime function " << Fn->getName() 110 << " with type " << *Fn->getFunctionType() << "\n"); 111 } 112 113 assert(Fn && "Failed to create OpenMP runtime function"); 114 115 // Cast the function to the expected type if necessary 116 Constant *C = ConstantExpr::getBitCast(Fn, FnTy->getPointerTo()); 117 return {FnTy, C}; 118 } 119 120 Function *OpenMPIRBuilder::getOrCreateRuntimeFunctionPtr(RuntimeFunction FnID) { 121 FunctionCallee RTLFn = getOrCreateRuntimeFunction(M, FnID); 122 auto *Fn = dyn_cast<llvm::Function>(RTLFn.getCallee()); 123 assert(Fn && "Failed to create OpenMP runtime function pointer"); 124 return Fn; 125 } 126 127 void OpenMPIRBuilder::initialize() { initializeTypes(M); } 128 129 void OpenMPIRBuilder::finalize() { 130 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet; 131 SmallVector<BasicBlock *, 32> Blocks; 132 for (OutlineInfo &OI : OutlineInfos) { 133 ParallelRegionBlockSet.clear(); 134 Blocks.clear(); 135 OI.collectBlocks(ParallelRegionBlockSet, Blocks); 136 137 Function *OuterFn = OI.EntryBB->getParent(); 138 CodeExtractorAnalysisCache CEAC(*OuterFn); 139 CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr, 140 /* AggregateArgs */ false, 141 /* BlockFrequencyInfo */ nullptr, 142 /* BranchProbabilityInfo */ nullptr, 143 /* AssumptionCache */ nullptr, 144 /* AllowVarArgs */ true, 145 /* AllowAlloca */ true, 146 /* Suffix */ ".omp_par"); 147 148 LLVM_DEBUG(dbgs() << "Before outlining: " << *OuterFn << "\n"); 149 LLVM_DEBUG(dbgs() << "Entry " << OI.EntryBB->getName() 150 << " Exit: " << OI.ExitBB->getName() << "\n"); 151 assert(Extractor.isEligible() && 152 "Expected OpenMP outlining to be possible!"); 153 154 Function *OutlinedFn = Extractor.extractCodeRegion(CEAC); 155 156 LLVM_DEBUG(dbgs() << "After outlining: " << *OuterFn << "\n"); 157 LLVM_DEBUG(dbgs() << " Outlined function: " << *OutlinedFn << "\n"); 158 assert(OutlinedFn->getReturnType()->isVoidTy() && 159 "OpenMP outlined functions should not return a value!"); 160 161 // For compability with the clang CG we move the outlined function after the 162 // one with the parallel region. 163 OutlinedFn->removeFromParent(); 164 M.getFunctionList().insertAfter(OuterFn->getIterator(), OutlinedFn); 165 166 // Remove the artificial entry introduced by the extractor right away, we 167 // made our own entry block after all. 168 { 169 BasicBlock &ArtificialEntry = OutlinedFn->getEntryBlock(); 170 assert(ArtificialEntry.getUniqueSuccessor() == OI.EntryBB); 171 assert(OI.EntryBB->getUniquePredecessor() == &ArtificialEntry); 172 OI.EntryBB->moveBefore(&ArtificialEntry); 173 ArtificialEntry.eraseFromParent(); 174 } 175 assert(&OutlinedFn->getEntryBlock() == OI.EntryBB); 176 assert(OutlinedFn && OutlinedFn->getNumUses() == 1); 177 178 // Run a user callback, e.g. to add attributes. 179 if (OI.PostOutlineCB) 180 OI.PostOutlineCB(*OutlinedFn); 181 } 182 183 // Allow finalize to be called multiple times. 184 OutlineInfos.clear(); 185 } 186 187 Value *OpenMPIRBuilder::getOrCreateIdent(Constant *SrcLocStr, 188 IdentFlag LocFlags, 189 unsigned Reserve2Flags) { 190 // Enable "C-mode". 191 LocFlags |= OMP_IDENT_FLAG_KMPC; 192 193 Value *&Ident = 194 IdentMap[{SrcLocStr, uint64_t(LocFlags) << 31 | Reserve2Flags}]; 195 if (!Ident) { 196 Constant *I32Null = ConstantInt::getNullValue(Int32); 197 Constant *IdentData[] = { 198 I32Null, ConstantInt::get(Int32, uint32_t(LocFlags)), 199 ConstantInt::get(Int32, Reserve2Flags), I32Null, SrcLocStr}; 200 Constant *Initializer = ConstantStruct::get( 201 cast<StructType>(IdentPtr->getPointerElementType()), IdentData); 202 203 // Look for existing encoding of the location + flags, not needed but 204 // minimizes the difference to the existing solution while we transition. 205 for (GlobalVariable &GV : M.getGlobalList()) 206 if (GV.getType() == IdentPtr && GV.hasInitializer()) 207 if (GV.getInitializer() == Initializer) 208 return Ident = &GV; 209 210 auto *GV = new GlobalVariable(M, IdentPtr->getPointerElementType(), 211 /* isConstant = */ true, 212 GlobalValue::PrivateLinkage, Initializer); 213 GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 214 GV->setAlignment(Align(8)); 215 Ident = GV; 216 } 217 return Ident; 218 } 219 220 Constant *OpenMPIRBuilder::getOrCreateSrcLocStr(StringRef LocStr) { 221 Constant *&SrcLocStr = SrcLocStrMap[LocStr]; 222 if (!SrcLocStr) { 223 Constant *Initializer = 224 ConstantDataArray::getString(M.getContext(), LocStr); 225 226 // Look for existing encoding of the location, not needed but minimizes the 227 // difference to the existing solution while we transition. 228 for (GlobalVariable &GV : M.getGlobalList()) 229 if (GV.isConstant() && GV.hasInitializer() && 230 GV.getInitializer() == Initializer) 231 return SrcLocStr = ConstantExpr::getPointerCast(&GV, Int8Ptr); 232 233 SrcLocStr = Builder.CreateGlobalStringPtr(LocStr, /* Name */ "", 234 /* AddressSpace */ 0, &M); 235 } 236 return SrcLocStr; 237 } 238 239 Constant *OpenMPIRBuilder::getOrCreateSrcLocStr(StringRef FunctionName, 240 StringRef FileName, 241 unsigned Line, 242 unsigned Column) { 243 SmallString<128> Buffer; 244 Buffer.push_back(';'); 245 Buffer.append(FileName); 246 Buffer.push_back(';'); 247 Buffer.append(FunctionName); 248 Buffer.push_back(';'); 249 Buffer.append(std::to_string(Line)); 250 Buffer.push_back(';'); 251 Buffer.append(std::to_string(Column)); 252 Buffer.push_back(';'); 253 Buffer.push_back(';'); 254 return getOrCreateSrcLocStr(Buffer.str()); 255 } 256 257 Constant *OpenMPIRBuilder::getOrCreateDefaultSrcLocStr() { 258 return getOrCreateSrcLocStr(";unknown;unknown;0;0;;"); 259 } 260 261 Constant * 262 OpenMPIRBuilder::getOrCreateSrcLocStr(const LocationDescription &Loc) { 263 DILocation *DIL = Loc.DL.get(); 264 if (!DIL) 265 return getOrCreateDefaultSrcLocStr(); 266 StringRef FileName = 267 !DIL->getFilename().empty() ? DIL->getFilename() : M.getName(); 268 StringRef Function = DIL->getScope()->getSubprogram()->getName(); 269 Function = 270 !Function.empty() ? Function : Loc.IP.getBlock()->getParent()->getName(); 271 return getOrCreateSrcLocStr(Function, FileName, DIL->getLine(), 272 DIL->getColumn()); 273 } 274 275 Value *OpenMPIRBuilder::getOrCreateThreadID(Value *Ident) { 276 return Builder.CreateCall( 277 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_global_thread_num), Ident, 278 "omp_global_thread_num"); 279 } 280 281 OpenMPIRBuilder::InsertPointTy 282 OpenMPIRBuilder::CreateBarrier(const LocationDescription &Loc, Directive DK, 283 bool ForceSimpleCall, bool CheckCancelFlag) { 284 if (!updateToLocation(Loc)) 285 return Loc.IP; 286 return emitBarrierImpl(Loc, DK, ForceSimpleCall, CheckCancelFlag); 287 } 288 289 OpenMPIRBuilder::InsertPointTy 290 OpenMPIRBuilder::emitBarrierImpl(const LocationDescription &Loc, Directive Kind, 291 bool ForceSimpleCall, bool CheckCancelFlag) { 292 // Build call __kmpc_cancel_barrier(loc, thread_id) or 293 // __kmpc_barrier(loc, thread_id); 294 295 IdentFlag BarrierLocFlags; 296 switch (Kind) { 297 case OMPD_for: 298 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR; 299 break; 300 case OMPD_sections: 301 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS; 302 break; 303 case OMPD_single: 304 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE; 305 break; 306 case OMPD_barrier: 307 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL; 308 break; 309 default: 310 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL; 311 break; 312 } 313 314 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 315 Value *Args[] = {getOrCreateIdent(SrcLocStr, BarrierLocFlags), 316 getOrCreateThreadID(getOrCreateIdent(SrcLocStr))}; 317 318 // If we are in a cancellable parallel region, barriers are cancellation 319 // points. 320 // TODO: Check why we would force simple calls or to ignore the cancel flag. 321 bool UseCancelBarrier = 322 !ForceSimpleCall && isLastFinalizationInfoCancellable(OMPD_parallel); 323 324 Value *Result = 325 Builder.CreateCall(getOrCreateRuntimeFunctionPtr( 326 UseCancelBarrier ? OMPRTL___kmpc_cancel_barrier 327 : OMPRTL___kmpc_barrier), 328 Args); 329 330 if (UseCancelBarrier && CheckCancelFlag) 331 emitCancelationCheckImpl(Result, OMPD_parallel); 332 333 return Builder.saveIP(); 334 } 335 336 OpenMPIRBuilder::InsertPointTy 337 OpenMPIRBuilder::CreateCancel(const LocationDescription &Loc, 338 Value *IfCondition, 339 omp::Directive CanceledDirective) { 340 if (!updateToLocation(Loc)) 341 return Loc.IP; 342 343 // LLVM utilities like blocks with terminators. 344 auto *UI = Builder.CreateUnreachable(); 345 346 Instruction *ThenTI = UI, *ElseTI = nullptr; 347 if (IfCondition) 348 SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI); 349 Builder.SetInsertPoint(ThenTI); 350 351 Value *CancelKind = nullptr; 352 switch (CanceledDirective) { 353 #define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \ 354 case DirectiveEnum: \ 355 CancelKind = Builder.getInt32(Value); \ 356 break; 357 #include "llvm/Frontend/OpenMP/OMPKinds.def" 358 default: 359 llvm_unreachable("Unknown cancel kind!"); 360 } 361 362 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 363 Value *Ident = getOrCreateIdent(SrcLocStr); 364 Value *Args[] = {Ident, getOrCreateThreadID(Ident), CancelKind}; 365 Value *Result = Builder.CreateCall( 366 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_cancel), Args); 367 368 // The actual cancel logic is shared with others, e.g., cancel_barriers. 369 emitCancelationCheckImpl(Result, CanceledDirective); 370 371 // Update the insertion point and remove the terminator we introduced. 372 Builder.SetInsertPoint(UI->getParent()); 373 UI->eraseFromParent(); 374 375 return Builder.saveIP(); 376 } 377 378 void OpenMPIRBuilder::emitCancelationCheckImpl( 379 Value *CancelFlag, omp::Directive CanceledDirective) { 380 assert(isLastFinalizationInfoCancellable(CanceledDirective) && 381 "Unexpected cancellation!"); 382 383 // For a cancel barrier we create two new blocks. 384 BasicBlock *BB = Builder.GetInsertBlock(); 385 BasicBlock *NonCancellationBlock; 386 if (Builder.GetInsertPoint() == BB->end()) { 387 // TODO: This branch will not be needed once we moved to the 388 // OpenMPIRBuilder codegen completely. 389 NonCancellationBlock = BasicBlock::Create( 390 BB->getContext(), BB->getName() + ".cont", BB->getParent()); 391 } else { 392 NonCancellationBlock = SplitBlock(BB, &*Builder.GetInsertPoint()); 393 BB->getTerminator()->eraseFromParent(); 394 Builder.SetInsertPoint(BB); 395 } 396 BasicBlock *CancellationBlock = BasicBlock::Create( 397 BB->getContext(), BB->getName() + ".cncl", BB->getParent()); 398 399 // Jump to them based on the return value. 400 Value *Cmp = Builder.CreateIsNull(CancelFlag); 401 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock, 402 /* TODO weight */ nullptr, nullptr); 403 404 // From the cancellation block we finalize all variables and go to the 405 // post finalization block that is known to the FiniCB callback. 406 Builder.SetInsertPoint(CancellationBlock); 407 auto &FI = FinalizationStack.back(); 408 FI.FiniCB(Builder.saveIP()); 409 410 // The continuation block is where code generation continues. 411 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->begin()); 412 } 413 414 IRBuilder<>::InsertPoint OpenMPIRBuilder::CreateParallel( 415 const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, 416 PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, 417 Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable) { 418 if (!updateToLocation(Loc)) 419 return Loc.IP; 420 421 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 422 Value *Ident = getOrCreateIdent(SrcLocStr); 423 Value *ThreadID = getOrCreateThreadID(Ident); 424 425 if (NumThreads) { 426 // Build call __kmpc_push_num_threads(&Ident, global_tid, num_threads) 427 Value *Args[] = { 428 Ident, ThreadID, 429 Builder.CreateIntCast(NumThreads, Int32, /*isSigned*/ false)}; 430 Builder.CreateCall( 431 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_num_threads), Args); 432 } 433 434 if (ProcBind != OMP_PROC_BIND_default) { 435 // Build call __kmpc_push_proc_bind(&Ident, global_tid, proc_bind) 436 Value *Args[] = { 437 Ident, ThreadID, 438 ConstantInt::get(Int32, unsigned(ProcBind), /*isSigned=*/true)}; 439 Builder.CreateCall( 440 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_proc_bind), Args); 441 } 442 443 BasicBlock *InsertBB = Builder.GetInsertBlock(); 444 Function *OuterFn = InsertBB->getParent(); 445 446 // Vector to remember instructions we used only during the modeling but which 447 // we want to delete at the end. 448 SmallVector<Instruction *, 4> ToBeDeleted; 449 450 Builder.SetInsertPoint(OuterFn->getEntryBlock().getFirstNonPHI()); 451 AllocaInst *TIDAddr = Builder.CreateAlloca(Int32, nullptr, "tid.addr"); 452 AllocaInst *ZeroAddr = Builder.CreateAlloca(Int32, nullptr, "zero.addr"); 453 454 // If there is an if condition we actually use the TIDAddr and ZeroAddr in the 455 // program, otherwise we only need them for modeling purposes to get the 456 // associated arguments in the outlined function. In the former case, 457 // initialize the allocas properly, in the latter case, delete them later. 458 if (IfCondition) { 459 Builder.CreateStore(Constant::getNullValue(Int32), TIDAddr); 460 Builder.CreateStore(Constant::getNullValue(Int32), ZeroAddr); 461 } else { 462 ToBeDeleted.push_back(TIDAddr); 463 ToBeDeleted.push_back(ZeroAddr); 464 } 465 466 // Create an artificial insertion point that will also ensure the blocks we 467 // are about to split are not degenerated. 468 auto *UI = new UnreachableInst(Builder.getContext(), InsertBB); 469 470 Instruction *ThenTI = UI, *ElseTI = nullptr; 471 if (IfCondition) 472 SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI); 473 474 BasicBlock *ThenBB = ThenTI->getParent(); 475 BasicBlock *PRegEntryBB = ThenBB->splitBasicBlock(ThenTI, "omp.par.entry"); 476 BasicBlock *PRegBodyBB = 477 PRegEntryBB->splitBasicBlock(ThenTI, "omp.par.region"); 478 BasicBlock *PRegPreFiniBB = 479 PRegBodyBB->splitBasicBlock(ThenTI, "omp.par.pre_finalize"); 480 BasicBlock *PRegExitBB = 481 PRegPreFiniBB->splitBasicBlock(ThenTI, "omp.par.exit"); 482 483 auto FiniCBWrapper = [&](InsertPointTy IP) { 484 // Hide "open-ended" blocks from the given FiniCB by setting the right jump 485 // target to the region exit block. 486 if (IP.getBlock()->end() == IP.getPoint()) { 487 IRBuilder<>::InsertPointGuard IPG(Builder); 488 Builder.restoreIP(IP); 489 Instruction *I = Builder.CreateBr(PRegExitBB); 490 IP = InsertPointTy(I->getParent(), I->getIterator()); 491 } 492 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 && 493 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB && 494 "Unexpected insertion point for finalization call!"); 495 return FiniCB(IP); 496 }; 497 498 FinalizationStack.push_back({FiniCBWrapper, OMPD_parallel, IsCancellable}); 499 500 // Generate the privatization allocas in the block that will become the entry 501 // of the outlined function. 502 InsertPointTy AllocaIP(PRegEntryBB, 503 PRegEntryBB->getTerminator()->getIterator()); 504 Builder.restoreIP(AllocaIP); 505 AllocaInst *PrivTIDAddr = 506 Builder.CreateAlloca(Int32, nullptr, "tid.addr.local"); 507 Instruction *PrivTID = Builder.CreateLoad(PrivTIDAddr, "tid"); 508 509 // Add some fake uses for OpenMP provided arguments. 510 ToBeDeleted.push_back(Builder.CreateLoad(TIDAddr, "tid.addr.use")); 511 ToBeDeleted.push_back(Builder.CreateLoad(ZeroAddr, "zero.addr.use")); 512 513 // ThenBB 514 // | 515 // V 516 // PRegionEntryBB <- Privatization allocas are placed here. 517 // | 518 // V 519 // PRegionBodyBB <- BodeGen is invoked here. 520 // | 521 // V 522 // PRegPreFiniBB <- The block we will start finalization from. 523 // | 524 // V 525 // PRegionExitBB <- A common exit to simplify block collection. 526 // 527 528 LLVM_DEBUG(dbgs() << "Before body codegen: " << *OuterFn << "\n"); 529 530 // Let the caller create the body. 531 assert(BodyGenCB && "Expected body generation callback!"); 532 InsertPointTy CodeGenIP(PRegBodyBB, PRegBodyBB->begin()); 533 BodyGenCB(AllocaIP, CodeGenIP, *PRegPreFiniBB); 534 535 LLVM_DEBUG(dbgs() << "After body codegen: " << *OuterFn << "\n"); 536 537 FunctionCallee RTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_fork_call); 538 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 539 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 540 llvm::LLVMContext &Ctx = F->getContext(); 541 MDBuilder MDB(Ctx); 542 // Annotate the callback behavior of the __kmpc_fork_call: 543 // - The callback callee is argument number 2 (microtask). 544 // - The first two arguments of the callback callee are unknown (-1). 545 // - All variadic arguments to the __kmpc_fork_call are passed to the 546 // callback callee. 547 F->addMetadata( 548 llvm::LLVMContext::MD_callback, 549 *llvm::MDNode::get( 550 Ctx, {MDB.createCallbackEncoding(2, {-1, -1}, 551 /* VarArgsArePassed */ true)})); 552 } 553 } 554 555 OutlineInfo OI; 556 OI.PostOutlineCB = [=](Function &OutlinedFn) { 557 // Add some known attributes. 558 OutlinedFn.addParamAttr(0, Attribute::NoAlias); 559 OutlinedFn.addParamAttr(1, Attribute::NoAlias); 560 OutlinedFn.addFnAttr(Attribute::NoUnwind); 561 OutlinedFn.addFnAttr(Attribute::NoRecurse); 562 563 assert(OutlinedFn.arg_size() >= 2 && 564 "Expected at least tid and bounded tid as arguments"); 565 unsigned NumCapturedVars = 566 OutlinedFn.arg_size() - /* tid & bounded tid */ 2; 567 568 CallInst *CI = cast<CallInst>(OutlinedFn.user_back()); 569 CI->getParent()->setName("omp_parallel"); 570 Builder.SetInsertPoint(CI); 571 572 // Build call __kmpc_fork_call(Ident, n, microtask, var1, .., varn); 573 Value *ForkCallArgs[] = { 574 Ident, Builder.getInt32(NumCapturedVars), 575 Builder.CreateBitCast(&OutlinedFn, ParallelTaskPtr)}; 576 577 SmallVector<Value *, 16> RealArgs; 578 RealArgs.append(std::begin(ForkCallArgs), std::end(ForkCallArgs)); 579 RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end()); 580 581 Builder.CreateCall(RTLFn, RealArgs); 582 583 LLVM_DEBUG(dbgs() << "With fork_call placed: " 584 << *Builder.GetInsertBlock()->getParent() << "\n"); 585 586 InsertPointTy ExitIP(PRegExitBB, PRegExitBB->end()); 587 588 // Initialize the local TID stack location with the argument value. 589 Builder.SetInsertPoint(PrivTID); 590 Function::arg_iterator OutlinedAI = OutlinedFn.arg_begin(); 591 Builder.CreateStore(Builder.CreateLoad(OutlinedAI), PrivTIDAddr); 592 593 // If no "if" clause was present we do not need the call created during 594 // outlining, otherwise we reuse it in the serialized parallel region. 595 if (!ElseTI) { 596 CI->eraseFromParent(); 597 } else { 598 599 // If an "if" clause was present we are now generating the serialized 600 // version into the "else" branch. 601 Builder.SetInsertPoint(ElseTI); 602 603 // Build calls __kmpc_serialized_parallel(&Ident, GTid); 604 Value *SerializedParallelCallArgs[] = {Ident, ThreadID}; 605 Builder.CreateCall( 606 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_serialized_parallel), 607 SerializedParallelCallArgs); 608 609 // OutlinedFn(>id, &zero, CapturedStruct); 610 CI->removeFromParent(); 611 Builder.Insert(CI); 612 613 // __kmpc_end_serialized_parallel(&Ident, GTid); 614 Value *EndArgs[] = {Ident, ThreadID}; 615 Builder.CreateCall( 616 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_serialized_parallel), 617 EndArgs); 618 619 LLVM_DEBUG(dbgs() << "With serialized parallel region: " 620 << *Builder.GetInsertBlock()->getParent() << "\n"); 621 } 622 623 for (Instruction *I : ToBeDeleted) 624 I->eraseFromParent(); 625 }; 626 627 // Adjust the finalization stack, verify the adjustment, and call the 628 // finalize function a last time to finalize values between the pre-fini 629 // block and the exit block if we left the parallel "the normal way". 630 auto FiniInfo = FinalizationStack.pop_back_val(); 631 (void)FiniInfo; 632 assert(FiniInfo.DK == OMPD_parallel && 633 "Unexpected finalization stack state!"); 634 635 Instruction *PRegPreFiniTI = PRegPreFiniBB->getTerminator(); 636 637 InsertPointTy PreFiniIP(PRegPreFiniBB, PRegPreFiniTI->getIterator()); 638 FiniCB(PreFiniIP); 639 640 OI.EntryBB = PRegEntryBB; 641 OI.ExitBB = PRegExitBB; 642 643 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet; 644 SmallVector<BasicBlock *, 32> Blocks; 645 OI.collectBlocks(ParallelRegionBlockSet, Blocks); 646 647 // Ensure a single exit node for the outlined region by creating one. 648 // We might have multiple incoming edges to the exit now due to finalizations, 649 // e.g., cancel calls that cause the control flow to leave the region. 650 BasicBlock *PRegOutlinedExitBB = PRegExitBB; 651 PRegExitBB = SplitBlock(PRegExitBB, &*PRegExitBB->getFirstInsertionPt()); 652 PRegOutlinedExitBB->setName("omp.par.outlined.exit"); 653 Blocks.push_back(PRegOutlinedExitBB); 654 655 CodeExtractorAnalysisCache CEAC(*OuterFn); 656 CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr, 657 /* AggregateArgs */ false, 658 /* BlockFrequencyInfo */ nullptr, 659 /* BranchProbabilityInfo */ nullptr, 660 /* AssumptionCache */ nullptr, 661 /* AllowVarArgs */ true, 662 /* AllowAlloca */ true, 663 /* Suffix */ ".omp_par"); 664 665 // Find inputs to, outputs from the code region. 666 BasicBlock *CommonExit = nullptr; 667 SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands; 668 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit); 669 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands); 670 671 LLVM_DEBUG(dbgs() << "Before privatization: " << *OuterFn << "\n"); 672 673 FunctionCallee TIDRTLFn = 674 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_global_thread_num); 675 676 auto PrivHelper = [&](Value &V) { 677 if (&V == TIDAddr || &V == ZeroAddr) 678 return; 679 680 SmallVector<Use *, 8> Uses; 681 for (Use &U : V.uses()) 682 if (auto *UserI = dyn_cast<Instruction>(U.getUser())) 683 if (ParallelRegionBlockSet.count(UserI->getParent())) 684 Uses.push_back(&U); 685 686 Value *ReplacementValue = nullptr; 687 CallInst *CI = dyn_cast<CallInst>(&V); 688 if (CI && CI->getCalledFunction() == TIDRTLFn.getCallee()) { 689 ReplacementValue = PrivTID; 690 } else { 691 Builder.restoreIP( 692 PrivCB(AllocaIP, Builder.saveIP(), V, ReplacementValue)); 693 assert(ReplacementValue && 694 "Expected copy/create callback to set replacement value!"); 695 if (ReplacementValue == &V) 696 return; 697 } 698 699 for (Use *UPtr : Uses) 700 UPtr->set(ReplacementValue); 701 }; 702 703 for (Value *Input : Inputs) { 704 LLVM_DEBUG(dbgs() << "Captured input: " << *Input << "\n"); 705 PrivHelper(*Input); 706 } 707 assert(Outputs.empty() && 708 "OpenMP outlining should not produce live-out values!"); 709 710 LLVM_DEBUG(dbgs() << "After privatization: " << *OuterFn << "\n"); 711 LLVM_DEBUG({ 712 for (auto *BB : Blocks) 713 dbgs() << " PBR: " << BB->getName() << "\n"; 714 }); 715 716 // Register the outlined info. 717 addOutlineInfo(std::move(OI)); 718 719 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end()); 720 UI->eraseFromParent(); 721 722 return AfterIP; 723 } 724 725 void OpenMPIRBuilder::emitFlush(const LocationDescription &Loc) { 726 // Build call void __kmpc_flush(ident_t *loc) 727 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 728 Value *Args[] = {getOrCreateIdent(SrcLocStr)}; 729 730 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_flush), Args); 731 } 732 733 void OpenMPIRBuilder::CreateFlush(const LocationDescription &Loc) { 734 if (!updateToLocation(Loc)) 735 return; 736 emitFlush(Loc); 737 } 738 739 void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) { 740 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 741 // global_tid); 742 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 743 Value *Ident = getOrCreateIdent(SrcLocStr); 744 Value *Args[] = {Ident, getOrCreateThreadID(Ident)}; 745 746 // Ignore return result until untied tasks are supported. 747 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait), 748 Args); 749 } 750 751 void OpenMPIRBuilder::CreateTaskwait(const LocationDescription &Loc) { 752 if (!updateToLocation(Loc)) 753 return; 754 emitTaskwaitImpl(Loc); 755 } 756 757 void OpenMPIRBuilder::emitTaskyieldImpl(const LocationDescription &Loc) { 758 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 759 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 760 Value *Ident = getOrCreateIdent(SrcLocStr); 761 Constant *I32Null = ConstantInt::getNullValue(Int32); 762 Value *Args[] = {Ident, getOrCreateThreadID(Ident), I32Null}; 763 764 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskyield), 765 Args); 766 } 767 768 void OpenMPIRBuilder::CreateTaskyield(const LocationDescription &Loc) { 769 if (!updateToLocation(Loc)) 770 return; 771 emitTaskyieldImpl(Loc); 772 } 773 774 OpenMPIRBuilder::InsertPointTy 775 OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc, 776 BodyGenCallbackTy BodyGenCB, 777 FinalizeCallbackTy FiniCB) { 778 779 if (!updateToLocation(Loc)) 780 return Loc.IP; 781 782 Directive OMPD = Directive::OMPD_master; 783 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 784 Value *Ident = getOrCreateIdent(SrcLocStr); 785 Value *ThreadId = getOrCreateThreadID(Ident); 786 Value *Args[] = {Ident, ThreadId}; 787 788 Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_master); 789 Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args); 790 791 Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_master); 792 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 793 794 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 795 /*Conditional*/ true, /*hasFinalize*/ true); 796 } 797 798 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCritical( 799 const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, 800 FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) { 801 802 if (!updateToLocation(Loc)) 803 return Loc.IP; 804 805 Directive OMPD = Directive::OMPD_critical; 806 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 807 Value *Ident = getOrCreateIdent(SrcLocStr); 808 Value *ThreadId = getOrCreateThreadID(Ident); 809 Value *LockVar = getOMPCriticalRegionLock(CriticalName); 810 Value *Args[] = {Ident, ThreadId, LockVar}; 811 812 SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args)); 813 Function *RTFn = nullptr; 814 if (HintInst) { 815 // Add Hint to entry Args and create call 816 EnterArgs.push_back(HintInst); 817 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical_with_hint); 818 } else { 819 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical); 820 } 821 Instruction *EntryCall = Builder.CreateCall(RTFn, EnterArgs); 822 823 Function *ExitRTLFn = 824 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_critical); 825 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 826 827 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 828 /*Conditional*/ false, /*hasFinalize*/ true); 829 } 830 831 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion( 832 Directive OMPD, Instruction *EntryCall, Instruction *ExitCall, 833 BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool Conditional, 834 bool HasFinalize) { 835 836 if (HasFinalize) 837 FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false}); 838 839 // Create inlined region's entry and body blocks, in preparation 840 // for conditional creation 841 BasicBlock *EntryBB = Builder.GetInsertBlock(); 842 Instruction *SplitPos = EntryBB->getTerminator(); 843 if (!isa_and_nonnull<BranchInst>(SplitPos)) 844 SplitPos = new UnreachableInst(Builder.getContext(), EntryBB); 845 BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end"); 846 BasicBlock *FiniBB = 847 EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize"); 848 849 Builder.SetInsertPoint(EntryBB->getTerminator()); 850 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional); 851 852 // generate body 853 BodyGenCB(/* AllocaIP */ InsertPointTy(), 854 /* CodeGenIP */ Builder.saveIP(), *FiniBB); 855 856 // If we didn't emit a branch to FiniBB during body generation, it means 857 // FiniBB is unreachable (e.g. while(1);). stop generating all the 858 // unreachable blocks, and remove anything we are not going to use. 859 auto SkipEmittingRegion = FiniBB->hasNPredecessors(0); 860 if (SkipEmittingRegion) { 861 FiniBB->eraseFromParent(); 862 ExitCall->eraseFromParent(); 863 // Discard finalization if we have it. 864 if (HasFinalize) { 865 assert(!FinalizationStack.empty() && 866 "Unexpected finalization stack state!"); 867 FinalizationStack.pop_back(); 868 } 869 } else { 870 // emit exit call and do any needed finalization. 871 auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt()); 872 assert(FiniBB->getTerminator()->getNumSuccessors() == 1 && 873 FiniBB->getTerminator()->getSuccessor(0) == ExitBB && 874 "Unexpected control flow graph state!!"); 875 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize); 876 assert(FiniBB->getUniquePredecessor()->getUniqueSuccessor() == FiniBB && 877 "Unexpected Control Flow State!"); 878 MergeBlockIntoPredecessor(FiniBB); 879 } 880 881 // If we are skipping the region of a non conditional, remove the exit 882 // block, and clear the builder's insertion point. 883 assert(SplitPos->getParent() == ExitBB && 884 "Unexpected Insertion point location!"); 885 if (!Conditional && SkipEmittingRegion) { 886 ExitBB->eraseFromParent(); 887 Builder.ClearInsertionPoint(); 888 } else { 889 auto merged = MergeBlockIntoPredecessor(ExitBB); 890 BasicBlock *ExitPredBB = SplitPos->getParent(); 891 auto InsertBB = merged ? ExitPredBB : ExitBB; 892 if (!isa_and_nonnull<BranchInst>(SplitPos)) 893 SplitPos->eraseFromParent(); 894 Builder.SetInsertPoint(InsertBB); 895 } 896 897 return Builder.saveIP(); 898 } 899 900 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry( 901 Directive OMPD, Value *EntryCall, BasicBlock *ExitBB, bool Conditional) { 902 903 // if nothing to do, Return current insertion point. 904 if (!Conditional) 905 return Builder.saveIP(); 906 907 BasicBlock *EntryBB = Builder.GetInsertBlock(); 908 Value *CallBool = Builder.CreateIsNotNull(EntryCall); 909 auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body"); 910 auto *UI = new UnreachableInst(Builder.getContext(), ThenBB); 911 912 // Emit thenBB and set the Builder's insertion point there for 913 // body generation next. Place the block after the current block. 914 Function *CurFn = EntryBB->getParent(); 915 CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB); 916 917 // Move Entry branch to end of ThenBB, and replace with conditional 918 // branch (If-stmt) 919 Instruction *EntryBBTI = EntryBB->getTerminator(); 920 Builder.CreateCondBr(CallBool, ThenBB, ExitBB); 921 EntryBBTI->removeFromParent(); 922 Builder.SetInsertPoint(UI); 923 Builder.Insert(EntryBBTI); 924 UI->eraseFromParent(); 925 Builder.SetInsertPoint(ThenBB->getTerminator()); 926 927 // return an insertion point to ExitBB. 928 return IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt()); 929 } 930 931 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit( 932 omp::Directive OMPD, InsertPointTy FinIP, Instruction *ExitCall, 933 bool HasFinalize) { 934 935 Builder.restoreIP(FinIP); 936 937 // If there is finalization to do, emit it before the exit call 938 if (HasFinalize) { 939 assert(!FinalizationStack.empty() && 940 "Unexpected finalization stack state!"); 941 942 FinalizationInfo Fi = FinalizationStack.pop_back_val(); 943 assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!"); 944 945 Fi.FiniCB(FinIP); 946 947 BasicBlock *FiniBB = FinIP.getBlock(); 948 Instruction *FiniBBTI = FiniBB->getTerminator(); 949 950 // set Builder IP for call creation 951 Builder.SetInsertPoint(FiniBBTI); 952 } 953 954 // place the Exitcall as last instruction before Finalization block terminator 955 ExitCall->removeFromParent(); 956 Builder.Insert(ExitCall); 957 958 return IRBuilder<>::InsertPoint(ExitCall->getParent(), 959 ExitCall->getIterator()); 960 } 961 962 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCopyinClauseBlocks( 963 InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, 964 llvm::IntegerType *IntPtrTy, bool BranchtoEnd) { 965 if (!IP.isSet()) 966 return IP; 967 968 IRBuilder<>::InsertPointGuard IPG(Builder); 969 970 // creates the following CFG structure 971 // OMP_Entry : (MasterAddr != PrivateAddr)? 972 // F T 973 // | \ 974 // | copin.not.master 975 // | / 976 // v / 977 // copyin.not.master.end 978 // | 979 // v 980 // OMP.Entry.Next 981 982 BasicBlock *OMP_Entry = IP.getBlock(); 983 Function *CurFn = OMP_Entry->getParent(); 984 BasicBlock *CopyBegin = 985 BasicBlock::Create(M.getContext(), "copyin.not.master", CurFn); 986 BasicBlock *CopyEnd = nullptr; 987 988 // If entry block is terminated, split to preserve the branch to following 989 // basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is. 990 if (isa_and_nonnull<BranchInst>(OMP_Entry->getTerminator())) { 991 CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(), 992 "copyin.not.master.end"); 993 OMP_Entry->getTerminator()->eraseFromParent(); 994 } else { 995 CopyEnd = 996 BasicBlock::Create(M.getContext(), "copyin.not.master.end", CurFn); 997 } 998 999 Builder.SetInsertPoint(OMP_Entry); 1000 Value *MasterPtr = Builder.CreatePtrToInt(MasterAddr, IntPtrTy); 1001 Value *PrivatePtr = Builder.CreatePtrToInt(PrivateAddr, IntPtrTy); 1002 Value *cmp = Builder.CreateICmpNE(MasterPtr, PrivatePtr); 1003 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd); 1004 1005 Builder.SetInsertPoint(CopyBegin); 1006 if (BranchtoEnd) 1007 Builder.SetInsertPoint(Builder.CreateBr(CopyEnd)); 1008 1009 return Builder.saveIP(); 1010 } 1011 1012 CallInst *OpenMPIRBuilder::CreateOMPAlloc(const LocationDescription &Loc, 1013 Value *Size, Value *Allocator, 1014 std::string Name) { 1015 IRBuilder<>::InsertPointGuard IPG(Builder); 1016 Builder.restoreIP(Loc.IP); 1017 1018 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1019 Value *Ident = getOrCreateIdent(SrcLocStr); 1020 Value *ThreadId = getOrCreateThreadID(Ident); 1021 Value *Args[] = {ThreadId, Size, Allocator}; 1022 1023 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_alloc); 1024 1025 return Builder.CreateCall(Fn, Args, Name); 1026 } 1027 1028 CallInst *OpenMPIRBuilder::CreateOMPFree(const LocationDescription &Loc, 1029 Value *Addr, Value *Allocator, 1030 std::string Name) { 1031 IRBuilder<>::InsertPointGuard IPG(Builder); 1032 Builder.restoreIP(Loc.IP); 1033 1034 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1035 Value *Ident = getOrCreateIdent(SrcLocStr); 1036 Value *ThreadId = getOrCreateThreadID(Ident); 1037 Value *Args[] = {ThreadId, Addr, Allocator}; 1038 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_free); 1039 return Builder.CreateCall(Fn, Args, Name); 1040 } 1041 1042 CallInst *OpenMPIRBuilder::CreateCachedThreadPrivate( 1043 const LocationDescription &Loc, llvm::Value *Pointer, 1044 llvm::ConstantInt *Size, const llvm::Twine &Name) { 1045 IRBuilder<>::InsertPointGuard IPG(Builder); 1046 Builder.restoreIP(Loc.IP); 1047 1048 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1049 Value *Ident = getOrCreateIdent(SrcLocStr); 1050 Value *ThreadId = getOrCreateThreadID(Ident); 1051 Constant *ThreadPrivateCache = 1052 getOrCreateOMPInternalVariable(Int8PtrPtr, Name); 1053 llvm::Value *Args[] = {Ident, ThreadId, Pointer, Size, ThreadPrivateCache}; 1054 1055 Function *Fn = 1056 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_threadprivate_cached); 1057 1058 return Builder.CreateCall(Fn, Args); 1059 } 1060 1061 std::string OpenMPIRBuilder::getNameWithSeparators(ArrayRef<StringRef> Parts, 1062 StringRef FirstSeparator, 1063 StringRef Separator) { 1064 SmallString<128> Buffer; 1065 llvm::raw_svector_ostream OS(Buffer); 1066 StringRef Sep = FirstSeparator; 1067 for (StringRef Part : Parts) { 1068 OS << Sep << Part; 1069 Sep = Separator; 1070 } 1071 return OS.str().str(); 1072 } 1073 1074 Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable( 1075 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 1076 // TODO: Replace the twine arg with stringref to get rid of the conversion 1077 // logic. However This is taken from current implementation in clang as is. 1078 // Since this method is used in many places exclusively for OMP internal use 1079 // we will keep it as is for temporarily until we move all users to the 1080 // builder and then, if possible, fix it everywhere in one go. 1081 SmallString<256> Buffer; 1082 llvm::raw_svector_ostream Out(Buffer); 1083 Out << Name; 1084 StringRef RuntimeName = Out.str(); 1085 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 1086 if (Elem.second) { 1087 assert(Elem.second->getType()->getPointerElementType() == Ty && 1088 "OMP internal variable has different type than requested"); 1089 } else { 1090 // TODO: investigate the appropriate linkage type used for the global 1091 // variable for possibly changing that to internal or private, or maybe 1092 // create different versions of the function for different OMP internal 1093 // variables. 1094 Elem.second = new llvm::GlobalVariable( 1095 M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage, 1096 llvm::Constant::getNullValue(Ty), Elem.first(), 1097 /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, 1098 AddressSpace); 1099 } 1100 1101 return Elem.second; 1102 } 1103 1104 Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) { 1105 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 1106 std::string Name = getNameWithSeparators({Prefix, "var"}, ".", "."); 1107 return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name); 1108 } 1109 1110 // Create all simple and struct types exposed by the runtime and remember 1111 // the llvm::PointerTypes of them for easy access later. 1112 void OpenMPIRBuilder::initializeTypes(Module &M) { 1113 LLVMContext &Ctx = M.getContext(); 1114 StructType *T; 1115 #define OMP_TYPE(VarName, InitValue) VarName = InitValue; 1116 #define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ 1117 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \ 1118 VarName##PtrTy = PointerType::getUnqual(VarName##Ty); 1119 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \ 1120 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \ 1121 VarName##Ptr = PointerType::getUnqual(VarName); 1122 #define OMP_STRUCT_TYPE(VarName, StructName, ...) \ 1123 T = M.getTypeByName(StructName); \ 1124 if (!T) \ 1125 T = StructType::create(Ctx, {__VA_ARGS__}, StructName); \ 1126 VarName = T; \ 1127 VarName##Ptr = PointerType::getUnqual(T); 1128 #include "llvm/Frontend/OpenMP/OMPKinds.def" 1129 } 1130 1131 void OpenMPIRBuilder::OutlineInfo::collectBlocks( 1132 SmallPtrSetImpl<BasicBlock *> &BlockSet, 1133 SmallVectorImpl<BasicBlock *> &BlockVector) { 1134 SmallVector<BasicBlock *, 32> Worklist; 1135 BlockSet.insert(EntryBB); 1136 BlockSet.insert(ExitBB); 1137 1138 Worklist.push_back(EntryBB); 1139 while (!Worklist.empty()) { 1140 BasicBlock *BB = Worklist.pop_back_val(); 1141 BlockVector.push_back(BB); 1142 for (BasicBlock *SuccBB : successors(BB)) 1143 if (BlockSet.insert(SuccBB).second) 1144 Worklist.push_back(SuccBB); 1145 } 1146 } 1147