xref: /llvm-project/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (revision 897bab9b35dd80e10e8a9c34dcac072c173fcffb)
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 *CalledValue = CS.getCalledValue();
105       auto *CalledFunction = CS.getCalledFunction();
106       // Check if this is an alias to a function. If so, get the
107       // called aliasee for the checks below.
108       if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
109         assert(!CalledFunction && "Expected null called function in callsite for alias");
110         CalledFunction = dyn_cast<Function>(GA->getBaseObject());
111       }
112       // Check if this is a direct call to a known function.
113       if (CalledFunction) {
114         // Skip nameless and intrinsics.
115         if (!CalledFunction->hasName() || CalledFunction->isIntrinsic())
116           continue;
117         auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
118         // Use the original CalledValue, in case it was an alias. We want
119         // to record the call edge to the alias in that case. Eventually
120         // an alias summary will be created to associate the alias and
121         // aliasee.
122         auto *CalleeId =
123             M.getValueSymbolTable().lookup(CalledValue->getName());
124 
125         auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
126                                    : CalleeInfo::HotnessType::Unknown;
127         CallGraphEdges[CalleeId].updateHotness(Hotness);
128       } else {
129         const auto *CI = dyn_cast<CallInst>(&I);
130         // Skip inline assembly calls.
131         if (CI && CI->isInlineAsm())
132           continue;
133         // Skip direct calls.
134         if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
135           continue;
136 
137         uint32_t NumVals, NumCandidates;
138         uint64_t TotalCount;
139         auto CandidateProfileData =
140             ICallAnalysis.getPromotionCandidatesForInstruction(
141                 &I, NumVals, TotalCount, NumCandidates);
142         for (auto &Candidate : CandidateProfileData)
143           IndirectCallEdges[Candidate.Value].updateHotness(
144               getHotness(Candidate.Count, PSI));
145       }
146     }
147 
148   GlobalValueSummary::GVFlags Flags(F);
149   std::unique_ptr<FunctionSummary> FuncSummary =
150       llvm::make_unique<FunctionSummary>(Flags, NumInsts);
151   FuncSummary->addCallGraphEdges(CallGraphEdges);
152   FuncSummary->addCallGraphEdges(IndirectCallEdges);
153   FuncSummary->addRefEdges(RefEdges);
154   Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
155 }
156 
157 static void computeVariableSummary(ModuleSummaryIndex &Index,
158                                    const GlobalVariable &V) {
159   DenseSet<const Value *> RefEdges;
160   SmallPtrSet<const User *, 8> Visited;
161   findRefEdges(&V, RefEdges, Visited);
162   GlobalValueSummary::GVFlags Flags(V);
163   std::unique_ptr<GlobalVarSummary> GVarSummary =
164       llvm::make_unique<GlobalVarSummary>(Flags);
165   GVarSummary->addRefEdges(RefEdges);
166   Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
167 }
168 
169 ModuleSummaryIndex llvm::buildModuleSummaryIndex(
170     const Module &M,
171     std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
172     ProfileSummaryInfo *PSI) {
173   ModuleSummaryIndex Index;
174   // Check if the module can be promoted, otherwise just disable importing from
175   // it by not emitting any summary.
176   // FIXME: we could still import *into* it most of the time.
177   if (!moduleCanBeRenamedForThinLTO(M))
178     return Index;
179 
180   // Compute summaries for all functions defined in module, and save in the
181   // index.
182   for (auto &F : M) {
183     if (F.isDeclaration())
184       continue;
185 
186     BlockFrequencyInfo *BFI = nullptr;
187     std::unique_ptr<BlockFrequencyInfo> BFIPtr;
188     if (GetBFICallback)
189       BFI = GetBFICallback(F);
190     else if (F.getEntryCount().hasValue()) {
191       LoopInfo LI{DominatorTree(const_cast<Function &>(F))};
192       BranchProbabilityInfo BPI{F, LI};
193       BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
194       BFI = BFIPtr.get();
195     }
196 
197     computeFunctionSummary(Index, M, F, BFI, PSI);
198   }
199 
200   // Compute summaries for all variables defined in module, and save in the
201   // index.
202   for (const GlobalVariable &G : M.globals()) {
203     if (G.isDeclaration())
204       continue;
205     computeVariableSummary(Index, G);
206   }
207   return Index;
208 }
209 
210 char ModuleSummaryIndexAnalysis::PassID;
211 
212 ModuleSummaryIndex
213 ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
214   ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
215   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
216   return buildModuleSummaryIndex(
217       M,
218       [&FAM](const Function &F) {
219         return &FAM.getResult<BlockFrequencyAnalysis>(
220             *const_cast<Function *>(&F));
221       },
222       &PSI);
223 }
224 
225 char ModuleSummaryIndexWrapperPass::ID = 0;
226 INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
227                       "Module Summary Analysis", false, true)
228 INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
229 INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
230                     "Module Summary Analysis", false, true)
231 
232 ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
233   return new ModuleSummaryIndexWrapperPass();
234 }
235 
236 ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
237     : ModulePass(ID) {
238   initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
239 }
240 
241 bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
242   auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
243   Index = buildModuleSummaryIndex(
244       M,
245       [this](const Function &F) {
246         return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
247                          *const_cast<Function *>(&F))
248                      .getBFI());
249       },
250       &PSI);
251   return false;
252 }
253 
254 bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
255   Index.reset();
256   return false;
257 }
258 
259 void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
260   AU.setPreservesAll();
261   AU.addRequired<BlockFrequencyInfoWrapperPass>();
262   AU.addRequired<ProfileSummaryInfoWrapperPass>();
263 }
264 
265 bool llvm::moduleCanBeRenamedForThinLTO(const Module &M) {
266   // We cannot currently promote or rename anything used in inline assembly,
267   // which are not visible to the compiler. Detect a possible case by looking
268   // for a llvm.used local value, in conjunction with an inline assembly call
269   // in the module. Prevent importing of any modules containing these uses by
270   // suppressing generation of the index. This also prevents importing
271   // into this module, which is also necessary to avoid needing to rename
272   // in case of a name clash between a local in this module and an imported
273   // global.
274   // FIXME: If we find we need a finer-grained approach of preventing promotion
275   // and renaming of just the functions using inline assembly we will need to:
276   // - Add flag in the function summaries to identify those with inline asm.
277   // - Prevent importing of any functions with flag set.
278   // - Prevent importing of any global function with the same name as a
279   //   function in current module that has the flag set.
280   // - For any llvm.used value that is exported and promoted, add a private
281   //   alias to the original name in the current module (even if we don't
282   //   export the function using those values in inline asm, another function
283   //   with a reference could be exported).
284   SmallPtrSet<GlobalValue *, 8> Used;
285   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
286   bool LocalIsUsed =
287       any_of(Used, [](GlobalValue *V) { return V->hasLocalLinkage(); });
288   if (!LocalIsUsed)
289     return true;
290 
291   // Walk all the instructions in the module and find if one is inline ASM
292   auto HasInlineAsm = any_of(M, [](const Function &F) {
293     return any_of(instructions(F), [](const Instruction &I) {
294       const CallInst *CallI = dyn_cast<CallInst>(&I);
295       if (!CallI)
296         return false;
297       return CallI->isInlineAsm();
298     });
299   });
300   return !HasInlineAsm;
301 }
302