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