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