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 // Vector to remember instructions we used only during the modeling but which 459 // we want to delete at the end. 460 SmallVector<Instruction *, 4> ToBeDeleted; 461 462 // Change the location to the outer alloca insertion point to create and 463 // initialize the allocas we pass into the parallel region. 464 Builder.restoreIP(OuterAllocaIP); 465 AllocaInst *TIDAddr = Builder.CreateAlloca(Int32, nullptr, "tid.addr"); 466 AllocaInst *ZeroAddr = Builder.CreateAlloca(Int32, nullptr, "zero.addr"); 467 468 // If there is an if condition we actually use the TIDAddr and ZeroAddr in the 469 // program, otherwise we only need them for modeling purposes to get the 470 // associated arguments in the outlined function. In the former case, 471 // initialize the allocas properly, in the latter case, delete them later. 472 if (IfCondition) { 473 Builder.CreateStore(Constant::getNullValue(Int32), TIDAddr); 474 Builder.CreateStore(Constant::getNullValue(Int32), ZeroAddr); 475 } else { 476 ToBeDeleted.push_back(TIDAddr); 477 ToBeDeleted.push_back(ZeroAddr); 478 } 479 480 // Create an artificial insertion point that will also ensure the blocks we 481 // are about to split are not degenerated. 482 auto *UI = new UnreachableInst(Builder.getContext(), InsertBB); 483 484 Instruction *ThenTI = UI, *ElseTI = nullptr; 485 if (IfCondition) 486 SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI); 487 488 BasicBlock *ThenBB = ThenTI->getParent(); 489 BasicBlock *PRegEntryBB = ThenBB->splitBasicBlock(ThenTI, "omp.par.entry"); 490 BasicBlock *PRegBodyBB = 491 PRegEntryBB->splitBasicBlock(ThenTI, "omp.par.region"); 492 BasicBlock *PRegPreFiniBB = 493 PRegBodyBB->splitBasicBlock(ThenTI, "omp.par.pre_finalize"); 494 BasicBlock *PRegExitBB = 495 PRegPreFiniBB->splitBasicBlock(ThenTI, "omp.par.exit"); 496 497 auto FiniCBWrapper = [&](InsertPointTy IP) { 498 // Hide "open-ended" blocks from the given FiniCB by setting the right jump 499 // target to the region exit block. 500 if (IP.getBlock()->end() == IP.getPoint()) { 501 IRBuilder<>::InsertPointGuard IPG(Builder); 502 Builder.restoreIP(IP); 503 Instruction *I = Builder.CreateBr(PRegExitBB); 504 IP = InsertPointTy(I->getParent(), I->getIterator()); 505 } 506 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 && 507 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB && 508 "Unexpected insertion point for finalization call!"); 509 return FiniCB(IP); 510 }; 511 512 FinalizationStack.push_back({FiniCBWrapper, OMPD_parallel, IsCancellable}); 513 514 // Generate the privatization allocas in the block that will become the entry 515 // of the outlined function. 516 Builder.SetInsertPoint(PRegEntryBB->getTerminator()); 517 InsertPointTy InnerAllocaIP = Builder.saveIP(); 518 519 AllocaInst *PrivTIDAddr = 520 Builder.CreateAlloca(Int32, nullptr, "tid.addr.local"); 521 Instruction *PrivTID = Builder.CreateLoad(PrivTIDAddr, "tid"); 522 523 // Add some fake uses for OpenMP provided arguments. 524 ToBeDeleted.push_back(Builder.CreateLoad(TIDAddr, "tid.addr.use")); 525 ToBeDeleted.push_back(Builder.CreateLoad(ZeroAddr, "zero.addr.use")); 526 527 // ThenBB 528 // | 529 // V 530 // PRegionEntryBB <- Privatization allocas are placed here. 531 // | 532 // V 533 // PRegionBodyBB <- BodeGen is invoked here. 534 // | 535 // V 536 // PRegPreFiniBB <- The block we will start finalization from. 537 // | 538 // V 539 // PRegionExitBB <- A common exit to simplify block collection. 540 // 541 542 LLVM_DEBUG(dbgs() << "Before body codegen: " << *OuterFn << "\n"); 543 544 // Let the caller create the body. 545 assert(BodyGenCB && "Expected body generation callback!"); 546 InsertPointTy CodeGenIP(PRegBodyBB, PRegBodyBB->begin()); 547 BodyGenCB(InnerAllocaIP, CodeGenIP, *PRegPreFiniBB); 548 549 LLVM_DEBUG(dbgs() << "After body codegen: " << *OuterFn << "\n"); 550 551 FunctionCallee RTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_fork_call); 552 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 553 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 554 llvm::LLVMContext &Ctx = F->getContext(); 555 MDBuilder MDB(Ctx); 556 // Annotate the callback behavior of the __kmpc_fork_call: 557 // - The callback callee is argument number 2 (microtask). 558 // - The first two arguments of the callback callee are unknown (-1). 559 // - All variadic arguments to the __kmpc_fork_call are passed to the 560 // callback callee. 561 F->addMetadata( 562 llvm::LLVMContext::MD_callback, 563 *llvm::MDNode::get( 564 Ctx, {MDB.createCallbackEncoding(2, {-1, -1}, 565 /* VarArgsArePassed */ true)})); 566 } 567 } 568 569 OutlineInfo OI; 570 OI.PostOutlineCB = [=](Function &OutlinedFn) { 571 // Add some known attributes. 572 OutlinedFn.addParamAttr(0, Attribute::NoAlias); 573 OutlinedFn.addParamAttr(1, Attribute::NoAlias); 574 OutlinedFn.addFnAttr(Attribute::NoUnwind); 575 OutlinedFn.addFnAttr(Attribute::NoRecurse); 576 577 assert(OutlinedFn.arg_size() >= 2 && 578 "Expected at least tid and bounded tid as arguments"); 579 unsigned NumCapturedVars = 580 OutlinedFn.arg_size() - /* tid & bounded tid */ 2; 581 582 CallInst *CI = cast<CallInst>(OutlinedFn.user_back()); 583 CI->getParent()->setName("omp_parallel"); 584 Builder.SetInsertPoint(CI); 585 586 // Build call __kmpc_fork_call(Ident, n, microtask, var1, .., varn); 587 Value *ForkCallArgs[] = { 588 Ident, Builder.getInt32(NumCapturedVars), 589 Builder.CreateBitCast(&OutlinedFn, ParallelTaskPtr)}; 590 591 SmallVector<Value *, 16> RealArgs; 592 RealArgs.append(std::begin(ForkCallArgs), std::end(ForkCallArgs)); 593 RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end()); 594 595 Builder.CreateCall(RTLFn, RealArgs); 596 597 LLVM_DEBUG(dbgs() << "With fork_call placed: " 598 << *Builder.GetInsertBlock()->getParent() << "\n"); 599 600 InsertPointTy ExitIP(PRegExitBB, PRegExitBB->end()); 601 602 // Initialize the local TID stack location with the argument value. 603 Builder.SetInsertPoint(PrivTID); 604 Function::arg_iterator OutlinedAI = OutlinedFn.arg_begin(); 605 Builder.CreateStore(Builder.CreateLoad(OutlinedAI), PrivTIDAddr); 606 607 // If no "if" clause was present we do not need the call created during 608 // outlining, otherwise we reuse it in the serialized parallel region. 609 if (!ElseTI) { 610 CI->eraseFromParent(); 611 } else { 612 613 // If an "if" clause was present we are now generating the serialized 614 // version into the "else" branch. 615 Builder.SetInsertPoint(ElseTI); 616 617 // Build calls __kmpc_serialized_parallel(&Ident, GTid); 618 Value *SerializedParallelCallArgs[] = {Ident, ThreadID}; 619 Builder.CreateCall( 620 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_serialized_parallel), 621 SerializedParallelCallArgs); 622 623 // OutlinedFn(>id, &zero, CapturedStruct); 624 CI->removeFromParent(); 625 Builder.Insert(CI); 626 627 // __kmpc_end_serialized_parallel(&Ident, GTid); 628 Value *EndArgs[] = {Ident, ThreadID}; 629 Builder.CreateCall( 630 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_serialized_parallel), 631 EndArgs); 632 633 LLVM_DEBUG(dbgs() << "With serialized parallel region: " 634 << *Builder.GetInsertBlock()->getParent() << "\n"); 635 } 636 637 for (Instruction *I : ToBeDeleted) 638 I->eraseFromParent(); 639 }; 640 641 // Adjust the finalization stack, verify the adjustment, and call the 642 // finalize function a last time to finalize values between the pre-fini 643 // block and the exit block if we left the parallel "the normal way". 644 auto FiniInfo = FinalizationStack.pop_back_val(); 645 (void)FiniInfo; 646 assert(FiniInfo.DK == OMPD_parallel && 647 "Unexpected finalization stack state!"); 648 649 Instruction *PRegPreFiniTI = PRegPreFiniBB->getTerminator(); 650 651 InsertPointTy PreFiniIP(PRegPreFiniBB, PRegPreFiniTI->getIterator()); 652 FiniCB(PreFiniIP); 653 654 OI.EntryBB = PRegEntryBB; 655 OI.ExitBB = PRegExitBB; 656 657 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet; 658 SmallVector<BasicBlock *, 32> Blocks; 659 OI.collectBlocks(ParallelRegionBlockSet, Blocks); 660 661 // Ensure a single exit node for the outlined region by creating one. 662 // We might have multiple incoming edges to the exit now due to finalizations, 663 // e.g., cancel calls that cause the control flow to leave the region. 664 BasicBlock *PRegOutlinedExitBB = PRegExitBB; 665 PRegExitBB = SplitBlock(PRegExitBB, &*PRegExitBB->getFirstInsertionPt()); 666 PRegOutlinedExitBB->setName("omp.par.outlined.exit"); 667 Blocks.push_back(PRegOutlinedExitBB); 668 669 CodeExtractorAnalysisCache CEAC(*OuterFn); 670 CodeExtractor Extractor(Blocks, /* DominatorTree */ nullptr, 671 /* AggregateArgs */ false, 672 /* BlockFrequencyInfo */ nullptr, 673 /* BranchProbabilityInfo */ nullptr, 674 /* AssumptionCache */ nullptr, 675 /* AllowVarArgs */ true, 676 /* AllowAlloca */ true, 677 /* Suffix */ ".omp_par"); 678 679 // Find inputs to, outputs from the code region. 680 BasicBlock *CommonExit = nullptr; 681 SetVector<Value *> Inputs, Outputs, SinkingCands, HoistingCands; 682 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit); 683 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands); 684 685 LLVM_DEBUG(dbgs() << "Before privatization: " << *OuterFn << "\n"); 686 687 FunctionCallee TIDRTLFn = 688 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_global_thread_num); 689 690 auto PrivHelper = [&](Value &V) { 691 if (&V == TIDAddr || &V == ZeroAddr) 692 return; 693 694 SmallVector<Use *, 8> Uses; 695 for (Use &U : V.uses()) 696 if (auto *UserI = dyn_cast<Instruction>(U.getUser())) 697 if (ParallelRegionBlockSet.count(UserI->getParent())) 698 Uses.push_back(&U); 699 700 Value *ReplacementValue = nullptr; 701 CallInst *CI = dyn_cast<CallInst>(&V); 702 if (CI && CI->getCalledFunction() == TIDRTLFn.getCallee()) { 703 ReplacementValue = PrivTID; 704 } else { 705 Builder.restoreIP( 706 PrivCB(InnerAllocaIP, Builder.saveIP(), V, ReplacementValue)); 707 assert(ReplacementValue && 708 "Expected copy/create callback to set replacement value!"); 709 if (ReplacementValue == &V) 710 return; 711 } 712 713 for (Use *UPtr : Uses) 714 UPtr->set(ReplacementValue); 715 }; 716 717 for (Value *Input : Inputs) { 718 LLVM_DEBUG(dbgs() << "Captured input: " << *Input << "\n"); 719 PrivHelper(*Input); 720 } 721 LLVM_DEBUG({ 722 for (Value *Output : Outputs) 723 LLVM_DEBUG(dbgs() << "Captured output: " << *Output << "\n"); 724 }); 725 assert(Outputs.empty() && 726 "OpenMP outlining should not produce live-out values!"); 727 728 LLVM_DEBUG(dbgs() << "After privatization: " << *OuterFn << "\n"); 729 LLVM_DEBUG({ 730 for (auto *BB : Blocks) 731 dbgs() << " PBR: " << BB->getName() << "\n"; 732 }); 733 734 // Register the outlined info. 735 addOutlineInfo(std::move(OI)); 736 737 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end()); 738 UI->eraseFromParent(); 739 740 return AfterIP; 741 } 742 743 void OpenMPIRBuilder::emitFlush(const LocationDescription &Loc) { 744 // Build call void __kmpc_flush(ident_t *loc) 745 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 746 Value *Args[] = {getOrCreateIdent(SrcLocStr)}; 747 748 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_flush), Args); 749 } 750 751 void OpenMPIRBuilder::createFlush(const LocationDescription &Loc) { 752 if (!updateToLocation(Loc)) 753 return; 754 emitFlush(Loc); 755 } 756 757 void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) { 758 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 759 // global_tid); 760 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 761 Value *Ident = getOrCreateIdent(SrcLocStr); 762 Value *Args[] = {Ident, getOrCreateThreadID(Ident)}; 763 764 // Ignore return result until untied tasks are supported. 765 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait), 766 Args); 767 } 768 769 void OpenMPIRBuilder::createTaskwait(const LocationDescription &Loc) { 770 if (!updateToLocation(Loc)) 771 return; 772 emitTaskwaitImpl(Loc); 773 } 774 775 void OpenMPIRBuilder::emitTaskyieldImpl(const LocationDescription &Loc) { 776 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 777 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 778 Value *Ident = getOrCreateIdent(SrcLocStr); 779 Constant *I32Null = ConstantInt::getNullValue(Int32); 780 Value *Args[] = {Ident, getOrCreateThreadID(Ident), I32Null}; 781 782 Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskyield), 783 Args); 784 } 785 786 void OpenMPIRBuilder::createTaskyield(const LocationDescription &Loc) { 787 if (!updateToLocation(Loc)) 788 return; 789 emitTaskyieldImpl(Loc); 790 } 791 792 OpenMPIRBuilder::InsertPointTy 793 OpenMPIRBuilder::createMaster(const LocationDescription &Loc, 794 BodyGenCallbackTy BodyGenCB, 795 FinalizeCallbackTy FiniCB) { 796 797 if (!updateToLocation(Loc)) 798 return Loc.IP; 799 800 Directive OMPD = Directive::OMPD_master; 801 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 802 Value *Ident = getOrCreateIdent(SrcLocStr); 803 Value *ThreadId = getOrCreateThreadID(Ident); 804 Value *Args[] = {Ident, ThreadId}; 805 806 Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_master); 807 Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args); 808 809 Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_master); 810 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 811 812 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 813 /*Conditional*/ true, /*hasFinalize*/ true); 814 } 815 816 CanonicalLoopInfo * 817 OpenMPIRBuilder::createCanonicalLoop(const LocationDescription &Loc, 818 LoopBodyGenCallbackTy BodyGenCB, 819 Value *TripCount) { 820 BasicBlock *BB = Loc.IP.getBlock(); 821 BasicBlock *NextBB = BB->getNextNode(); 822 Function *F = BB->getParent(); 823 Type *IndVarTy = TripCount->getType(); 824 825 // Create the basic block structure. 826 BasicBlock *Preheader = 827 BasicBlock::Create(M.getContext(), "omp_for.preheader", F, NextBB); 828 BasicBlock *Header = 829 BasicBlock::Create(M.getContext(), "omp_for.header", F, NextBB); 830 BasicBlock *Cond = 831 BasicBlock::Create(M.getContext(), "omp_for.cond", F, NextBB); 832 BasicBlock *Body = 833 BasicBlock::Create(M.getContext(), "omp_for.body", F, NextBB); 834 BasicBlock *Latch = 835 BasicBlock::Create(M.getContext(), "omp_for.inc", F, NextBB); 836 BasicBlock *Exit = 837 BasicBlock::Create(M.getContext(), "omp_for.exit", F, NextBB); 838 BasicBlock *After = 839 BasicBlock::Create(M.getContext(), "omp_for.after", F, NextBB); 840 841 updateToLocation(Loc); 842 Builder.CreateBr(Preheader); 843 844 Builder.SetInsertPoint(Preheader); 845 Builder.CreateBr(Header); 846 847 Builder.SetInsertPoint(Header); 848 PHINode *IndVarPHI = Builder.CreatePHI(IndVarTy, 2, "omp_for.iv"); 849 IndVarPHI->addIncoming(ConstantInt::get(IndVarTy, 0), Preheader); 850 Builder.CreateBr(Cond); 851 852 Builder.SetInsertPoint(Cond); 853 Value *Cmp = Builder.CreateICmpULT(IndVarPHI, TripCount, "omp_for.cmp"); 854 Builder.CreateCondBr(Cmp, Body, Exit); 855 856 Builder.SetInsertPoint(Body); 857 Builder.CreateBr(Latch); 858 859 Builder.SetInsertPoint(Latch); 860 Value *Next = Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1), 861 "omp_for.next", /*HasNUW=*/true); 862 Builder.CreateBr(Header); 863 IndVarPHI->addIncoming(Next, Latch); 864 865 Builder.SetInsertPoint(Exit); 866 Builder.CreateBr(After); 867 868 // After all control flow has been created, insert the body user code. 869 BodyGenCB(InsertPointTy(Body, Body->begin()), IndVarPHI); 870 871 // Remember and return the canonical control flow. 872 LoopInfos.emplace_front(); 873 CanonicalLoopInfo *CL = &LoopInfos.front(); 874 875 CL->Preheader = Preheader; 876 CL->Header = Header; 877 CL->Cond = Cond; 878 CL->Body = Body; 879 CL->Latch = Latch; 880 CL->Exit = Exit; 881 CL->After = After; 882 883 CL->IsValid = true; 884 885 #ifndef NDEBUG 886 CL->assertOK(); 887 #endif 888 return CL; 889 } 890 891 CanonicalLoopInfo *OpenMPIRBuilder::createCanonicalLoop( 892 const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, 893 Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop) { 894 // Consider the following difficulties (assuming 8-bit signed integers): 895 // * Adding \p Step to the loop counter which passes \p Stop may overflow: 896 // DO I = 1, 100, 50 897 /// * A \p Step of INT_MIN cannot not be normalized to a positive direction: 898 // DO I = 100, 0, -128 899 900 // Start, Stop and Step must be of the same integer type. 901 auto *IndVarTy = cast<IntegerType>(Start->getType()); 902 assert(IndVarTy == Stop->getType() && "Stop type mismatch"); 903 assert(IndVarTy == Step->getType() && "Step type mismatch"); 904 905 updateToLocation(Loc); 906 907 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0); 908 ConstantInt *One = ConstantInt::get(IndVarTy, 1); 909 910 // Like Step, but always positive. 911 Value *Incr = Step; 912 913 // Distance between Start and Stop; always positive. 914 Value *Span; 915 916 // Condition whether there are no iterations are executed at all, e.g. because 917 // UB < LB. 918 Value *ZeroCmp; 919 920 if (IsSigned) { 921 // Ensure that increment is positive. If not, negate and invert LB and UB. 922 Value *IsNeg = Builder.CreateICmpSLT(Step, Zero); 923 Incr = Builder.CreateSelect(IsNeg, Builder.CreateNeg(Step), Step); 924 Value *LB = Builder.CreateSelect(IsNeg, Stop, Start); 925 Value *UB = Builder.CreateSelect(IsNeg, Start, Stop); 926 Span = Builder.CreateSub(UB, LB, "", false, true); 927 ZeroCmp = Builder.CreateICmp( 928 InclusiveStop ? CmpInst::ICMP_SLT : CmpInst::ICMP_SLE, UB, LB); 929 } else { 930 Span = Builder.CreateSub(Stop, Start, "", true); 931 ZeroCmp = Builder.CreateICmp( 932 InclusiveStop ? CmpInst::ICMP_ULT : CmpInst::ICMP_ULE, Stop, Start); 933 } 934 935 Value *CountIfLooping; 936 if (InclusiveStop) { 937 CountIfLooping = Builder.CreateAdd(Builder.CreateUDiv(Span, Incr), One); 938 } else { 939 // Avoid incrementing past stop since it could overflow. 940 Value *CountIfTwo = Builder.CreateAdd( 941 Builder.CreateUDiv(Builder.CreateSub(Span, One), Incr), One); 942 Value *OneCmp = Builder.CreateICmp( 943 InclusiveStop ? CmpInst::ICMP_ULT : CmpInst::ICMP_ULE, Span, Incr); 944 CountIfLooping = Builder.CreateSelect(OneCmp, One, CountIfTwo); 945 } 946 Value *TripCount = Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping); 947 948 auto BodyGen = [=](InsertPointTy CodeGenIP, Value *IV) { 949 Builder.restoreIP(CodeGenIP); 950 Value *Span = Builder.CreateMul(IV, Step); 951 Value *IndVar = Builder.CreateAdd(Span, Start); 952 BodyGenCB(Builder.saveIP(), IndVar); 953 }; 954 return createCanonicalLoop(Builder.saveIP(), BodyGen, TripCount); 955 } 956 957 void CanonicalLoopInfo::eraseFromParent() { 958 assert(IsValid && "can only erase previously valid loop cfg"); 959 IsValid = false; 960 961 SmallVector<BasicBlock *, 5> BBsToRemove{Header, Cond, Latch, Exit}; 962 SmallVector<Instruction *, 16> InstsToRemove; 963 964 // Only remove preheader if not re-purposed somewhere else. 965 if (Preheader->getNumUses() == 0) 966 BBsToRemove.push_back(Preheader); 967 968 DeleteDeadBlocks(BBsToRemove); 969 } 970 971 OpenMPIRBuilder::InsertPointTy 972 OpenMPIRBuilder::createCopyPrivate(const LocationDescription &Loc, 973 llvm::Value *BufSize, llvm::Value *CpyBuf, 974 llvm::Value *CpyFn, llvm::Value *DidIt) { 975 if (!updateToLocation(Loc)) 976 return Loc.IP; 977 978 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 979 Value *Ident = getOrCreateIdent(SrcLocStr); 980 Value *ThreadId = getOrCreateThreadID(Ident); 981 982 llvm::Value *DidItLD = Builder.CreateLoad(DidIt); 983 984 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD}; 985 986 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_copyprivate); 987 Builder.CreateCall(Fn, Args); 988 989 return Builder.saveIP(); 990 } 991 992 OpenMPIRBuilder::InsertPointTy 993 OpenMPIRBuilder::createSingle(const LocationDescription &Loc, 994 BodyGenCallbackTy BodyGenCB, 995 FinalizeCallbackTy FiniCB, llvm::Value *DidIt) { 996 997 if (!updateToLocation(Loc)) 998 return Loc.IP; 999 1000 // If needed (i.e. not null), initialize `DidIt` with 0 1001 if (DidIt) { 1002 Builder.CreateStore(Builder.getInt32(0), DidIt); 1003 } 1004 1005 Directive OMPD = Directive::OMPD_single; 1006 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1007 Value *Ident = getOrCreateIdent(SrcLocStr); 1008 Value *ThreadId = getOrCreateThreadID(Ident); 1009 Value *Args[] = {Ident, ThreadId}; 1010 1011 Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_single); 1012 Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args); 1013 1014 Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_single); 1015 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 1016 1017 // generates the following: 1018 // if (__kmpc_single()) { 1019 // .... single region ... 1020 // __kmpc_end_single 1021 // } 1022 1023 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 1024 /*Conditional*/ true, /*hasFinalize*/ true); 1025 } 1026 1027 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCritical( 1028 const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, 1029 FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) { 1030 1031 if (!updateToLocation(Loc)) 1032 return Loc.IP; 1033 1034 Directive OMPD = Directive::OMPD_critical; 1035 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1036 Value *Ident = getOrCreateIdent(SrcLocStr); 1037 Value *ThreadId = getOrCreateThreadID(Ident); 1038 Value *LockVar = getOMPCriticalRegionLock(CriticalName); 1039 Value *Args[] = {Ident, ThreadId, LockVar}; 1040 1041 SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args)); 1042 Function *RTFn = nullptr; 1043 if (HintInst) { 1044 // Add Hint to entry Args and create call 1045 EnterArgs.push_back(HintInst); 1046 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical_with_hint); 1047 } else { 1048 RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical); 1049 } 1050 Instruction *EntryCall = Builder.CreateCall(RTFn, EnterArgs); 1051 1052 Function *ExitRTLFn = 1053 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_critical); 1054 Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args); 1055 1056 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB, 1057 /*Conditional*/ false, /*hasFinalize*/ true); 1058 } 1059 1060 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion( 1061 Directive OMPD, Instruction *EntryCall, Instruction *ExitCall, 1062 BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool Conditional, 1063 bool HasFinalize) { 1064 1065 if (HasFinalize) 1066 FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false}); 1067 1068 // Create inlined region's entry and body blocks, in preparation 1069 // for conditional creation 1070 BasicBlock *EntryBB = Builder.GetInsertBlock(); 1071 Instruction *SplitPos = EntryBB->getTerminator(); 1072 if (!isa_and_nonnull<BranchInst>(SplitPos)) 1073 SplitPos = new UnreachableInst(Builder.getContext(), EntryBB); 1074 BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end"); 1075 BasicBlock *FiniBB = 1076 EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize"); 1077 1078 Builder.SetInsertPoint(EntryBB->getTerminator()); 1079 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional); 1080 1081 // generate body 1082 BodyGenCB(/* AllocaIP */ InsertPointTy(), 1083 /* CodeGenIP */ Builder.saveIP(), *FiniBB); 1084 1085 // If we didn't emit a branch to FiniBB during body generation, it means 1086 // FiniBB is unreachable (e.g. while(1);). stop generating all the 1087 // unreachable blocks, and remove anything we are not going to use. 1088 auto SkipEmittingRegion = FiniBB->hasNPredecessors(0); 1089 if (SkipEmittingRegion) { 1090 FiniBB->eraseFromParent(); 1091 ExitCall->eraseFromParent(); 1092 // Discard finalization if we have it. 1093 if (HasFinalize) { 1094 assert(!FinalizationStack.empty() && 1095 "Unexpected finalization stack state!"); 1096 FinalizationStack.pop_back(); 1097 } 1098 } else { 1099 // emit exit call and do any needed finalization. 1100 auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt()); 1101 assert(FiniBB->getTerminator()->getNumSuccessors() == 1 && 1102 FiniBB->getTerminator()->getSuccessor(0) == ExitBB && 1103 "Unexpected control flow graph state!!"); 1104 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize); 1105 assert(FiniBB->getUniquePredecessor()->getUniqueSuccessor() == FiniBB && 1106 "Unexpected Control Flow State!"); 1107 MergeBlockIntoPredecessor(FiniBB); 1108 } 1109 1110 // If we are skipping the region of a non conditional, remove the exit 1111 // block, and clear the builder's insertion point. 1112 assert(SplitPos->getParent() == ExitBB && 1113 "Unexpected Insertion point location!"); 1114 if (!Conditional && SkipEmittingRegion) { 1115 ExitBB->eraseFromParent(); 1116 Builder.ClearInsertionPoint(); 1117 } else { 1118 auto merged = MergeBlockIntoPredecessor(ExitBB); 1119 BasicBlock *ExitPredBB = SplitPos->getParent(); 1120 auto InsertBB = merged ? ExitPredBB : ExitBB; 1121 if (!isa_and_nonnull<BranchInst>(SplitPos)) 1122 SplitPos->eraseFromParent(); 1123 Builder.SetInsertPoint(InsertBB); 1124 } 1125 1126 return Builder.saveIP(); 1127 } 1128 1129 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry( 1130 Directive OMPD, Value *EntryCall, BasicBlock *ExitBB, bool Conditional) { 1131 1132 // if nothing to do, Return current insertion point. 1133 if (!Conditional) 1134 return Builder.saveIP(); 1135 1136 BasicBlock *EntryBB = Builder.GetInsertBlock(); 1137 Value *CallBool = Builder.CreateIsNotNull(EntryCall); 1138 auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body"); 1139 auto *UI = new UnreachableInst(Builder.getContext(), ThenBB); 1140 1141 // Emit thenBB and set the Builder's insertion point there for 1142 // body generation next. Place the block after the current block. 1143 Function *CurFn = EntryBB->getParent(); 1144 CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB); 1145 1146 // Move Entry branch to end of ThenBB, and replace with conditional 1147 // branch (If-stmt) 1148 Instruction *EntryBBTI = EntryBB->getTerminator(); 1149 Builder.CreateCondBr(CallBool, ThenBB, ExitBB); 1150 EntryBBTI->removeFromParent(); 1151 Builder.SetInsertPoint(UI); 1152 Builder.Insert(EntryBBTI); 1153 UI->eraseFromParent(); 1154 Builder.SetInsertPoint(ThenBB->getTerminator()); 1155 1156 // return an insertion point to ExitBB. 1157 return IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt()); 1158 } 1159 1160 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit( 1161 omp::Directive OMPD, InsertPointTy FinIP, Instruction *ExitCall, 1162 bool HasFinalize) { 1163 1164 Builder.restoreIP(FinIP); 1165 1166 // If there is finalization to do, emit it before the exit call 1167 if (HasFinalize) { 1168 assert(!FinalizationStack.empty() && 1169 "Unexpected finalization stack state!"); 1170 1171 FinalizationInfo Fi = FinalizationStack.pop_back_val(); 1172 assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!"); 1173 1174 Fi.FiniCB(FinIP); 1175 1176 BasicBlock *FiniBB = FinIP.getBlock(); 1177 Instruction *FiniBBTI = FiniBB->getTerminator(); 1178 1179 // set Builder IP for call creation 1180 Builder.SetInsertPoint(FiniBBTI); 1181 } 1182 1183 // place the Exitcall as last instruction before Finalization block terminator 1184 ExitCall->removeFromParent(); 1185 Builder.Insert(ExitCall); 1186 1187 return IRBuilder<>::InsertPoint(ExitCall->getParent(), 1188 ExitCall->getIterator()); 1189 } 1190 1191 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCopyinClauseBlocks( 1192 InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, 1193 llvm::IntegerType *IntPtrTy, bool BranchtoEnd) { 1194 if (!IP.isSet()) 1195 return IP; 1196 1197 IRBuilder<>::InsertPointGuard IPG(Builder); 1198 1199 // creates the following CFG structure 1200 // OMP_Entry : (MasterAddr != PrivateAddr)? 1201 // F T 1202 // | \ 1203 // | copin.not.master 1204 // | / 1205 // v / 1206 // copyin.not.master.end 1207 // | 1208 // v 1209 // OMP.Entry.Next 1210 1211 BasicBlock *OMP_Entry = IP.getBlock(); 1212 Function *CurFn = OMP_Entry->getParent(); 1213 BasicBlock *CopyBegin = 1214 BasicBlock::Create(M.getContext(), "copyin.not.master", CurFn); 1215 BasicBlock *CopyEnd = nullptr; 1216 1217 // If entry block is terminated, split to preserve the branch to following 1218 // basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is. 1219 if (isa_and_nonnull<BranchInst>(OMP_Entry->getTerminator())) { 1220 CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(), 1221 "copyin.not.master.end"); 1222 OMP_Entry->getTerminator()->eraseFromParent(); 1223 } else { 1224 CopyEnd = 1225 BasicBlock::Create(M.getContext(), "copyin.not.master.end", CurFn); 1226 } 1227 1228 Builder.SetInsertPoint(OMP_Entry); 1229 Value *MasterPtr = Builder.CreatePtrToInt(MasterAddr, IntPtrTy); 1230 Value *PrivatePtr = Builder.CreatePtrToInt(PrivateAddr, IntPtrTy); 1231 Value *cmp = Builder.CreateICmpNE(MasterPtr, PrivatePtr); 1232 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd); 1233 1234 Builder.SetInsertPoint(CopyBegin); 1235 if (BranchtoEnd) 1236 Builder.SetInsertPoint(Builder.CreateBr(CopyEnd)); 1237 1238 return Builder.saveIP(); 1239 } 1240 1241 CallInst *OpenMPIRBuilder::createOMPAlloc(const LocationDescription &Loc, 1242 Value *Size, Value *Allocator, 1243 std::string Name) { 1244 IRBuilder<>::InsertPointGuard IPG(Builder); 1245 Builder.restoreIP(Loc.IP); 1246 1247 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1248 Value *Ident = getOrCreateIdent(SrcLocStr); 1249 Value *ThreadId = getOrCreateThreadID(Ident); 1250 Value *Args[] = {ThreadId, Size, Allocator}; 1251 1252 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_alloc); 1253 1254 return Builder.CreateCall(Fn, Args, Name); 1255 } 1256 1257 CallInst *OpenMPIRBuilder::createOMPFree(const LocationDescription &Loc, 1258 Value *Addr, Value *Allocator, 1259 std::string Name) { 1260 IRBuilder<>::InsertPointGuard IPG(Builder); 1261 Builder.restoreIP(Loc.IP); 1262 1263 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1264 Value *Ident = getOrCreateIdent(SrcLocStr); 1265 Value *ThreadId = getOrCreateThreadID(Ident); 1266 Value *Args[] = {ThreadId, Addr, Allocator}; 1267 Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_free); 1268 return Builder.CreateCall(Fn, Args, Name); 1269 } 1270 1271 CallInst *OpenMPIRBuilder::createCachedThreadPrivate( 1272 const LocationDescription &Loc, llvm::Value *Pointer, 1273 llvm::ConstantInt *Size, const llvm::Twine &Name) { 1274 IRBuilder<>::InsertPointGuard IPG(Builder); 1275 Builder.restoreIP(Loc.IP); 1276 1277 Constant *SrcLocStr = getOrCreateSrcLocStr(Loc); 1278 Value *Ident = getOrCreateIdent(SrcLocStr); 1279 Value *ThreadId = getOrCreateThreadID(Ident); 1280 Constant *ThreadPrivateCache = 1281 getOrCreateOMPInternalVariable(Int8PtrPtr, Name); 1282 llvm::Value *Args[] = {Ident, ThreadId, Pointer, Size, ThreadPrivateCache}; 1283 1284 Function *Fn = 1285 getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_threadprivate_cached); 1286 1287 return Builder.CreateCall(Fn, Args); 1288 } 1289 1290 std::string OpenMPIRBuilder::getNameWithSeparators(ArrayRef<StringRef> Parts, 1291 StringRef FirstSeparator, 1292 StringRef Separator) { 1293 SmallString<128> Buffer; 1294 llvm::raw_svector_ostream OS(Buffer); 1295 StringRef Sep = FirstSeparator; 1296 for (StringRef Part : Parts) { 1297 OS << Sep << Part; 1298 Sep = Separator; 1299 } 1300 return OS.str().str(); 1301 } 1302 1303 Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable( 1304 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 1305 // TODO: Replace the twine arg with stringref to get rid of the conversion 1306 // logic. However This is taken from current implementation in clang as is. 1307 // Since this method is used in many places exclusively for OMP internal use 1308 // we will keep it as is for temporarily until we move all users to the 1309 // builder and then, if possible, fix it everywhere in one go. 1310 SmallString<256> Buffer; 1311 llvm::raw_svector_ostream Out(Buffer); 1312 Out << Name; 1313 StringRef RuntimeName = Out.str(); 1314 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 1315 if (Elem.second) { 1316 assert(Elem.second->getType()->getPointerElementType() == Ty && 1317 "OMP internal variable has different type than requested"); 1318 } else { 1319 // TODO: investigate the appropriate linkage type used for the global 1320 // variable for possibly changing that to internal or private, or maybe 1321 // create different versions of the function for different OMP internal 1322 // variables. 1323 Elem.second = new llvm::GlobalVariable( 1324 M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage, 1325 llvm::Constant::getNullValue(Ty), Elem.first(), 1326 /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, 1327 AddressSpace); 1328 } 1329 1330 return Elem.second; 1331 } 1332 1333 Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) { 1334 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 1335 std::string Name = getNameWithSeparators({Prefix, "var"}, ".", "."); 1336 return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name); 1337 } 1338 1339 // Create all simple and struct types exposed by the runtime and remember 1340 // the llvm::PointerTypes of them for easy access later. 1341 void OpenMPIRBuilder::initializeTypes(Module &M) { 1342 LLVMContext &Ctx = M.getContext(); 1343 StructType *T; 1344 #define OMP_TYPE(VarName, InitValue) VarName = InitValue; 1345 #define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ 1346 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \ 1347 VarName##PtrTy = PointerType::getUnqual(VarName##Ty); 1348 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \ 1349 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \ 1350 VarName##Ptr = PointerType::getUnqual(VarName); 1351 #define OMP_STRUCT_TYPE(VarName, StructName, ...) \ 1352 T = M.getTypeByName(StructName); \ 1353 if (!T) \ 1354 T = StructType::create(Ctx, {__VA_ARGS__}, StructName); \ 1355 VarName = T; \ 1356 VarName##Ptr = PointerType::getUnqual(T); 1357 #include "llvm/Frontend/OpenMP/OMPKinds.def" 1358 } 1359 1360 void OpenMPIRBuilder::OutlineInfo::collectBlocks( 1361 SmallPtrSetImpl<BasicBlock *> &BlockSet, 1362 SmallVectorImpl<BasicBlock *> &BlockVector) { 1363 SmallVector<BasicBlock *, 32> Worklist; 1364 BlockSet.insert(EntryBB); 1365 BlockSet.insert(ExitBB); 1366 1367 Worklist.push_back(EntryBB); 1368 while (!Worklist.empty()) { 1369 BasicBlock *BB = Worklist.pop_back_val(); 1370 BlockVector.push_back(BB); 1371 for (BasicBlock *SuccBB : successors(BB)) 1372 if (BlockSet.insert(SuccBB).second) 1373 Worklist.push_back(SuccBB); 1374 } 1375 } 1376 1377 void CanonicalLoopInfo::assertOK() const { 1378 #ifndef NDEBUG 1379 if (!IsValid) 1380 return; 1381 1382 // Verify standard control-flow we use for OpenMP loops. 1383 assert(Preheader); 1384 assert(isa<BranchInst>(Preheader->getTerminator()) && 1385 "Preheader must terminate with unconditional branch"); 1386 assert(Preheader->getSingleSuccessor() == Header && 1387 "Preheader must jump to header"); 1388 1389 assert(Header); 1390 assert(isa<BranchInst>(Header->getTerminator()) && 1391 "Header must terminate with unconditional branch"); 1392 assert(Header->getSingleSuccessor() == Cond && 1393 "Header must jump to exiting block"); 1394 1395 assert(Cond); 1396 assert(Cond->getSinglePredecessor() == Header && 1397 "Exiting block only reachable from header"); 1398 1399 assert(isa<BranchInst>(Cond->getTerminator()) && 1400 "Exiting block must terminate with conditional branch"); 1401 assert(size(successors(Cond)) == 2 && 1402 "Exiting block must have two successors"); 1403 assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(0) == Body && 1404 "Exiting block's first successor jump to the body"); 1405 assert(cast<BranchInst>(Cond->getTerminator())->getSuccessor(1) == Exit && 1406 "Exiting block's second successor must exit the loop"); 1407 1408 assert(Body); 1409 assert(Body->getSinglePredecessor() == Cond && 1410 "Body only reachable from exiting block"); 1411 1412 assert(Latch); 1413 assert(isa<BranchInst>(Latch->getTerminator()) && 1414 "Latch must terminate with unconditional branch"); 1415 assert(Latch->getSingleSuccessor() == Header && "Latch must jump to header"); 1416 1417 assert(Exit); 1418 assert(isa<BranchInst>(Exit->getTerminator()) && 1419 "Exit block must terminate with unconditional branch"); 1420 assert(Exit->getSingleSuccessor() == After && 1421 "Exit block must jump to after block"); 1422 1423 assert(After); 1424 assert(After->getSinglePredecessor() == Exit && 1425 "After block only reachable from exit block"); 1426 1427 Instruction *IndVar = getIndVar(); 1428 assert(IndVar && "Canonical induction variable not found?"); 1429 assert(isa<IntegerType>(IndVar->getType()) && 1430 "Induction variable must be an integer"); 1431 assert(cast<PHINode>(IndVar)->getParent() == Header && 1432 "Induction variable must be a PHI in the loop header"); 1433 1434 Value *TripCount = getTripCount(); 1435 assert(TripCount && "Loop trip count not found?"); 1436 assert(IndVar->getType() == TripCount->getType() && 1437 "Trip count and induction variable must have the same type"); 1438 1439 auto *CmpI = cast<CmpInst>(&Cond->front()); 1440 assert(CmpI->getPredicate() == CmpInst::ICMP_ULT && 1441 "Exit condition must be a signed less-than comparison"); 1442 assert(CmpI->getOperand(0) == IndVar && 1443 "Exit condition must compare the induction variable"); 1444 assert(CmpI->getOperand(1) == TripCount && 1445 "Exit condition must compare with the trip count"); 1446 #endif 1447 } 1448