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