1 //===-- IPO/OpenMPOpt.cpp - Collection of OpenMP specific optimizations ---===//
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 //
9 // OpenMP specific optimizations:
10 //
11 // - Deduplication of runtime calls, e.g., omp_get_thread_num.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Transforms/IPO/OpenMPOpt.h"
16 
17 #include "llvm/ADT/EnumeratedArray.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/Analysis/CallGraph.h"
20 #include "llvm/Analysis/CallGraphSCCPass.h"
21 #include "llvm/Frontend/OpenMP/OMPConstants.h"
22 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
23 #include "llvm/IR/CallSite.h"
24 #include "llvm/InitializePasses.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Transforms/IPO.h"
27 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
28 
29 using namespace llvm;
30 using namespace omp;
31 using namespace types;
32 
33 #define DEBUG_TYPE "openmp-opt"
34 
35 static cl::opt<bool> DisableOpenMPOptimizations(
36     "openmp-opt-disable", cl::ZeroOrMore,
37     cl::desc("Disable OpenMP specific optimizations."), cl::Hidden,
38     cl::init(false));
39 
40 STATISTIC(NumOpenMPRuntimeCallsDeduplicated,
41           "Number of OpenMP runtime calls deduplicated");
42 STATISTIC(NumOpenMPRuntimeFunctionsIdentified,
43           "Number of OpenMP runtime functions identified");
44 STATISTIC(NumOpenMPRuntimeFunctionUsesIdentified,
45           "Number of OpenMP runtime function uses identified");
46 
47 #if !defined(NDEBUG)
48 static constexpr auto TAG = "[" DEBUG_TYPE "]";
49 #endif
50 
51 namespace {
52 struct OpenMPOpt {
53 
54   OpenMPOpt(SmallVectorImpl<Function *> &SCC,
55             SmallPtrSetImpl<Function *> &ModuleSlice,
56             CallGraphUpdater &CGUpdater)
57       : M(*(*SCC.begin())->getParent()), SCC(SCC), ModuleSlice(ModuleSlice),
58         OMPBuilder(M), CGUpdater(CGUpdater) {
59     initializeTypes(M);
60     initializeRuntimeFunctions();
61     OMPBuilder.initialize();
62   }
63 
64   /// Generic information that describes a runtime function
65   struct RuntimeFunctionInfo {
66     ~RuntimeFunctionInfo() { DeleteContainerSeconds(UsesMap); }
67 
68     /// The kind, as described by the RuntimeFunction enum.
69     RuntimeFunction Kind;
70 
71     /// The name of the function.
72     StringRef Name;
73 
74     /// Flag to indicate a variadic function.
75     bool IsVarArg;
76 
77     /// The return type of the function.
78     Type *ReturnType;
79 
80     /// The argument types of the function.
81     SmallVector<Type *, 8> ArgumentTypes;
82 
83     /// The declaration if available.
84     Function *Declaration = nullptr;
85 
86     /// Uses of this runtime function per function containing the use.
87     using UseVector = SmallVector<Use *, 16>;
88 
89     /// Return the vector of uses in function \p F.
90     UseVector &getOrCreateUseVector(Function *F) {
91       UseVector *&UV = UsesMap[F];
92       if (!UV)
93         UV = new UseVector();
94       return *UV;
95     }
96 
97     /// Return the vector of uses in function \p F or `nullptr` if there are
98     /// none.
99     const UseVector *getUseVector(Function &F) const {
100       return UsesMap.lookup(&F);
101     }
102 
103     /// Return how many functions contain uses of this runtime function.
104     size_t getNumFunctionsWithUses() const { return UsesMap.size(); }
105 
106     /// Return the number of arguments (or the minimal number for variadic
107     /// functions).
108     size_t getNumArgs() const { return ArgumentTypes.size(); }
109 
110     /// Run the callback \p CB on each use and forget the use if the result is
111     /// true. The callback will be fed the function in which the use was
112     /// encountered as second argument.
113     void foreachUse(function_ref<bool(Use &, Function &)> CB) {
114       SmallVector<unsigned, 8> ToBeDeleted;
115       for (auto &It : UsesMap) {
116         ToBeDeleted.clear();
117         unsigned Idx = 0;
118         UseVector &UV = *It.second;
119         for (Use *U : UV) {
120           if (CB(*U, *It.first))
121             ToBeDeleted.push_back(Idx);
122           ++Idx;
123         }
124 
125         // Remove the to-be-deleted indices in reverse order as prior
126         // modifcations will not modify the smaller indices.
127         while (!ToBeDeleted.empty()) {
128           unsigned Idx = ToBeDeleted.pop_back_val();
129           UV[Idx] = UV.back();
130           UV.pop_back();
131         }
132       }
133     }
134 
135   private:
136     /// Map from functions to all uses of this runtime function contained in
137     /// them.
138     DenseMap<Function *, UseVector *> UsesMap;
139   };
140 
141   /// Run all OpenMP optimizations on the underlying SCC/ModuleSlice.
142   bool run() {
143     bool Changed = false;
144 
145     LLVM_DEBUG(dbgs() << TAG << "Run on SCC with " << SCC.size()
146                       << " functions in a slice with " << ModuleSlice.size()
147                       << " functions\n");
148 
149     Changed |= deduplicateRuntimeCalls();
150     Changed |= deleteParallelRegions();
151 
152     return Changed;
153   }
154 
155 private:
156   /// Try to delete parallel regions if possible.
157   bool deleteParallelRegions() {
158     const unsigned CallbackCalleeOperand = 2;
159 
160     RuntimeFunctionInfo &RFI = RFIs[OMPRTL___kmpc_fork_call];
161     if (!RFI.Declaration)
162       return false;
163 
164     bool Changed = false;
165     auto DeleteCallCB = [&](Use &U, Function &) {
166       CallInst *CI = getCallIfRegularCall(U);
167       if (!CI)
168         return false;
169       auto *Fn = dyn_cast<Function>(
170           CI->getArgOperand(CallbackCalleeOperand)->stripPointerCasts());
171       if (!Fn)
172         return false;
173       if (!Fn->onlyReadsMemory())
174         return false;
175       if (!Fn->hasFnAttribute(Attribute::WillReturn))
176         return false;
177 
178       LLVM_DEBUG(dbgs() << TAG << "Delete read-only parallel region in "
179                         << CI->getCaller()->getName() << "\n");
180       CGUpdater.removeCallSite(*CI);
181       CI->eraseFromParent();
182       Changed = true;
183       return true;
184     };
185 
186     RFI.foreachUse(DeleteCallCB);
187 
188     return Changed;
189   }
190 
191   /// Try to eliminiate runtime calls by reusing existing ones.
192   bool deduplicateRuntimeCalls() {
193     bool Changed = false;
194 
195     RuntimeFunction DeduplicableRuntimeCallIDs[] = {
196         OMPRTL_omp_get_num_threads,
197         OMPRTL_omp_in_parallel,
198         OMPRTL_omp_get_cancellation,
199         OMPRTL_omp_get_thread_limit,
200         OMPRTL_omp_get_supported_active_levels,
201         OMPRTL_omp_get_level,
202         OMPRTL_omp_get_ancestor_thread_num,
203         OMPRTL_omp_get_team_size,
204         OMPRTL_omp_get_active_level,
205         OMPRTL_omp_in_final,
206         OMPRTL_omp_get_proc_bind,
207         OMPRTL_omp_get_num_places,
208         OMPRTL_omp_get_num_procs,
209         OMPRTL_omp_get_place_num,
210         OMPRTL_omp_get_partition_num_places,
211         OMPRTL_omp_get_partition_place_nums};
212 
213     // Global-tid is handled separatly.
214     SmallSetVector<Value *, 16> GTIdArgs;
215     collectGlobalThreadIdArguments(GTIdArgs);
216     LLVM_DEBUG(dbgs() << TAG << "Found " << GTIdArgs.size()
217                       << " global thread ID arguments\n");
218 
219     for (Function *F : SCC) {
220       for (auto DeduplicableRuntimeCallID : DeduplicableRuntimeCallIDs)
221         deduplicateRuntimeCalls(*F, RFIs[DeduplicableRuntimeCallID]);
222 
223       // __kmpc_global_thread_num is special as we can replace it with an
224       // argument in enough cases to make it worth trying.
225       Value *GTIdArg = nullptr;
226       for (Argument &Arg : F->args())
227         if (GTIdArgs.count(&Arg)) {
228           GTIdArg = &Arg;
229           break;
230         }
231       Changed |= deduplicateRuntimeCalls(
232           *F, RFIs[OMPRTL___kmpc_global_thread_num], GTIdArg);
233     }
234 
235     return Changed;
236   }
237 
238   static Value *combinedIdentStruct(Value *CurrentIdent, Value *NextIdent,
239                                     bool GlobalOnly, bool &SingleChoice) {
240     if (CurrentIdent == NextIdent)
241       return CurrentIdent;
242 
243     // TODO: Figure out how to actually combine multiple debug locations. For
244     //       now we just keep an existing one if there is a single choice.
245     if (!GlobalOnly || isa<GlobalValue>(NextIdent)) {
246       SingleChoice = !CurrentIdent;
247       return NextIdent;
248     }
249     return nullptr;
250   }
251 
252   /// Return an `struct ident_t*` value that represents the ones used in the
253   /// calls of \p RFI inside of \p F. If \p GlobalOnly is true, we will not
254   /// return a local `struct ident_t*`. For now, if we cannot find a suitable
255   /// return value we create one from scratch. We also do not yet combine
256   /// information, e.g., the source locations, see combinedIdentStruct.
257   Value *getCombinedIdentFromCallUsesIn(RuntimeFunctionInfo &RFI, Function &F,
258                                         bool GlobalOnly) {
259     bool SingleChoice = true;
260     Value *Ident = nullptr;
261     auto CombineIdentStruct = [&](Use &U, Function &Caller) {
262       CallInst *CI = getCallIfRegularCall(U, &RFI);
263       if (!CI || &F != &Caller)
264         return false;
265       Ident = combinedIdentStruct(Ident, CI->getArgOperand(0),
266                                   /* GlobalOnly */ true, SingleChoice);
267       return false;
268     };
269     RFI.foreachUse(CombineIdentStruct);
270 
271     if (!Ident || !SingleChoice) {
272       // The IRBuilder uses the insertion block to get to the module, this is
273       // unfortunate but we work around it for now.
274       if (!OMPBuilder.getInsertionPoint().getBlock())
275         OMPBuilder.updateToLocation(OpenMPIRBuilder::InsertPointTy(
276             &F.getEntryBlock(), F.getEntryBlock().begin()));
277       // Create a fallback location if non was found.
278       // TODO: Use the debug locations of the calls instead.
279       Constant *Loc = OMPBuilder.getOrCreateDefaultSrcLocStr();
280       Ident = OMPBuilder.getOrCreateIdent(Loc);
281     }
282     return Ident;
283   }
284 
285   /// Try to eliminiate calls of \p RFI in \p F by reusing an existing one or
286   /// \p ReplVal if given.
287   bool deduplicateRuntimeCalls(Function &F, RuntimeFunctionInfo &RFI,
288                                Value *ReplVal = nullptr) {
289     auto *UV = RFI.getUseVector(F);
290     if (!UV || UV->size() + (ReplVal != nullptr) < 2)
291       return false;
292 
293     LLVM_DEBUG(dbgs() << TAG << "Deduplicate " << UV->size() << " uses of "
294                       << RFI.Name
295                       << (ReplVal ? " with an existing value\n" : "\n")
296                       << "\n");
297     assert((!ReplVal || (isa<Argument>(ReplVal) &&
298                          cast<Argument>(ReplVal)->getParent() == &F)) &&
299            "Unexpected replacement value!");
300 
301     // TODO: Use dominance to find a good position instead.
302     auto CanBeMoved = [](CallBase &CB) {
303       unsigned NumArgs = CB.getNumArgOperands();
304       if (NumArgs == 0)
305         return true;
306       if (CB.getArgOperand(0)->getType() != IdentPtr)
307         return false;
308       for (unsigned u = 1; u < NumArgs; ++u)
309         if (isa<Instruction>(CB.getArgOperand(u)))
310           return false;
311       return true;
312     };
313 
314     if (!ReplVal) {
315       for (Use *U : *UV)
316         if (CallInst *CI = getCallIfRegularCall(*U, &RFI)) {
317           if (!CanBeMoved(*CI))
318             continue;
319           CI->moveBefore(&*F.getEntryBlock().getFirstInsertionPt());
320           ReplVal = CI;
321           break;
322         }
323       if (!ReplVal)
324         return false;
325     }
326 
327     // If we use a call as a replacement value we need to make sure the ident is
328     // valid at the new location. For now we just pick a global one, either
329     // existing and used by one of the calls, or created from scratch.
330     if (CallBase *CI = dyn_cast<CallBase>(ReplVal)) {
331       if (CI->getNumArgOperands() > 0 &&
332           CI->getArgOperand(0)->getType() == IdentPtr) {
333         Value *Ident = getCombinedIdentFromCallUsesIn(RFI, F,
334                                                       /* GlobalOnly */ true);
335         CI->setArgOperand(0, Ident);
336       }
337     }
338 
339     bool Changed = false;
340     auto ReplaceAndDeleteCB = [&](Use &U, Function &Caller) {
341       CallInst *CI = getCallIfRegularCall(U, &RFI);
342       if (!CI || CI == ReplVal || &F != &Caller)
343         return false;
344       assert(CI->getCaller() == &F && "Unexpected call!");
345       CGUpdater.removeCallSite(*CI);
346       CI->replaceAllUsesWith(ReplVal);
347       CI->eraseFromParent();
348       ++NumOpenMPRuntimeCallsDeduplicated;
349       Changed = true;
350       return true;
351     };
352     RFI.foreachUse(ReplaceAndDeleteCB);
353 
354     return Changed;
355   }
356 
357   /// Collect arguments that represent the global thread id in \p GTIdArgs.
358   void collectGlobalThreadIdArguments(SmallSetVector<Value *, 16> &GTIdArgs) {
359     // TODO: Below we basically perform a fixpoint iteration with a pessimistic
360     //       initialization. We could define an AbstractAttribute instead and
361     //       run the Attributor here once it can be run as an SCC pass.
362 
363     // Helper to check the argument \p ArgNo at all call sites of \p F for
364     // a GTId.
365     auto CallArgOpIsGTId = [&](Function &F, unsigned ArgNo, CallInst &RefCI) {
366       if (!F.hasLocalLinkage())
367         return false;
368       for (Use &U : F.uses()) {
369         if (CallInst *CI = getCallIfRegularCall(U)) {
370           Value *ArgOp = CI->getArgOperand(ArgNo);
371           if (CI == &RefCI || GTIdArgs.count(ArgOp) ||
372               getCallIfRegularCall(*ArgOp,
373                                    &RFIs[OMPRTL___kmpc_global_thread_num]))
374             continue;
375         }
376         return false;
377       }
378       return true;
379     };
380 
381     // Helper to identify uses of a GTId as GTId arguments.
382     auto AddUserArgs = [&](Value &GTId) {
383       for (Use &U : GTId.uses())
384         if (CallInst *CI = dyn_cast<CallInst>(U.getUser()))
385           if (CI->isArgOperand(&U))
386             if (Function *Callee = CI->getCalledFunction())
387               if (CallArgOpIsGTId(*Callee, U.getOperandNo(), *CI))
388                 GTIdArgs.insert(Callee->getArg(U.getOperandNo()));
389     };
390 
391     // The argument users of __kmpc_global_thread_num calls are GTIds.
392     RuntimeFunctionInfo &GlobThreadNumRFI =
393         RFIs[OMPRTL___kmpc_global_thread_num];
394     GlobThreadNumRFI.foreachUse([&](Use &U, Function &F) {
395       if (CallInst *CI = getCallIfRegularCall(U, &GlobThreadNumRFI))
396         AddUserArgs(*CI);
397       return false;
398     });
399 
400     // Transitively search for more arguments by looking at the users of the
401     // ones we know already. During the search the GTIdArgs vector is extended
402     // so we cannot cache the size nor can we use a range based for.
403     for (unsigned u = 0; u < GTIdArgs.size(); ++u)
404       AddUserArgs(*GTIdArgs[u]);
405   }
406 
407   /// Return the call if \p U is a callee use in a regular call. If \p RFI is
408   /// given it has to be the callee or a nullptr is returned.
409   CallInst *getCallIfRegularCall(Use &U, RuntimeFunctionInfo *RFI = nullptr) {
410     CallInst *CI = dyn_cast<CallInst>(U.getUser());
411     if (CI && CI->isCallee(&U) && !CI->hasOperandBundles() &&
412         (!RFI || CI->getCalledFunction() == RFI->Declaration))
413       return CI;
414     return nullptr;
415   }
416 
417   /// Return the call if \p V is a regular call. If \p RFI is given it has to be
418   /// the callee or a nullptr is returned.
419   CallInst *getCallIfRegularCall(Value &V, RuntimeFunctionInfo *RFI = nullptr) {
420     CallInst *CI = dyn_cast<CallInst>(&V);
421     if (CI && !CI->hasOperandBundles() &&
422         (!RFI || CI->getCalledFunction() == RFI->Declaration))
423       return CI;
424     return nullptr;
425   }
426 
427   /// Returns true if the function declaration \p F matches the runtime
428   /// function types, that is, return type \p RTFRetType, and argument types
429   /// \p RTFArgTypes.
430   static bool declMatchesRTFTypes(Function *F, Type *RTFRetType,
431                                   SmallVector<Type *, 8> &RTFArgTypes) {
432     // TODO: We should output information to the user (under debug output
433     //       and via remarks).
434 
435     if (!F)
436       return false;
437     if (F->getReturnType() != RTFRetType)
438       return false;
439     if (F->arg_size() != RTFArgTypes.size())
440       return false;
441 
442     auto RTFTyIt = RTFArgTypes.begin();
443     for (Argument &Arg : F->args()) {
444       if (Arg.getType() != *RTFTyIt)
445         return false;
446 
447       ++RTFTyIt;
448     }
449 
450     return true;
451   }
452 
453   /// Helper to initialize all runtime function information for those defined in
454   /// OpenMPKinds.def.
455   void initializeRuntimeFunctions() {
456     // Helper to collect all uses of the decleration in the UsesMap.
457     auto CollectUses = [&](RuntimeFunctionInfo &RFI) {
458       unsigned NumUses = 0;
459       if (!RFI.Declaration)
460         return NumUses;
461       OMPBuilder.addAttributes(RFI.Kind, *RFI.Declaration);
462 
463       NumOpenMPRuntimeFunctionsIdentified += 1;
464       NumOpenMPRuntimeFunctionUsesIdentified += RFI.Declaration->getNumUses();
465 
466       // TODO: We directly convert uses into proper calls and unknown uses.
467       for (Use &U : RFI.Declaration->uses()) {
468         if (Instruction *UserI = dyn_cast<Instruction>(U.getUser())) {
469           if (ModuleSlice.count(UserI->getFunction())) {
470             RFI.getOrCreateUseVector(UserI->getFunction()).push_back(&U);
471             ++NumUses;
472           }
473         } else {
474           RFI.getOrCreateUseVector(nullptr).push_back(&U);
475           ++NumUses;
476         }
477       }
478       return NumUses;
479     };
480 
481 #define OMP_RTL(_Enum, _Name, _IsVarArg, _ReturnType, ...)                     \
482   {                                                                            \
483     SmallVector<Type *, 8> ArgsTypes({__VA_ARGS__});                           \
484     Function *F = M.getFunction(_Name);                                        \
485     if (declMatchesRTFTypes(F, _ReturnType, ArgsTypes)) {                      \
486       auto &RFI = RFIs[_Enum];                                                 \
487       RFI.Kind = _Enum;                                                        \
488       RFI.Name = _Name;                                                        \
489       RFI.IsVarArg = _IsVarArg;                                                \
490       RFI.ReturnType = _ReturnType;                                            \
491       RFI.ArgumentTypes = std::move(ArgsTypes);                                \
492       RFI.Declaration = F;                                                     \
493       unsigned NumUses = CollectUses(RFI);                                     \
494       (void)NumUses;                                                           \
495       LLVM_DEBUG({                                                             \
496         dbgs() << TAG << RFI.Name << (RFI.Declaration ? "" : " not")           \
497                << " found\n";                                                  \
498         if (RFI.Declaration)                                                   \
499           dbgs() << TAG << "-> got " << NumUses << " uses in "                 \
500                  << RFI.getNumFunctionsWithUses()                              \
501                  << " different functions.\n";                                 \
502       });                                                                      \
503     }                                                                          \
504   }
505 #include "llvm/Frontend/OpenMP/OMPKinds.def"
506 
507     // TODO: We should attach the attributes defined in OMPKinds.def.
508   }
509 
510   /// The underyling module.
511   Module &M;
512 
513   /// The SCC we are operating on.
514   SmallVectorImpl<Function *> &SCC;
515 
516   /// The slice of the module we are allowed to look at.
517   SmallPtrSetImpl<Function *> &ModuleSlice;
518 
519   /// An OpenMP-IR-Builder instance
520   OpenMPIRBuilder OMPBuilder;
521 
522   /// Callback to update the call graph, the first argument is a removed call,
523   /// the second an optional replacement call.
524   CallGraphUpdater &CGUpdater;
525 
526   /// Map from runtime function kind to the runtime function description.
527   EnumeratedArray<RuntimeFunctionInfo, RuntimeFunction,
528                   RuntimeFunction::OMPRTL___last>
529       RFIs;
530 };
531 } // namespace
532 
533 PreservedAnalyses OpenMPOptPass::run(LazyCallGraph::SCC &C,
534                                      CGSCCAnalysisManager &AM,
535                                      LazyCallGraph &CG, CGSCCUpdateResult &UR) {
536   if (!containsOpenMP(*C.begin()->getFunction().getParent(), OMPInModule))
537     return PreservedAnalyses::all();
538 
539   if (DisableOpenMPOptimizations)
540     return PreservedAnalyses::all();
541 
542   SmallPtrSet<Function *, 16> ModuleSlice;
543   SmallVector<Function *, 16> SCC;
544   for (LazyCallGraph::Node &N : C) {
545     SCC.push_back(&N.getFunction());
546     ModuleSlice.insert(SCC.back());
547   }
548 
549   if (SCC.empty())
550     return PreservedAnalyses::all();
551 
552   CallGraphUpdater CGUpdater;
553   CGUpdater.initialize(CG, C, AM, UR);
554   // TODO: Compute the module slice we are allowed to look at.
555   OpenMPOpt OMPOpt(SCC, ModuleSlice, CGUpdater);
556   bool Changed = OMPOpt.run();
557   (void)Changed;
558   return PreservedAnalyses::all();
559 }
560 
561 namespace {
562 
563 struct OpenMPOptLegacyPass : public CallGraphSCCPass {
564   CallGraphUpdater CGUpdater;
565   OpenMPInModule OMPInModule;
566   static char ID;
567 
568   OpenMPOptLegacyPass() : CallGraphSCCPass(ID) {
569     initializeOpenMPOptLegacyPassPass(*PassRegistry::getPassRegistry());
570   }
571 
572   void getAnalysisUsage(AnalysisUsage &AU) const override {
573     CallGraphSCCPass::getAnalysisUsage(AU);
574   }
575 
576   bool doInitialization(CallGraph &CG) override {
577     // Disable the pass if there is no OpenMP (runtime call) in the module.
578     containsOpenMP(CG.getModule(), OMPInModule);
579     return false;
580   }
581 
582   bool runOnSCC(CallGraphSCC &CGSCC) override {
583     if (!containsOpenMP(CGSCC.getCallGraph().getModule(), OMPInModule))
584       return false;
585     if (DisableOpenMPOptimizations || skipSCC(CGSCC))
586       return false;
587 
588     SmallPtrSet<Function *, 16> ModuleSlice;
589     SmallVector<Function *, 16> SCC;
590     for (CallGraphNode *CGN : CGSCC)
591       if (Function *Fn = CGN->getFunction())
592         if (!Fn->isDeclaration()) {
593           SCC.push_back(Fn);
594           ModuleSlice.insert(Fn);
595         }
596 
597     if (SCC.empty())
598       return false;
599 
600     CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
601     CGUpdater.initialize(CG, CGSCC);
602 
603     // TODO: Compute the module slice we are allowed to look at.
604     OpenMPOpt OMPOpt(SCC, ModuleSlice, CGUpdater);
605     return OMPOpt.run();
606   }
607 
608   bool doFinalization(CallGraph &CG) override { return CGUpdater.finalize(); }
609 };
610 
611 } // end anonymous namespace
612 
613 bool llvm::omp::containsOpenMP(Module &M, OpenMPInModule &OMPInModule) {
614   if (OMPInModule.isKnown())
615     return OMPInModule;
616 
617 #define OMP_RTL(_Enum, _Name, ...)                                             \
618   if (M.getFunction(_Name))                                                    \
619     return OMPInModule = true;
620 #include "llvm/Frontend/OpenMP/OMPKinds.def"
621   return OMPInModule = false;
622 }
623 
624 char OpenMPOptLegacyPass::ID = 0;
625 
626 INITIALIZE_PASS_BEGIN(OpenMPOptLegacyPass, "openmpopt",
627                       "OpenMP specific optimizations", false, false)
628 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
629 INITIALIZE_PASS_END(OpenMPOptLegacyPass, "openmpopt",
630                     "OpenMP specific optimizations", false, false)
631 
632 Pass *llvm::createOpenMPOptLegacyPass() { return new OpenMPOptLegacyPass(); }
633