xref: /llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (revision 75da10d1b2db41f6789846ff499e2842cfe5de8e)
1 //===- ModuleSummaryAnalysis.cpp - Module summary index builder -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass builds a ModuleSummaryIndex object for the module, to be written
11 // to bitcode or LLVM assembly.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Analysis/ModuleSummaryAnalysis.h"
16 #include "llvm/ADT/MapVector.h"
17 #include "llvm/ADT/SetVector.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Analysis/BlockFrequencyInfo.h"
20 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
21 #include "llvm/Analysis/BranchProbabilityInfo.h"
22 #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
23 #include "llvm/Analysis/LoopInfo.h"
24 #include "llvm/Analysis/ProfileSummaryInfo.h"
25 #include "llvm/Analysis/TypeMetadataUtils.h"
26 #include "llvm/IR/CallSite.h"
27 #include "llvm/IR/Dominators.h"
28 #include "llvm/IR/InstIterator.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/IR/ValueSymbolTable.h"
31 #include "llvm/Object/ModuleSymbolTable.h"
32 #include "llvm/Pass.h"
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "module-summary-analysis"
36 
37 // Walk through the operands of a given User via worklist iteration and populate
38 // the set of GlobalValue references encountered. Invoked either on an
39 // Instruction or a GlobalVariable (which walks its initializer).
40 static void findRefEdges(ModuleSummaryIndex &Index, const User *CurUser,
41                          SetVector<ValueInfo> &RefEdges,
42                          SmallPtrSet<const User *, 8> &Visited) {
43   SmallVector<const User *, 32> Worklist;
44   Worklist.push_back(CurUser);
45 
46   while (!Worklist.empty()) {
47     const User *U = Worklist.pop_back_val();
48 
49     if (!Visited.insert(U).second)
50       continue;
51 
52     ImmutableCallSite CS(U);
53 
54     for (const auto &OI : U->operands()) {
55       const User *Operand = dyn_cast<User>(OI);
56       if (!Operand)
57         continue;
58       if (isa<BlockAddress>(Operand))
59         continue;
60       if (auto *GV = dyn_cast<GlobalValue>(Operand)) {
61         // We have a reference to a global value. This should be added to
62         // the reference set unless it is a callee. Callees are handled
63         // specially by WriteFunction and are added to a separate list.
64         if (!(CS && CS.isCallee(&OI)))
65           RefEdges.insert(Index.getOrInsertValueInfo(GV));
66         continue;
67       }
68       Worklist.push_back(Operand);
69     }
70   }
71 }
72 
73 static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount,
74                                           ProfileSummaryInfo *PSI) {
75   if (!PSI)
76     return CalleeInfo::HotnessType::Unknown;
77   if (PSI->isHotCount(ProfileCount))
78     return CalleeInfo::HotnessType::Hot;
79   if (PSI->isColdCount(ProfileCount))
80     return CalleeInfo::HotnessType::Cold;
81   return CalleeInfo::HotnessType::None;
82 }
83 
84 static bool isNonRenamableLocal(const GlobalValue &GV) {
85   return GV.hasSection() && GV.hasLocalLinkage();
86 }
87 
88 /// Determine whether this call has all constant integer arguments (excluding
89 /// "this") and summarize it to VCalls or ConstVCalls as appropriate.
90 static void addVCallToSet(DevirtCallSite Call, GlobalValue::GUID Guid,
91                           SetVector<FunctionSummary::VFuncId> &VCalls,
92                           SetVector<FunctionSummary::ConstVCall> &ConstVCalls) {
93   std::vector<uint64_t> Args;
94   // Start from the second argument to skip the "this" pointer.
95   for (auto &Arg : make_range(Call.CS.arg_begin() + 1, Call.CS.arg_end())) {
96     auto *CI = dyn_cast<ConstantInt>(Arg);
97     if (!CI || CI->getBitWidth() > 64) {
98       VCalls.insert({Guid, Call.Offset});
99       return;
100     }
101     Args.push_back(CI->getZExtValue());
102   }
103   ConstVCalls.insert({{Guid, Call.Offset}, std::move(Args)});
104 }
105 
106 /// If this intrinsic call requires that we add information to the function
107 /// summary, do so via the non-constant reference arguments.
108 static void addIntrinsicToSummary(
109     const CallInst *CI, SetVector<GlobalValue::GUID> &TypeTests,
110     SetVector<FunctionSummary::VFuncId> &TypeTestAssumeVCalls,
111     SetVector<FunctionSummary::VFuncId> &TypeCheckedLoadVCalls,
112     SetVector<FunctionSummary::ConstVCall> &TypeTestAssumeConstVCalls,
113     SetVector<FunctionSummary::ConstVCall> &TypeCheckedLoadConstVCalls) {
114   switch (CI->getCalledFunction()->getIntrinsicID()) {
115   case Intrinsic::type_test: {
116     auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(1));
117     auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
118     if (!TypeId)
119       break;
120     GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
121 
122     // Produce a summary from type.test intrinsics. We only summarize type.test
123     // intrinsics that are used other than by an llvm.assume intrinsic.
124     // Intrinsics that are assumed are relevant only to the devirtualization
125     // pass, not the type test lowering pass.
126     bool HasNonAssumeUses = llvm::any_of(CI->uses(), [](const Use &CIU) {
127       auto *AssumeCI = dyn_cast<CallInst>(CIU.getUser());
128       if (!AssumeCI)
129         return true;
130       Function *F = AssumeCI->getCalledFunction();
131       return !F || F->getIntrinsicID() != Intrinsic::assume;
132     });
133     if (HasNonAssumeUses)
134       TypeTests.insert(Guid);
135 
136     SmallVector<DevirtCallSite, 4> DevirtCalls;
137     SmallVector<CallInst *, 4> Assumes;
138     findDevirtualizableCallsForTypeTest(DevirtCalls, Assumes, CI);
139     for (auto &Call : DevirtCalls)
140       addVCallToSet(Call, Guid, TypeTestAssumeVCalls,
141                     TypeTestAssumeConstVCalls);
142 
143     break;
144   }
145 
146   case Intrinsic::type_checked_load: {
147     auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(2));
148     auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata());
149     if (!TypeId)
150       break;
151     GlobalValue::GUID Guid = GlobalValue::getGUID(TypeId->getString());
152 
153     SmallVector<DevirtCallSite, 4> DevirtCalls;
154     SmallVector<Instruction *, 4> LoadedPtrs;
155     SmallVector<Instruction *, 4> Preds;
156     bool HasNonCallUses = false;
157     findDevirtualizableCallsForTypeCheckedLoad(DevirtCalls, LoadedPtrs, Preds,
158                                                HasNonCallUses, CI);
159     // Any non-call uses of the result of llvm.type.checked.load will
160     // prevent us from optimizing away the llvm.type.test.
161     if (HasNonCallUses)
162       TypeTests.insert(Guid);
163     for (auto &Call : DevirtCalls)
164       addVCallToSet(Call, Guid, TypeCheckedLoadVCalls,
165                     TypeCheckedLoadConstVCalls);
166 
167     break;
168   }
169   default:
170     break;
171   }
172 }
173 
174 static void
175 computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
176                        const Function &F, BlockFrequencyInfo *BFI,
177                        ProfileSummaryInfo *PSI, bool HasLocalsInUsed,
178                        DenseSet<GlobalValue::GUID> &CantBePromoted) {
179   // Summary not currently supported for anonymous functions, they should
180   // have been named.
181   assert(F.hasName());
182 
183   unsigned NumInsts = 0;
184   // Map from callee ValueId to profile count. Used to accumulate profile
185   // counts for all static calls to a given callee.
186   MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
187   SetVector<ValueInfo> RefEdges;
188   SetVector<GlobalValue::GUID> TypeTests;
189   SetVector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
190       TypeCheckedLoadVCalls;
191   SetVector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
192       TypeCheckedLoadConstVCalls;
193   ICallPromotionAnalysis ICallAnalysis;
194 
195   bool HasInlineAsmMaybeReferencingInternal = false;
196   SmallPtrSet<const User *, 8> Visited;
197   for (const BasicBlock &BB : F)
198     for (const Instruction &I : BB) {
199       if (isa<DbgInfoIntrinsic>(I))
200         continue;
201       ++NumInsts;
202       findRefEdges(Index, &I, RefEdges, Visited);
203       auto CS = ImmutableCallSite(&I);
204       if (!CS)
205         continue;
206 
207       const auto *CI = dyn_cast<CallInst>(&I);
208       // Since we don't know exactly which local values are referenced in inline
209       // assembly, conservatively mark the function as possibly referencing
210       // a local value from inline assembly to ensure we don't export a
211       // reference (which would require renaming and promotion of the
212       // referenced value).
213       if (HasLocalsInUsed && CI && CI->isInlineAsm())
214         HasInlineAsmMaybeReferencingInternal = true;
215 
216       auto *CalledValue = CS.getCalledValue();
217       auto *CalledFunction = CS.getCalledFunction();
218       // Check if this is an alias to a function. If so, get the
219       // called aliasee for the checks below.
220       if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
221         assert(!CalledFunction && "Expected null called function in callsite for alias");
222         CalledFunction = dyn_cast<Function>(GA->getBaseObject());
223       }
224       // Check if this is a direct call to a known function or a known
225       // intrinsic, or an indirect call with profile data.
226       if (CalledFunction) {
227         if (CI && CalledFunction->isIntrinsic()) {
228           addIntrinsicToSummary(
229               CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls,
230               TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls);
231           continue;
232         }
233         // We should have named any anonymous globals
234         assert(CalledFunction->hasName());
235         auto ScaledCount = PSI->getProfileCount(&I, BFI);
236         auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
237                                    : CalleeInfo::HotnessType::Unknown;
238 
239         // Use the original CalledValue, in case it was an alias. We want
240         // to record the call edge to the alias in that case. Eventually
241         // an alias summary will be created to associate the alias and
242         // aliasee.
243         CallGraphEdges[Index.getOrInsertValueInfo(
244                            cast<GlobalValue>(CalledValue))]
245             .updateHotness(Hotness);
246       } else {
247         // Skip inline assembly calls.
248         if (CI && CI->isInlineAsm())
249           continue;
250         // Skip direct calls.
251         if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
252           continue;
253 
254         uint32_t NumVals, NumCandidates;
255         uint64_t TotalCount;
256         auto CandidateProfileData =
257             ICallAnalysis.getPromotionCandidatesForInstruction(
258                 &I, NumVals, TotalCount, NumCandidates);
259         for (auto &Candidate : CandidateProfileData)
260           CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)]
261               .updateHotness(getHotness(Candidate.Count, PSI));
262       }
263     }
264 
265   // Explicit add hot edges to enforce importing for designated GUIDs for
266   // sample PGO, to enable the same inlines as the profiled optimized binary.
267   for (auto &I : F.getImportGUIDs())
268     CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(
269         CalleeInfo::HotnessType::Critical);
270 
271   bool NonRenamableLocal = isNonRenamableLocal(F);
272   bool NotEligibleForImport =
273       NonRenamableLocal || HasInlineAsmMaybeReferencingInternal ||
274       // Inliner doesn't handle variadic functions.
275       // FIXME: refactor this to use the same code that inliner is using.
276       F.isVarArg();
277   GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
278                                     /* Live = */ false);
279   FunctionSummary::FFlags FunFlags{
280       F.hasFnAttribute(Attribute::ReadNone),
281       F.hasFnAttribute(Attribute::ReadOnly),
282       F.hasFnAttribute(Attribute::NoRecurse),
283       F.returnDoesNotAlias(),
284   };
285   auto FuncSummary = llvm::make_unique<FunctionSummary>(
286       Flags, NumInsts, FunFlags, RefEdges.takeVector(),
287       CallGraphEdges.takeVector(), TypeTests.takeVector(),
288       TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
289       TypeTestAssumeConstVCalls.takeVector(),
290       TypeCheckedLoadConstVCalls.takeVector());
291   if (NonRenamableLocal)
292     CantBePromoted.insert(F.getGUID());
293   Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
294 }
295 
296 static void
297 computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
298                        DenseSet<GlobalValue::GUID> &CantBePromoted) {
299   SetVector<ValueInfo> RefEdges;
300   SmallPtrSet<const User *, 8> Visited;
301   findRefEdges(Index, &V, RefEdges, Visited);
302   bool NonRenamableLocal = isNonRenamableLocal(V);
303   GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
304                                     /* Live = */ false);
305   auto GVarSummary =
306       llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector());
307   if (NonRenamableLocal)
308     CantBePromoted.insert(V.getGUID());
309   Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
310 }
311 
312 static void
313 computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
314                     DenseSet<GlobalValue::GUID> &CantBePromoted) {
315   bool NonRenamableLocal = isNonRenamableLocal(A);
316   GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal,
317                                     /* Live = */ false);
318   auto AS = llvm::make_unique<AliasSummary>(Flags, ArrayRef<ValueInfo>{});
319   auto *Aliasee = A.getBaseObject();
320   auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
321   assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
322   AS->setAliasee(AliaseeSummary);
323   if (NonRenamableLocal)
324     CantBePromoted.insert(A.getGUID());
325   Index.addGlobalValueSummary(A.getName(), std::move(AS));
326 }
327 
328 // Set LiveRoot flag on entries matching the given value name.
329 static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) {
330   if (ValueInfo VI = Index.getValueInfo(GlobalValue::getGUID(Name)))
331     for (auto &Summary : VI.getSummaryList())
332       Summary->setLive(true);
333 }
334 
335 ModuleSummaryIndex llvm::buildModuleSummaryIndex(
336     const Module &M,
337     std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
338     ProfileSummaryInfo *PSI) {
339   assert(PSI);
340   ModuleSummaryIndex Index;
341 
342   // Identify the local values in the llvm.used and llvm.compiler.used sets,
343   // which should not be exported as they would then require renaming and
344   // promotion, but we may have opaque uses e.g. in inline asm. We collect them
345   // here because we use this information to mark functions containing inline
346   // assembly calls as not importable.
347   SmallPtrSet<GlobalValue *, 8> LocalsUsed;
348   SmallPtrSet<GlobalValue *, 8> Used;
349   // First collect those in the llvm.used set.
350   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
351   // Next collect those in the llvm.compiler.used set.
352   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ true);
353   DenseSet<GlobalValue::GUID> CantBePromoted;
354   for (auto *V : Used) {
355     if (V->hasLocalLinkage()) {
356       LocalsUsed.insert(V);
357       CantBePromoted.insert(V->getGUID());
358     }
359   }
360 
361   // Compute summaries for all functions defined in module, and save in the
362   // index.
363   for (auto &F : M) {
364     if (F.isDeclaration())
365       continue;
366 
367     BlockFrequencyInfo *BFI = nullptr;
368     std::unique_ptr<BlockFrequencyInfo> BFIPtr;
369     if (GetBFICallback)
370       BFI = GetBFICallback(F);
371     else if (F.getEntryCount().hasValue()) {
372       LoopInfo LI{DominatorTree(const_cast<Function &>(F))};
373       BranchProbabilityInfo BPI{F, LI};
374       BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
375       BFI = BFIPtr.get();
376     }
377 
378     computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty(),
379                            CantBePromoted);
380   }
381 
382   // Compute summaries for all variables defined in module, and save in the
383   // index.
384   for (const GlobalVariable &G : M.globals()) {
385     if (G.isDeclaration())
386       continue;
387     computeVariableSummary(Index, G, CantBePromoted);
388   }
389 
390   // Compute summaries for all aliases defined in module, and save in the
391   // index.
392   for (const GlobalAlias &A : M.aliases())
393     computeAliasSummary(Index, A, CantBePromoted);
394 
395   for (auto *V : LocalsUsed) {
396     auto *Summary = Index.getGlobalValueSummary(*V);
397     assert(Summary && "Missing summary for global value");
398     Summary->setNotEligibleToImport();
399   }
400 
401   // The linker doesn't know about these LLVM produced values, so we need
402   // to flag them as live in the index to ensure index-based dead value
403   // analysis treats them as live roots of the analysis.
404   setLiveRoot(Index, "llvm.used");
405   setLiveRoot(Index, "llvm.compiler.used");
406   setLiveRoot(Index, "llvm.global_ctors");
407   setLiveRoot(Index, "llvm.global_dtors");
408   setLiveRoot(Index, "llvm.global.annotations");
409 
410   if (!M.getModuleInlineAsm().empty()) {
411     // Collect the local values defined by module level asm, and set up
412     // summaries for these symbols so that they can be marked as NoRename,
413     // to prevent export of any use of them in regular IR that would require
414     // renaming within the module level asm. Note we don't need to create a
415     // summary for weak or global defs, as they don't need to be flagged as
416     // NoRename, and defs in module level asm can't be imported anyway.
417     // Also, any values used but not defined within module level asm should
418     // be listed on the llvm.used or llvm.compiler.used global and marked as
419     // referenced from there.
420     ModuleSymbolTable::CollectAsmSymbols(
421         M, [&M, &Index, &CantBePromoted](StringRef Name,
422                                          object::BasicSymbolRef::Flags Flags) {
423           // Symbols not marked as Weak or Global are local definitions.
424           if (Flags & (object::BasicSymbolRef::SF_Weak |
425                        object::BasicSymbolRef::SF_Global))
426             return;
427           GlobalValue *GV = M.getNamedValue(Name);
428           if (!GV)
429             return;
430           assert(GV->isDeclaration() && "Def in module asm already has definition");
431           GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage,
432                                               /* NotEligibleToImport = */ true,
433                                               /* Live = */ true);
434           CantBePromoted.insert(GlobalValue::getGUID(Name));
435           // Create the appropriate summary type.
436           if (Function *F = dyn_cast<Function>(GV)) {
437             std::unique_ptr<FunctionSummary> Summary =
438                 llvm::make_unique<FunctionSummary>(
439                     GVFlags, 0,
440                     FunctionSummary::FFlags{
441                         F->hasFnAttribute(Attribute::ReadNone),
442                         F->hasFnAttribute(Attribute::ReadOnly),
443                         F->hasFnAttribute(Attribute::NoRecurse),
444                         F->returnDoesNotAlias()},
445                     ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
446                     ArrayRef<GlobalValue::GUID>{},
447                     ArrayRef<FunctionSummary::VFuncId>{},
448                     ArrayRef<FunctionSummary::VFuncId>{},
449                     ArrayRef<FunctionSummary::ConstVCall>{},
450                     ArrayRef<FunctionSummary::ConstVCall>{});
451             Index.addGlobalValueSummary(Name, std::move(Summary));
452           } else {
453             std::unique_ptr<GlobalVarSummary> Summary =
454                 llvm::make_unique<GlobalVarSummary>(GVFlags,
455                                                     ArrayRef<ValueInfo>{});
456             Index.addGlobalValueSummary(Name, std::move(Summary));
457           }
458         });
459   }
460 
461   bool IsThinLTO = true;
462   if (auto *MD =
463           mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
464     IsThinLTO = MD->getZExtValue();
465 
466   for (auto &GlobalList : Index) {
467     // Ignore entries for references that are undefined in the current module.
468     if (GlobalList.second.SummaryList.empty())
469       continue;
470 
471     assert(GlobalList.second.SummaryList.size() == 1 &&
472            "Expected module's index to have one summary per GUID");
473     auto &Summary = GlobalList.second.SummaryList[0];
474     if (!IsThinLTO) {
475       Summary->setNotEligibleToImport();
476       continue;
477     }
478 
479     bool AllRefsCanBeExternallyReferenced =
480         llvm::all_of(Summary->refs(), [&](const ValueInfo &VI) {
481           return !CantBePromoted.count(VI.getGUID());
482         });
483     if (!AllRefsCanBeExternallyReferenced) {
484       Summary->setNotEligibleToImport();
485       continue;
486     }
487 
488     if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
489       bool AllCallsCanBeExternallyReferenced = llvm::all_of(
490           FuncSummary->calls(), [&](const FunctionSummary::EdgeTy &Edge) {
491             return !CantBePromoted.count(Edge.first.getGUID());
492           });
493       if (!AllCallsCanBeExternallyReferenced)
494         Summary->setNotEligibleToImport();
495     }
496   }
497 
498   return Index;
499 }
500 
501 AnalysisKey ModuleSummaryIndexAnalysis::Key;
502 
503 ModuleSummaryIndex
504 ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
505   ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
506   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
507   return buildModuleSummaryIndex(
508       M,
509       [&FAM](const Function &F) {
510         return &FAM.getResult<BlockFrequencyAnalysis>(
511             *const_cast<Function *>(&F));
512       },
513       &PSI);
514 }
515 
516 char ModuleSummaryIndexWrapperPass::ID = 0;
517 INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
518                       "Module Summary Analysis", false, true)
519 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
520 INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
521 INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
522                     "Module Summary Analysis", false, true)
523 
524 ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
525   return new ModuleSummaryIndexWrapperPass();
526 }
527 
528 ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
529     : ModulePass(ID) {
530   initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
531 }
532 
533 bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
534   auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
535   Index = buildModuleSummaryIndex(
536       M,
537       [this](const Function &F) {
538         return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
539                          *const_cast<Function *>(&F))
540                      .getBFI());
541       },
542       &PSI);
543   return false;
544 }
545 
546 bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
547   Index.reset();
548   return false;
549 }
550 
551 void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
552   AU.setPreservesAll();
553   AU.addRequired<BlockFrequencyInfoWrapperPass>();
554   AU.addRequired<ProfileSummaryInfoWrapperPass>();
555 }
556