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