blob: 09d18eb3da13417a08507c8e6147b6fb3099041a [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,
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +000080 ProfileSummaryInfo *PSI,
81 SmallPtrSetImpl<GlobalValue *> &LocalsUsed) {
Teresa Johnson02563cd2016-10-28 02:39:38 +000082 // Summary not currently supported for anonymous functions, they should
83 // have been named.
84 assert(F.hasName());
Teresa Johnson2d5487c2016-04-11 13:58:45 +000085
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 Johnsonbf28c8f2016-10-30 05:40:44 +000093 bool HasLocalsInUsed = !LocalsUsed.empty();
Teresa Johnson2d5487c2016-04-11 13:58:45 +000094
95 SmallPtrSet<const User *, 8> Visited;
Benjamin Krameraa209152016-06-26 17:27:42 +000096 for (const BasicBlock &BB : F)
97 for (const Instruction &I : BB) {
Piotr Padlewski442d38c2016-08-30 00:46:26 +000098 if (isa<DbgInfoIntrinsic>(I))
99 continue;
100 ++NumInsts;
Benjamin Krameraa209152016-06-26 17:27:42 +0000101 findRefEdges(&I, RefEdges, Visited);
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000102 auto CS = ImmutableCallSite(&I);
103 if (!CS)
104 continue;
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000105
106 const auto *CI = dyn_cast<CallInst>(&I);
107 // Since we don't know exactly which local values are referenced in inline
108 // assembly, conservatively reference all of them from this function, to
109 // ensure we don't export a reference (which would require renaming and
110 // promotion).
111 if (HasLocalsInUsed && CI && CI->isInlineAsm())
112 RefEdges.insert(LocalsUsed.begin(), LocalsUsed.end());
113
Teresa Johnson897bab92016-10-08 16:11:42 +0000114 auto *CalledValue = CS.getCalledValue();
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000115 auto *CalledFunction = CS.getCalledFunction();
Teresa Johnson897bab92016-10-08 16:11:42 +0000116 // Check if this is an alias to a function. If so, get the
117 // called aliasee for the checks below.
118 if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
119 assert(!CalledFunction && "Expected null called function in callsite for alias");
120 CalledFunction = dyn_cast<Function>(GA->getBaseObject());
121 }
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000122 // Check if this is a direct call to a known function.
123 if (CalledFunction) {
Teresa Johnson02563cd2016-10-28 02:39:38 +0000124 // Skip intrinsics.
125 if (CalledFunction->isIntrinsic())
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000126 continue;
Teresa Johnson02563cd2016-10-28 02:39:38 +0000127 // We should have named any anonymous globals
128 assert(CalledFunction->hasName());
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000129 auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
Teresa Johnson897bab92016-10-08 16:11:42 +0000130 // Use the original CalledValue, in case it was an alias. We want
131 // to record the call edge to the alias in that case. Eventually
132 // an alias summary will be created to associate the alias and
133 // aliasee.
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000134 auto *CalleeId =
Teresa Johnson897bab92016-10-08 16:11:42 +0000135 M.getValueSymbolTable().lookup(CalledValue->getName());
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000136
137 auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
138 : CalleeInfo::HotnessType::Unknown;
139 CallGraphEdges[CalleeId].updateHotness(Hotness);
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000140 } else {
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000141 // Skip inline assembly calls.
142 if (CI && CI->isInlineAsm())
143 continue;
144 // Skip direct calls.
145 if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
146 continue;
147
148 uint32_t NumVals, NumCandidates;
149 uint64_t TotalCount;
150 auto CandidateProfileData =
151 ICallAnalysis.getPromotionCandidatesForInstruction(
152 &I, NumVals, TotalCount, NumCandidates);
153 for (auto &Candidate : CandidateProfileData)
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000154 IndirectCallEdges[Candidate.Value].updateHotness(
155 getHotness(Candidate.Count, PSI));
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000156 }
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000157 }
158
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000159 GlobalValueSummary::GVFlags Flags(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000160 std::unique_ptr<FunctionSummary> FuncSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000161 llvm::make_unique<FunctionSummary>(Flags, NumInsts);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000162 FuncSummary->addCallGraphEdges(CallGraphEdges);
Teresa Johnsoncd21a642016-07-17 14:47:01 +0000163 FuncSummary->addCallGraphEdges(IndirectCallEdges);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000164 FuncSummary->addRefEdges(RefEdges);
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000165 Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000166}
167
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000168static void computeVariableSummary(ModuleSummaryIndex &Index,
169 const GlobalVariable &V) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000170 DenseSet<const Value *> RefEdges;
171 SmallPtrSet<const User *, 8> Visited;
172 findRefEdges(&V, RefEdges, Visited);
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000173 GlobalValueSummary::GVFlags Flags(V);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000174 std::unique_ptr<GlobalVarSummary> GVarSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000175 llvm::make_unique<GlobalVarSummary>(Flags);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000176 GVarSummary->addRefEdges(RefEdges);
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000177 Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000178}
179
Teresa Johnson02563cd2016-10-28 02:39:38 +0000180static void computeAliasSummary(ModuleSummaryIndex &Index,
181 const GlobalAlias &A) {
182 GlobalValueSummary::GVFlags Flags(A);
183 std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags);
184 auto *Aliasee = A.getBaseObject();
185 auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
186 assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
187 AS->setAliasee(AliaseeSummary);
188 Index.addGlobalValueSummary(A.getName(), std::move(AS));
189}
190
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000191ModuleSummaryIndex llvm::buildModuleSummaryIndex(
192 const Module &M,
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000193 std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
194 ProfileSummaryInfo *PSI) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000195 ModuleSummaryIndex Index;
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000196
Mehdi Aminib6a11a72016-11-09 01:45:13 +0000197 // Identify the local values in the llvm.used set, which should not be
198 // exported as they would then require renaming and promotion, but we
199 // may have opaque uses e.g. in inline asm.
Teresa Johnson6955fee2016-11-08 21:53:35 +0000200 SmallPtrSet<GlobalValue *, 8> Used;
Teresa Johnson6955fee2016-11-08 21:53:35 +0000201 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
Mehdi Aminib6a11a72016-11-09 01:45:13 +0000202 SmallPtrSet<GlobalValue *, 8> LocalsUsed;
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000203 for (auto *V : Used) {
204 if (V->hasLocalLinkage())
205 LocalsUsed.insert(V);
206 }
Teresa Johnsonb35cc692016-04-20 14:39:45 +0000207
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000208 // Compute summaries for all functions defined in module, and save in the
209 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000210 for (auto &F : M) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000211 if (F.isDeclaration())
212 continue;
213
214 BlockFrequencyInfo *BFI = nullptr;
215 std::unique_ptr<BlockFrequencyInfo> BFIPtr;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000216 if (GetBFICallback)
217 BFI = GetBFICallback(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000218 else if (F.getEntryCount().hasValue()) {
219 LoopInfo LI{DominatorTree(const_cast<Function &>(F))};
220 BranchProbabilityInfo BPI{F, LI};
221 BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
222 BFI = BFIPtr.get();
223 }
224
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000225 computeFunctionSummary(Index, M, F, BFI, PSI, LocalsUsed);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000226 }
227
228 // Compute summaries for all variables defined in module, and save in the
229 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000230 for (const GlobalVariable &G : M.globals()) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000231 if (G.isDeclaration())
232 continue;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000233 computeVariableSummary(Index, G);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000234 }
Teresa Johnson02563cd2016-10-28 02:39:38 +0000235
236 // Compute summaries for all aliases defined in module, and save in the
237 // index.
238 for (const GlobalAlias &A : M.aliases())
239 computeAliasSummary(Index, A);
240
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000241 for (auto *V : LocalsUsed) {
242 auto *Summary = Index.getGlobalValueSummary(*V);
243 assert(Summary && "Missing summary for global value");
244 Summary->setNoRename();
245 }
246
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000247 return Index;
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000248}
249
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000250char ModuleSummaryIndexAnalysis::PassID;
251
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000252ModuleSummaryIndex
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000253ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000254 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000255 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000256 return buildModuleSummaryIndex(
257 M,
258 [&FAM](const Function &F) {
259 return &FAM.getResult<BlockFrequencyAnalysis>(
260 *const_cast<Function *>(&F));
261 },
262 &PSI);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000263}
264
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000265char ModuleSummaryIndexWrapperPass::ID = 0;
266INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
267 "Module Summary Analysis", false, true)
268INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
269INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
270 "Module Summary Analysis", false, true)
271
272ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
273 return new ModuleSummaryIndexWrapperPass();
274}
275
276ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
277 : ModulePass(ID) {
278 initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
279}
280
281bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
Dehao Chen5461d8b2016-09-28 21:00:58 +0000282 auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000283 Index = buildModuleSummaryIndex(
284 M,
285 [this](const Function &F) {
286 return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
287 *const_cast<Function *>(&F))
288 .getBFI());
289 },
290 &PSI);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000291 return false;
292}
293
294bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000295 Index.reset();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000296 return false;
297}
298
299void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
300 AU.setPreservesAll();
301 AU.addRequired<BlockFrequencyInfoWrapperPass>();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000302 AU.addRequired<ProfileSummaryInfoWrapperPass>();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000303}