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