xref: /llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (revision d9830eb79fdc42368d370abeab9a3b56c08e3963)
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/Analysis/BlockFrequencyInfo.h"
17 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
18 #include "llvm/Analysis/BranchProbabilityInfo.h"
19 #include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
20 #include "llvm/Analysis/LoopInfo.h"
21 #include "llvm/Analysis/ProfileSummaryInfo.h"
22 #include "llvm/IR/CallSite.h"
23 #include "llvm/IR/Dominators.h"
24 #include "llvm/IR/InstIterator.h"
25 #include "llvm/IR/IntrinsicInst.h"
26 #include "llvm/IR/ValueSymbolTable.h"
27 #include "llvm/Pass.h"
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "module-summary-analysis"
31 
32 // Walk through the operands of a given User via worklist iteration and populate
33 // the set of GlobalValue references encountered. Invoked either on an
34 // Instruction or a GlobalVariable (which walks its initializer).
35 static void findRefEdges(const User *CurUser, DenseSet<const Value *> &RefEdges,
36                          SmallPtrSet<const User *, 8> &Visited) {
37   SmallVector<const User *, 32> Worklist;
38   Worklist.push_back(CurUser);
39 
40   while (!Worklist.empty()) {
41     const User *U = Worklist.pop_back_val();
42 
43     if (!Visited.insert(U).second)
44       continue;
45 
46     ImmutableCallSite CS(U);
47 
48     for (const auto &OI : U->operands()) {
49       const User *Operand = dyn_cast<User>(OI);
50       if (!Operand)
51         continue;
52       if (isa<BlockAddress>(Operand))
53         continue;
54       if (isa<GlobalValue>(Operand)) {
55         // We have a reference to a global value. This should be added to
56         // the reference set unless it is a callee. Callees are handled
57         // specially by WriteFunction and are added to a separate list.
58         if (!(CS && CS.isCallee(&OI)))
59           RefEdges.insert(Operand);
60         continue;
61       }
62       Worklist.push_back(Operand);
63     }
64   }
65 }
66 
67 static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount,
68                                           ProfileSummaryInfo *PSI) {
69   if (!PSI)
70     return CalleeInfo::HotnessType::Unknown;
71   if (PSI->isHotCount(ProfileCount))
72     return CalleeInfo::HotnessType::Hot;
73   if (PSI->isColdCount(ProfileCount))
74     return CalleeInfo::HotnessType::Cold;
75   return CalleeInfo::HotnessType::None;
76 }
77 
78 static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
79                                    const Function &F, BlockFrequencyInfo *BFI,
80                                    ProfileSummaryInfo *PSI) {
81   // Summary not currently supported for anonymous functions, they must
82   // be renamed.
83   if (!F.hasName())
84     return;
85 
86   unsigned NumInsts = 0;
87   // Map from callee ValueId to profile count. Used to accumulate profile
88   // counts for all static calls to a given callee.
89   DenseMap<const Value *, CalleeInfo> CallGraphEdges;
90   DenseMap<GlobalValue::GUID, CalleeInfo> IndirectCallEdges;
91   DenseSet<const Value *> RefEdges;
92   ICallPromotionAnalysis ICallAnalysis;
93 
94   SmallPtrSet<const User *, 8> Visited;
95   for (const BasicBlock &BB : F)
96     for (const Instruction &I : BB) {
97       if (isa<DbgInfoIntrinsic>(I))
98         continue;
99       ++NumInsts;
100       findRefEdges(&I, RefEdges, Visited);
101       auto CS = ImmutableCallSite(&I);
102       if (!CS)
103         continue;
104       auto *CalledFunction = CS.getCalledFunction();
105       // Check if this is a direct call to a known function.
106       if (CalledFunction) {
107         // Skip nameless and intrinsics.
108         if (!CalledFunction->hasName() || CalledFunction->isIntrinsic())
109           continue;
110         auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
111         auto *CalleeId =
112             M.getValueSymbolTable().lookup(CalledFunction->getName());
113 
114         auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
115                                    : CalleeInfo::HotnessType::Unknown;
116         CallGraphEdges[CalleeId].updateHotness(Hotness);
117       } else {
118         const auto *CI = dyn_cast<CallInst>(&I);
119         // Skip inline assembly calls.
120         if (CI && CI->isInlineAsm())
121           continue;
122         // Skip direct calls.
123         if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
124           continue;
125 
126         uint32_t NumVals, NumCandidates;
127         uint64_t TotalCount;
128         auto CandidateProfileData =
129             ICallAnalysis.getPromotionCandidatesForInstruction(
130                 &I, NumVals, TotalCount, NumCandidates);
131         for (auto &Candidate : CandidateProfileData)
132           IndirectCallEdges[Candidate.Value].updateHotness(
133               getHotness(Candidate.Count, PSI));
134       }
135     }
136 
137   GlobalValueSummary::GVFlags Flags(F);
138   std::unique_ptr<FunctionSummary> FuncSummary =
139       llvm::make_unique<FunctionSummary>(Flags, NumInsts);
140   FuncSummary->addCallGraphEdges(CallGraphEdges);
141   FuncSummary->addCallGraphEdges(IndirectCallEdges);
142   FuncSummary->addRefEdges(RefEdges);
143   Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
144 }
145 
146 static void computeVariableSummary(ModuleSummaryIndex &Index,
147                                    const GlobalVariable &V) {
148   DenseSet<const Value *> RefEdges;
149   SmallPtrSet<const User *, 8> Visited;
150   findRefEdges(&V, RefEdges, Visited);
151   GlobalValueSummary::GVFlags Flags(V);
152   std::unique_ptr<GlobalVarSummary> GVarSummary =
153       llvm::make_unique<GlobalVarSummary>(Flags);
154   GVarSummary->addRefEdges(RefEdges);
155   Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
156 }
157 
158 ModuleSummaryIndex llvm::buildModuleSummaryIndex(
159     const Module &M,
160     std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
161     ProfileSummaryInfo *PSI) {
162   ModuleSummaryIndex Index;
163   // Check if the module can be promoted, otherwise just disable importing from
164   // it by not emitting any summary.
165   // FIXME: we could still import *into* it most of the time.
166   if (!moduleCanBeRenamedForThinLTO(M))
167     return Index;
168 
169   // Compute summaries for all functions defined in module, and save in the
170   // index.
171   for (auto &F : M) {
172     if (F.isDeclaration())
173       continue;
174 
175     BlockFrequencyInfo *BFI = nullptr;
176     std::unique_ptr<BlockFrequencyInfo> BFIPtr;
177     if (GetBFICallback)
178       BFI = GetBFICallback(F);
179     else if (F.getEntryCount().hasValue()) {
180       LoopInfo LI{DominatorTree(const_cast<Function &>(F))};
181       BranchProbabilityInfo BPI{F, LI};
182       BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
183       BFI = BFIPtr.get();
184     }
185 
186     computeFunctionSummary(Index, M, F, BFI, PSI);
187   }
188 
189   // Compute summaries for all variables defined in module, and save in the
190   // index.
191   for (const GlobalVariable &G : M.globals()) {
192     if (G.isDeclaration())
193       continue;
194     computeVariableSummary(Index, G);
195   }
196   return Index;
197 }
198 
199 char ModuleSummaryIndexAnalysis::PassID;
200 
201 ModuleSummaryIndex
202 ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
203   ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
204   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
205   return buildModuleSummaryIndex(
206       M,
207       [&FAM](const Function &F) {
208         return &FAM.getResult<BlockFrequencyAnalysis>(
209             *const_cast<Function *>(&F));
210       },
211       &PSI);
212 }
213 
214 char ModuleSummaryIndexWrapperPass::ID = 0;
215 INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
216                       "Module Summary Analysis", false, true)
217 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
218 INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
219                     "Module Summary Analysis", false, true)
220 
221 ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
222   return new ModuleSummaryIndexWrapperPass();
223 }
224 
225 ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
226     : ModulePass(ID) {
227   initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
228 }
229 
230 bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
231   auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(M);
232   Index = buildModuleSummaryIndex(
233       M,
234       [this](const Function &F) {
235         return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
236                          *const_cast<Function *>(&F))
237                      .getBFI());
238       },
239       &PSI);
240   return false;
241 }
242 
243 bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
244   Index.reset();
245   return false;
246 }
247 
248 void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
249   AU.setPreservesAll();
250   AU.addRequired<BlockFrequencyInfoWrapperPass>();
251   AU.addRequired<ProfileSummaryInfoWrapperPass>();
252 }
253 
254 bool llvm::moduleCanBeRenamedForThinLTO(const Module &M) {
255   // We cannot currently promote or rename anything used in inline assembly,
256   // which are not visible to the compiler. Detect a possible case by looking
257   // for a llvm.used local value, in conjunction with an inline assembly call
258   // in the module. Prevent importing of any modules containing these uses by
259   // suppressing generation of the index. This also prevents importing
260   // into this module, which is also necessary to avoid needing to rename
261   // in case of a name clash between a local in this module and an imported
262   // global.
263   // FIXME: If we find we need a finer-grained approach of preventing promotion
264   // and renaming of just the functions using inline assembly we will need to:
265   // - Add flag in the function summaries to identify those with inline asm.
266   // - Prevent importing of any functions with flag set.
267   // - Prevent importing of any global function with the same name as a
268   //   function in current module that has the flag set.
269   // - For any llvm.used value that is exported and promoted, add a private
270   //   alias to the original name in the current module (even if we don't
271   //   export the function using those values in inline asm, another function
272   //   with a reference could be exported).
273   SmallPtrSet<GlobalValue *, 8> Used;
274   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
275   bool LocalIsUsed =
276       any_of(Used, [](GlobalValue *V) { return V->hasLocalLinkage(); });
277   if (!LocalIsUsed)
278     return true;
279 
280   // Walk all the instructions in the module and find if one is inline ASM
281   auto HasInlineAsm = any_of(M, [](const Function &F) {
282     return any_of(instructions(F), [](const Instruction &I) {
283       const CallInst *CallI = dyn_cast<CallInst>(&I);
284       if (!CallI)
285         return false;
286       return CallI->isInlineAsm();
287     });
288   });
289   return !HasInlineAsm;
290 }
291