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