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