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, InsertPointTy OuterAllocaIP,
398     BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB,
399     FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads,
400     omp::ProcBindKind ProcBind, bool IsCancellable) {
401   if (!updateToLocation(Loc))
402     return Loc.IP;
403 
404   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
405   Value *Ident = getOrCreateIdent(SrcLocStr);
406   Value *ThreadID = getOrCreateThreadID(Ident);
407 
408   if (NumThreads) {
409     // Build call __kmpc_push_num_threads(&Ident, global_tid, num_threads)
410     Value *Args[] = {
411         Ident, ThreadID,
412         Builder.CreateIntCast(NumThreads, Int32, /*isSigned*/ false)};
413     Builder.CreateCall(
414         getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_num_threads), Args);
415   }
416 
417   if (ProcBind != OMP_PROC_BIND_default) {
418     // Build call __kmpc_push_proc_bind(&Ident, global_tid, proc_bind)
419     Value *Args[] = {
420         Ident, ThreadID,
421         ConstantInt::get(Int32, unsigned(ProcBind), /*isSigned=*/true)};
422     Builder.CreateCall(
423         getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_push_proc_bind), Args);
424   }
425 
426   BasicBlock *InsertBB = Builder.GetInsertBlock();
427   Function *OuterFn = InsertBB->getParent();
428 
429   // Vector to remember instructions we used only during the modeling but which
430   // we want to delete at the end.
431   SmallVector<Instruction *, 4> ToBeDeleted;
432 
433   // Change the location to the outer alloca insertion point to create and
434   // initialize the allocas we pass into the parallel region.
435   Builder.restoreIP(OuterAllocaIP);
436   AllocaInst *TIDAddr = Builder.CreateAlloca(Int32, nullptr, "tid.addr");
437   AllocaInst *ZeroAddr = Builder.CreateAlloca(Int32, nullptr, "zero.addr");
438 
439   // If there is an if condition we actually use the TIDAddr and ZeroAddr in the
440   // program, otherwise we only need them for modeling purposes to get the
441   // associated arguments in the outlined function. In the former case,
442   // initialize the allocas properly, in the latter case, delete them later.
443   if (IfCondition) {
444     Builder.CreateStore(Constant::getNullValue(Int32), TIDAddr);
445     Builder.CreateStore(Constant::getNullValue(Int32), ZeroAddr);
446   } else {
447     ToBeDeleted.push_back(TIDAddr);
448     ToBeDeleted.push_back(ZeroAddr);
449   }
450 
451   // Create an artificial insertion point that will also ensure the blocks we
452   // are about to split are not degenerated.
453   auto *UI = new UnreachableInst(Builder.getContext(), InsertBB);
454 
455   Instruction *ThenTI = UI, *ElseTI = nullptr;
456   if (IfCondition)
457     SplitBlockAndInsertIfThenElse(IfCondition, UI, &ThenTI, &ElseTI);
458 
459   BasicBlock *ThenBB = ThenTI->getParent();
460   BasicBlock *PRegEntryBB = ThenBB->splitBasicBlock(ThenTI, "omp.par.entry");
461   BasicBlock *PRegBodyBB =
462       PRegEntryBB->splitBasicBlock(ThenTI, "omp.par.region");
463   BasicBlock *PRegPreFiniBB =
464       PRegBodyBB->splitBasicBlock(ThenTI, "omp.par.pre_finalize");
465   BasicBlock *PRegExitBB =
466       PRegPreFiniBB->splitBasicBlock(ThenTI, "omp.par.exit");
467 
468   auto FiniCBWrapper = [&](InsertPointTy IP) {
469     // Hide "open-ended" blocks from the given FiniCB by setting the right jump
470     // target to the region exit block.
471     if (IP.getBlock()->end() == IP.getPoint()) {
472       IRBuilder<>::InsertPointGuard IPG(Builder);
473       Builder.restoreIP(IP);
474       Instruction *I = Builder.CreateBr(PRegExitBB);
475       IP = InsertPointTy(I->getParent(), I->getIterator());
476     }
477     assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
478            IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
479            "Unexpected insertion point for finalization call!");
480     return FiniCB(IP);
481   };
482 
483   FinalizationStack.push_back({FiniCBWrapper, OMPD_parallel, IsCancellable});
484 
485   // Generate the privatization allocas in the block that will become the entry
486   // of the outlined function.
487   Builder.SetInsertPoint(PRegEntryBB->getTerminator());
488   InsertPointTy InnerAllocaIP = Builder.saveIP();
489 
490   AllocaInst *PrivTIDAddr =
491       Builder.CreateAlloca(Int32, nullptr, "tid.addr.local");
492   Instruction *PrivTID = Builder.CreateLoad(PrivTIDAddr, "tid");
493 
494   // Add some fake uses for OpenMP provided arguments.
495   ToBeDeleted.push_back(Builder.CreateLoad(TIDAddr, "tid.addr.use"));
496   ToBeDeleted.push_back(Builder.CreateLoad(ZeroAddr, "zero.addr.use"));
497 
498   // ThenBB
499   //   |
500   //   V
501   // PRegionEntryBB         <- Privatization allocas are placed here.
502   //   |
503   //   V
504   // PRegionBodyBB          <- BodeGen is invoked here.
505   //   |
506   //   V
507   // PRegPreFiniBB          <- The block we will start finalization from.
508   //   |
509   //   V
510   // PRegionExitBB          <- A common exit to simplify block collection.
511   //
512 
513   LLVM_DEBUG(dbgs() << "Before body codegen: " << *OuterFn << "\n");
514 
515   // Let the caller create the body.
516   assert(BodyGenCB && "Expected body generation callback!");
517   InsertPointTy CodeGenIP(PRegBodyBB, PRegBodyBB->begin());
518   BodyGenCB(InnerAllocaIP, CodeGenIP, *PRegPreFiniBB);
519 
520   LLVM_DEBUG(dbgs() << "After  body codegen: " << *OuterFn << "\n");
521 
522   FunctionCallee RTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_fork_call);
523   if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
524     if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
525       llvm::LLVMContext &Ctx = F->getContext();
526       MDBuilder MDB(Ctx);
527       // Annotate the callback behavior of the __kmpc_fork_call:
528       //  - The callback callee is argument number 2 (microtask).
529       //  - The first two arguments of the callback callee are unknown (-1).
530       //  - All variadic arguments to the __kmpc_fork_call are passed to the
531       //    callback callee.
532       F->addMetadata(
533           llvm::LLVMContext::MD_callback,
534           *llvm::MDNode::get(
535               Ctx, {MDB.createCallbackEncoding(2, {-1, -1},
536                                                /* VarArgsArePassed */ true)}));
537     }
538   }
539 
540   OutlineInfo OI;
541   OI.PostOutlineCB = [=](Function &OutlinedFn) {
542     // Add some known attributes.
543     OutlinedFn.addParamAttr(0, Attribute::NoAlias);
544     OutlinedFn.addParamAttr(1, Attribute::NoAlias);
545     OutlinedFn.addFnAttr(Attribute::NoUnwind);
546     OutlinedFn.addFnAttr(Attribute::NoRecurse);
547 
548     assert(OutlinedFn.arg_size() >= 2 &&
549            "Expected at least tid and bounded tid as arguments");
550     unsigned NumCapturedVars =
551         OutlinedFn.arg_size() - /* tid & bounded tid */ 2;
552 
553     CallInst *CI = cast<CallInst>(OutlinedFn.user_back());
554     CI->getParent()->setName("omp_parallel");
555     Builder.SetInsertPoint(CI);
556 
557     // Build call __kmpc_fork_call(Ident, n, microtask, var1, .., varn);
558     Value *ForkCallArgs[] = {
559         Ident, Builder.getInt32(NumCapturedVars),
560         Builder.CreateBitCast(&OutlinedFn, ParallelTaskPtr)};
561 
562     SmallVector<Value *, 16> RealArgs;
563     RealArgs.append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
564     RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end());
565 
566     Builder.CreateCall(RTLFn, RealArgs);
567 
568     LLVM_DEBUG(dbgs() << "With fork_call placed: "
569                       << *Builder.GetInsertBlock()->getParent() << "\n");
570 
571     InsertPointTy ExitIP(PRegExitBB, PRegExitBB->end());
572 
573     // Initialize the local TID stack location with the argument value.
574     Builder.SetInsertPoint(PrivTID);
575     Function::arg_iterator OutlinedAI = OutlinedFn.arg_begin();
576     Builder.CreateStore(Builder.CreateLoad(OutlinedAI), PrivTIDAddr);
577 
578     // If no "if" clause was present we do not need the call created during
579     // outlining, otherwise we reuse it in the serialized parallel region.
580     if (!ElseTI) {
581       CI->eraseFromParent();
582     } else {
583 
584       // If an "if" clause was present we are now generating the serialized
585       // version into the "else" branch.
586       Builder.SetInsertPoint(ElseTI);
587 
588       // Build calls __kmpc_serialized_parallel(&Ident, GTid);
589       Value *SerializedParallelCallArgs[] = {Ident, ThreadID};
590       Builder.CreateCall(
591           getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_serialized_parallel),
592           SerializedParallelCallArgs);
593 
594       // OutlinedFn(&GTid, &zero, CapturedStruct);
595       CI->removeFromParent();
596       Builder.Insert(CI);
597 
598       // __kmpc_end_serialized_parallel(&Ident, GTid);
599       Value *EndArgs[] = {Ident, ThreadID};
600       Builder.CreateCall(
601           getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_serialized_parallel),
602           EndArgs);
603 
604       LLVM_DEBUG(dbgs() << "With serialized parallel region: "
605                         << *Builder.GetInsertBlock()->getParent() << "\n");
606     }
607 
608     for (Instruction *I : ToBeDeleted)
609       I->eraseFromParent();
610   };
611 
612   // Adjust the finalization stack, verify the adjustment, and call the
613   // finalize function a last time to finalize values between the pre-fini
614   // block and the exit block if we left the parallel "the normal way".
615   auto FiniInfo = FinalizationStack.pop_back_val();
616   (void)FiniInfo;
617   assert(FiniInfo.DK == OMPD_parallel &&
618          "Unexpected finalization stack state!");
619 
620   Instruction *PRegPreFiniTI = PRegPreFiniBB->getTerminator();
621 
622   InsertPointTy PreFiniIP(PRegPreFiniBB, PRegPreFiniTI->getIterator());
623   FiniCB(PreFiniIP);
624 
625   OI.EntryBB = PRegEntryBB;
626   OI.ExitBB = PRegExitBB;
627 
628   SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
629   SmallVector<BasicBlock *, 32> Blocks;
630   OI.collectBlocks(ParallelRegionBlockSet, Blocks);
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   Blocks.push_back(PRegOutlinedExitBB);
639 
640   CodeExtractorAnalysisCache CEAC(*OuterFn);
641   CodeExtractor Extractor(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(InnerAllocaIP, 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   LLVM_DEBUG({
693     for (Value *Output : Outputs)
694       LLVM_DEBUG(dbgs() << "Captured output: " << *Output << "\n");
695   });
696   assert(Outputs.empty() &&
697          "OpenMP outlining should not produce live-out values!");
698 
699   LLVM_DEBUG(dbgs() << "After  privatization: " << *OuterFn << "\n");
700   LLVM_DEBUG({
701     for (auto *BB : Blocks)
702       dbgs() << " PBR: " << BB->getName() << "\n";
703   });
704 
705   // Register the outlined info.
706   addOutlineInfo(std::move(OI));
707 
708   InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
709   UI->eraseFromParent();
710 
711   return AfterIP;
712 }
713 
714 void OpenMPIRBuilder::emitFlush(const LocationDescription &Loc) {
715   // Build call void __kmpc_flush(ident_t *loc)
716   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
717   Value *Args[] = {getOrCreateIdent(SrcLocStr)};
718 
719   Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_flush), Args);
720 }
721 
722 void OpenMPIRBuilder::CreateFlush(const LocationDescription &Loc) {
723   if (!updateToLocation(Loc))
724     return;
725   emitFlush(Loc);
726 }
727 
728 void OpenMPIRBuilder::emitTaskwaitImpl(const LocationDescription &Loc) {
729   // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
730   // global_tid);
731   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
732   Value *Ident = getOrCreateIdent(SrcLocStr);
733   Value *Args[] = {Ident, getOrCreateThreadID(Ident)};
734 
735   // Ignore return result until untied tasks are supported.
736   Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskwait),
737                      Args);
738 }
739 
740 void OpenMPIRBuilder::CreateTaskwait(const LocationDescription &Loc) {
741   if (!updateToLocation(Loc))
742     return;
743   emitTaskwaitImpl(Loc);
744 }
745 
746 void OpenMPIRBuilder::emitTaskyieldImpl(const LocationDescription &Loc) {
747   // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
748   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
749   Value *Ident = getOrCreateIdent(SrcLocStr);
750   Constant *I32Null = ConstantInt::getNullValue(Int32);
751   Value *Args[] = {Ident, getOrCreateThreadID(Ident), I32Null};
752 
753   Builder.CreateCall(getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_taskyield),
754                      Args);
755 }
756 
757 void OpenMPIRBuilder::CreateTaskyield(const LocationDescription &Loc) {
758   if (!updateToLocation(Loc))
759     return;
760   emitTaskyieldImpl(Loc);
761 }
762 
763 OpenMPIRBuilder::InsertPointTy
764 OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc,
765                               BodyGenCallbackTy BodyGenCB,
766                               FinalizeCallbackTy FiniCB) {
767 
768   if (!updateToLocation(Loc))
769     return Loc.IP;
770 
771   Directive OMPD = Directive::OMPD_master;
772   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
773   Value *Ident = getOrCreateIdent(SrcLocStr);
774   Value *ThreadId = getOrCreateThreadID(Ident);
775   Value *Args[] = {Ident, ThreadId};
776 
777   Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_master);
778   Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args);
779 
780   Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_master);
781   Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
782 
783   return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
784                               /*Conditional*/ true, /*hasFinalize*/ true);
785 }
786 
787 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCritical(
788     const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB,
789     FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) {
790 
791   if (!updateToLocation(Loc))
792     return Loc.IP;
793 
794   Directive OMPD = Directive::OMPD_critical;
795   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
796   Value *Ident = getOrCreateIdent(SrcLocStr);
797   Value *ThreadId = getOrCreateThreadID(Ident);
798   Value *LockVar = getOMPCriticalRegionLock(CriticalName);
799   Value *Args[] = {Ident, ThreadId, LockVar};
800 
801   SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args));
802   Function *RTFn = nullptr;
803   if (HintInst) {
804     // Add Hint to entry Args and create call
805     EnterArgs.push_back(HintInst);
806     RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical_with_hint);
807   } else {
808     RTFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_critical);
809   }
810   Instruction *EntryCall = Builder.CreateCall(RTFn, EnterArgs);
811 
812   Function *ExitRTLFn =
813       getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_critical);
814   Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
815 
816   return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
817                               /*Conditional*/ false, /*hasFinalize*/ true);
818 }
819 
820 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion(
821     Directive OMPD, Instruction *EntryCall, Instruction *ExitCall,
822     BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool Conditional,
823     bool HasFinalize) {
824 
825   if (HasFinalize)
826     FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false});
827 
828   // Create inlined region's entry and body blocks, in preparation
829   // for conditional creation
830   BasicBlock *EntryBB = Builder.GetInsertBlock();
831   Instruction *SplitPos = EntryBB->getTerminator();
832   if (!isa_and_nonnull<BranchInst>(SplitPos))
833     SplitPos = new UnreachableInst(Builder.getContext(), EntryBB);
834   BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end");
835   BasicBlock *FiniBB =
836       EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize");
837 
838   Builder.SetInsertPoint(EntryBB->getTerminator());
839   emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
840 
841   // generate body
842   BodyGenCB(/* AllocaIP */ InsertPointTy(),
843             /* CodeGenIP */ Builder.saveIP(), *FiniBB);
844 
845   // If we didn't emit a branch to FiniBB during body generation, it means
846   // FiniBB is unreachable (e.g. while(1);). stop generating all the
847   // unreachable blocks, and remove anything we are not going to use.
848   auto SkipEmittingRegion = FiniBB->hasNPredecessors(0);
849   if (SkipEmittingRegion) {
850     FiniBB->eraseFromParent();
851     ExitCall->eraseFromParent();
852     // Discard finalization if we have it.
853     if (HasFinalize) {
854       assert(!FinalizationStack.empty() &&
855              "Unexpected finalization stack state!");
856       FinalizationStack.pop_back();
857     }
858   } else {
859     // emit exit call and do any needed finalization.
860     auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt());
861     assert(FiniBB->getTerminator()->getNumSuccessors() == 1 &&
862            FiniBB->getTerminator()->getSuccessor(0) == ExitBB &&
863            "Unexpected control flow graph state!!");
864     emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
865     assert(FiniBB->getUniquePredecessor()->getUniqueSuccessor() == FiniBB &&
866            "Unexpected Control Flow State!");
867     MergeBlockIntoPredecessor(FiniBB);
868   }
869 
870   // If we are skipping the region of a non conditional, remove the exit
871   // block, and clear the builder's insertion point.
872   assert(SplitPos->getParent() == ExitBB &&
873          "Unexpected Insertion point location!");
874   if (!Conditional && SkipEmittingRegion) {
875     ExitBB->eraseFromParent();
876     Builder.ClearInsertionPoint();
877   } else {
878     auto merged = MergeBlockIntoPredecessor(ExitBB);
879     BasicBlock *ExitPredBB = SplitPos->getParent();
880     auto InsertBB = merged ? ExitPredBB : ExitBB;
881     if (!isa_and_nonnull<BranchInst>(SplitPos))
882       SplitPos->eraseFromParent();
883     Builder.SetInsertPoint(InsertBB);
884   }
885 
886   return Builder.saveIP();
887 }
888 
889 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry(
890     Directive OMPD, Value *EntryCall, BasicBlock *ExitBB, bool Conditional) {
891 
892   // if nothing to do, Return current insertion point.
893   if (!Conditional)
894     return Builder.saveIP();
895 
896   BasicBlock *EntryBB = Builder.GetInsertBlock();
897   Value *CallBool = Builder.CreateIsNotNull(EntryCall);
898   auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body");
899   auto *UI = new UnreachableInst(Builder.getContext(), ThenBB);
900 
901   // Emit thenBB and set the Builder's insertion point there for
902   // body generation next. Place the block after the current block.
903   Function *CurFn = EntryBB->getParent();
904   CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB);
905 
906   // Move Entry branch to end of ThenBB, and replace with conditional
907   // branch (If-stmt)
908   Instruction *EntryBBTI = EntryBB->getTerminator();
909   Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
910   EntryBBTI->removeFromParent();
911   Builder.SetInsertPoint(UI);
912   Builder.Insert(EntryBBTI);
913   UI->eraseFromParent();
914   Builder.SetInsertPoint(ThenBB->getTerminator());
915 
916   // return an insertion point to ExitBB.
917   return IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt());
918 }
919 
920 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit(
921     omp::Directive OMPD, InsertPointTy FinIP, Instruction *ExitCall,
922     bool HasFinalize) {
923 
924   Builder.restoreIP(FinIP);
925 
926   // If there is finalization to do, emit it before the exit call
927   if (HasFinalize) {
928     assert(!FinalizationStack.empty() &&
929            "Unexpected finalization stack state!");
930 
931     FinalizationInfo Fi = FinalizationStack.pop_back_val();
932     assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!");
933 
934     Fi.FiniCB(FinIP);
935 
936     BasicBlock *FiniBB = FinIP.getBlock();
937     Instruction *FiniBBTI = FiniBB->getTerminator();
938 
939     // set Builder IP for call creation
940     Builder.SetInsertPoint(FiniBBTI);
941   }
942 
943   // place the Exitcall as last instruction before Finalization block terminator
944   ExitCall->removeFromParent();
945   Builder.Insert(ExitCall);
946 
947   return IRBuilder<>::InsertPoint(ExitCall->getParent(),
948                                   ExitCall->getIterator());
949 }
950 
951 OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCopyinClauseBlocks(
952     InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr,
953     llvm::IntegerType *IntPtrTy, bool BranchtoEnd) {
954   if (!IP.isSet())
955     return IP;
956 
957   IRBuilder<>::InsertPointGuard IPG(Builder);
958 
959   // creates the following CFG structure
960   //	   OMP_Entry : (MasterAddr != PrivateAddr)?
961   //       F     T
962   //       |      \
963   //       |     copin.not.master
964   //       |      /
965   //       v     /
966   //   copyin.not.master.end
967   //		     |
968   //         v
969   //   OMP.Entry.Next
970 
971   BasicBlock *OMP_Entry = IP.getBlock();
972   Function *CurFn = OMP_Entry->getParent();
973   BasicBlock *CopyBegin =
974       BasicBlock::Create(M.getContext(), "copyin.not.master", CurFn);
975   BasicBlock *CopyEnd = nullptr;
976 
977   // If entry block is terminated, split to preserve the branch to following
978   // basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is.
979   if (isa_and_nonnull<BranchInst>(OMP_Entry->getTerminator())) {
980     CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(),
981                                          "copyin.not.master.end");
982     OMP_Entry->getTerminator()->eraseFromParent();
983   } else {
984     CopyEnd =
985         BasicBlock::Create(M.getContext(), "copyin.not.master.end", CurFn);
986   }
987 
988   Builder.SetInsertPoint(OMP_Entry);
989   Value *MasterPtr = Builder.CreatePtrToInt(MasterAddr, IntPtrTy);
990   Value *PrivatePtr = Builder.CreatePtrToInt(PrivateAddr, IntPtrTy);
991   Value *cmp = Builder.CreateICmpNE(MasterPtr, PrivatePtr);
992   Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
993 
994   Builder.SetInsertPoint(CopyBegin);
995   if (BranchtoEnd)
996     Builder.SetInsertPoint(Builder.CreateBr(CopyEnd));
997 
998   return Builder.saveIP();
999 }
1000 
1001 CallInst *OpenMPIRBuilder::CreateOMPAlloc(const LocationDescription &Loc,
1002                                           Value *Size, Value *Allocator,
1003                                           std::string Name) {
1004   IRBuilder<>::InsertPointGuard IPG(Builder);
1005   Builder.restoreIP(Loc.IP);
1006 
1007   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
1008   Value *Ident = getOrCreateIdent(SrcLocStr);
1009   Value *ThreadId = getOrCreateThreadID(Ident);
1010   Value *Args[] = {ThreadId, Size, Allocator};
1011 
1012   Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_alloc);
1013 
1014   return Builder.CreateCall(Fn, Args, Name);
1015 }
1016 
1017 CallInst *OpenMPIRBuilder::CreateOMPFree(const LocationDescription &Loc,
1018                                          Value *Addr, Value *Allocator,
1019                                          std::string Name) {
1020   IRBuilder<>::InsertPointGuard IPG(Builder);
1021   Builder.restoreIP(Loc.IP);
1022 
1023   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
1024   Value *Ident = getOrCreateIdent(SrcLocStr);
1025   Value *ThreadId = getOrCreateThreadID(Ident);
1026   Value *Args[] = {ThreadId, Addr, Allocator};
1027   Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_free);
1028   return Builder.CreateCall(Fn, Args, Name);
1029 }
1030 
1031 CallInst *OpenMPIRBuilder::CreateCachedThreadPrivate(
1032     const LocationDescription &Loc, llvm::Value *Pointer,
1033     llvm::ConstantInt *Size, const llvm::Twine &Name) {
1034   IRBuilder<>::InsertPointGuard IPG(Builder);
1035   Builder.restoreIP(Loc.IP);
1036 
1037   Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
1038   Value *Ident = getOrCreateIdent(SrcLocStr);
1039   Value *ThreadId = getOrCreateThreadID(Ident);
1040   Constant *ThreadPrivateCache =
1041       getOrCreateOMPInternalVariable(Int8PtrPtr, Name);
1042   llvm::Value *Args[] = {Ident, ThreadId, Pointer, Size, ThreadPrivateCache};
1043 
1044   Function *Fn =
1045   		getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_threadprivate_cached);
1046 
1047   return Builder.CreateCall(Fn, Args);
1048 }
1049 
1050 std::string OpenMPIRBuilder::getNameWithSeparators(ArrayRef<StringRef> Parts,
1051                                                    StringRef FirstSeparator,
1052                                                    StringRef Separator) {
1053   SmallString<128> Buffer;
1054   llvm::raw_svector_ostream OS(Buffer);
1055   StringRef Sep = FirstSeparator;
1056   for (StringRef Part : Parts) {
1057     OS << Sep << Part;
1058     Sep = Separator;
1059   }
1060   return OS.str().str();
1061 }
1062 
1063 Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable(
1064     llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
1065   // TODO: Replace the twine arg with stringref to get rid of the conversion
1066   // logic. However This is taken from current implementation in clang as is.
1067   // Since this method is used in many places exclusively for OMP internal use
1068   // we will keep it as is for temporarily until we move all users to the
1069   // builder and then, if possible, fix it everywhere in one go.
1070   SmallString<256> Buffer;
1071   llvm::raw_svector_ostream Out(Buffer);
1072   Out << Name;
1073   StringRef RuntimeName = Out.str();
1074   auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
1075   if (Elem.second) {
1076     assert(Elem.second->getType()->getPointerElementType() == Ty &&
1077            "OMP internal variable has different type than requested");
1078   } else {
1079     // TODO: investigate the appropriate linkage type used for the global
1080     // variable for possibly changing that to internal or private, or maybe
1081     // create different versions of the function for different OMP internal
1082     // variables.
1083     Elem.second = new llvm::GlobalVariable(
1084         M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage,
1085         llvm::Constant::getNullValue(Ty), Elem.first(),
1086         /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal,
1087         AddressSpace);
1088   }
1089 
1090   return Elem.second;
1091 }
1092 
1093 Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) {
1094   std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
1095   std::string Name = getNameWithSeparators({Prefix, "var"}, ".", ".");
1096   return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name);
1097 }
1098 
1099 // Create all simple and struct types exposed by the runtime and remember
1100 // the llvm::PointerTypes of them for easy access later.
1101 void OpenMPIRBuilder::initializeTypes(Module &M) {
1102   LLVMContext &Ctx = M.getContext();
1103   StructType *T;
1104 #define OMP_TYPE(VarName, InitValue) VarName = InitValue;
1105 #define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)                             \
1106   VarName##Ty = ArrayType::get(ElemTy, ArraySize);                             \
1107   VarName##PtrTy = PointerType::getUnqual(VarName##Ty);
1108 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)                  \
1109   VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg);            \
1110   VarName##Ptr = PointerType::getUnqual(VarName);
1111 #define OMP_STRUCT_TYPE(VarName, StructName, ...)                              \
1112   T = M.getTypeByName(StructName);                                             \
1113   if (!T)                                                                      \
1114     T = StructType::create(Ctx, {__VA_ARGS__}, StructName);                    \
1115   VarName = T;                                                                 \
1116   VarName##Ptr = PointerType::getUnqual(T);
1117 #include "llvm/Frontend/OpenMP/OMPKinds.def"
1118 }
1119 
1120 void OpenMPIRBuilder::OutlineInfo::collectBlocks(
1121     SmallPtrSetImpl<BasicBlock *> &BlockSet,
1122     SmallVectorImpl<BasicBlock *> &BlockVector) {
1123   SmallVector<BasicBlock *, 32> Worklist;
1124   BlockSet.insert(EntryBB);
1125   BlockSet.insert(ExitBB);
1126 
1127   Worklist.push_back(EntryBB);
1128   while (!Worklist.empty()) {
1129     BasicBlock *BB = Worklist.pop_back_val();
1130     BlockVector.push_back(BB);
1131     for (BasicBlock *SuccBB : successors(BB))
1132       if (BlockSet.insert(SuccBB).second)
1133         Worklist.push_back(SuccBB);
1134   }
1135 }
1136