blob: 5a9d9a6604fec04347f3acb72f9379096b6e1509 [file] [log] [blame]
Teresa Johnson2d5487c2016-04-11 13:58:45 +00001//===- 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"
Teresa Johnsoncd21a642016-07-17 14:47:01 +000019#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
Teresa Johnson2d5487c2016-04-11 13:58:45 +000020#include "llvm/Analysis/LoopInfo.h"
Piotr Padlewskid9830eb2016-09-26 20:37:32 +000021#include "llvm/Analysis/ProfileSummaryInfo.h"
Teresa Johnson2d5487c2016-04-11 13:58:45 +000022#include "llvm/IR/CallSite.h"
23#include "llvm/IR/Dominators.h"
Teresa Johnsondf5ef872016-04-27 14:19:38 +000024#include "llvm/IR/InstIterator.h"
Teresa Johnson2d5487c2016-04-11 13:58:45 +000025#include "llvm/IR/IntrinsicInst.h"
26#include "llvm/IR/ValueSymbolTable.h"
27#include "llvm/Pass.h"
28using 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).
35static 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
Piotr Padlewskid9830eb2016-09-26 20:37:32 +000067static 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
Chandler Carruthb7be5b62016-08-19 07:49:19 +000078static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
Piotr Padlewskid9830eb2016-09-26 20:37:32 +000079 const Function &F, BlockFrequencyInfo *BFI,
80 ProfileSummaryInfo *PSI) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +000081 // 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;
Teresa Johnsoncd21a642016-07-17 14:47:01 +000090 DenseMap<GlobalValue::GUID, CalleeInfo> IndirectCallEdges;
Teresa Johnson2d5487c2016-04-11 13:58:45 +000091 DenseSet<const Value *> RefEdges;
Teresa Johnsoncd21a642016-07-17 14:47:01 +000092 ICallPromotionAnalysis ICallAnalysis;
Teresa Johnson2d5487c2016-04-11 13:58:45 +000093
94 SmallPtrSet<const User *, 8> Visited;
Benjamin Krameraa209152016-06-26 17:27:42 +000095 for (const BasicBlock &BB : F)
96 for (const Instruction &I : BB) {
Piotr Padlewski442d38c2016-08-30 00:46:26 +000097 if (isa<DbgInfoIntrinsic>(I))
98 continue;
99 ++NumInsts;
Benjamin Krameraa209152016-06-26 17:27:42 +0000100 findRefEdges(&I, RefEdges, Visited);
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000101 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());
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000113
114 auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
115 : CalleeInfo::HotnessType::Unknown;
116 CallGraphEdges[CalleeId].updateHotness(Hotness);
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000117 } 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)
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000132 IndirectCallEdges[Candidate.Value].updateHotness(
133 getHotness(Candidate.Count, PSI));
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000134 }
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000135 }
136
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000137 GlobalValueSummary::GVFlags Flags(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000138 std::unique_ptr<FunctionSummary> FuncSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000139 llvm::make_unique<FunctionSummary>(Flags, NumInsts);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000140 FuncSummary->addCallGraphEdges(CallGraphEdges);
Teresa Johnsoncd21a642016-07-17 14:47:01 +0000141 FuncSummary->addCallGraphEdges(IndirectCallEdges);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000142 FuncSummary->addRefEdges(RefEdges);
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000143 Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000144}
145
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000146static void computeVariableSummary(ModuleSummaryIndex &Index,
147 const GlobalVariable &V) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000148 DenseSet<const Value *> RefEdges;
149 SmallPtrSet<const User *, 8> Visited;
150 findRefEdges(&V, RefEdges, Visited);
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000151 GlobalValueSummary::GVFlags Flags(V);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000152 std::unique_ptr<GlobalVarSummary> GVarSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000153 llvm::make_unique<GlobalVarSummary>(Flags);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000154 GVarSummary->addRefEdges(RefEdges);
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000155 Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000156}
157
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000158ModuleSummaryIndex llvm::buildModuleSummaryIndex(
159 const Module &M,
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000160 std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
161 ProfileSummaryInfo *PSI) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000162 ModuleSummaryIndex Index;
Mehdi Amini3b132e32016-05-06 08:25:33 +0000163 // 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.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000166 if (!moduleCanBeRenamedForThinLTO(M))
167 return Index;
Teresa Johnsonb35cc692016-04-20 14:39:45 +0000168
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000169 // Compute summaries for all functions defined in module, and save in the
170 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000171 for (auto &F : M) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000172 if (F.isDeclaration())
173 continue;
174
175 BlockFrequencyInfo *BFI = nullptr;
176 std::unique_ptr<BlockFrequencyInfo> BFIPtr;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000177 if (GetBFICallback)
178 BFI = GetBFICallback(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000179 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
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000186 computeFunctionSummary(Index, M, F, BFI, PSI);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000187 }
188
189 // Compute summaries for all variables defined in module, and save in the
190 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000191 for (const GlobalVariable &G : M.globals()) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000192 if (G.isDeclaration())
193 continue;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000194 computeVariableSummary(Index, G);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000195 }
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000196 return Index;
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000197}
198
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000199char ModuleSummaryIndexAnalysis::PassID;
200
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000201ModuleSummaryIndex
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000202ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000203 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000204 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000205 return buildModuleSummaryIndex(
206 M,
207 [&FAM](const Function &F) {
208 return &FAM.getResult<BlockFrequencyAnalysis>(
209 *const_cast<Function *>(&F));
210 },
211 &PSI);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000212}
213
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000214char ModuleSummaryIndexWrapperPass::ID = 0;
215INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
216 "Module Summary Analysis", false, true)
217INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
218INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
219 "Module Summary Analysis", false, true)
220
221ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
222 return new ModuleSummaryIndexWrapperPass();
223}
224
225ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
226 : ModulePass(ID) {
227 initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
228}
229
230bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
Dehao Chen5461d8b2016-09-28 21:00:58 +0000231 auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000232 Index = buildModuleSummaryIndex(
233 M,
234 [this](const Function &F) {
235 return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
236 *const_cast<Function *>(&F))
237 .getBFI());
238 },
239 &PSI);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000240 return false;
241}
242
243bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000244 Index.reset();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000245 return false;
246}
247
248void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
249 AU.setPreservesAll();
250 AU.addRequired<BlockFrequencyInfoWrapperPass>();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000251 AU.addRequired<ProfileSummaryInfoWrapperPass>();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000252}
Mehdi Amini3b132e32016-05-06 08:25:33 +0000253
254bool 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 =
David Majnemer0a16c222016-08-11 21:15:00 +0000276 any_of(Used, [](GlobalValue *V) { return V->hasLocalLinkage(); });
Mehdi Amini3b132e32016-05-06 08:25:33 +0000277 if (!LocalIsUsed)
278 return true;
279
280 // Walk all the instructions in the module and find if one is inline ASM
David Majnemer0a16c222016-08-11 21:15:00 +0000281 auto HasInlineAsm = any_of(M, [](const Function &F) {
282 return any_of(instructions(F), [](const Instruction &I) {
Mehdi Amini3b132e32016-05-06 08:25:33 +0000283 const CallInst *CallI = dyn_cast<CallInst>(&I);
284 if (!CallI)
285 return false;
286 return CallI->isInlineAsm();
287 });
288 });
289 return !HasInlineAsm;
290}