blob: 0c07e1d878f68150c5dcdbe5887259ee7f00882c [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,
Teresa Johnsond5033a42016-11-14 16:40:19 +000081 bool HasLocalsInUsed) {
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 Johnson2d5487c2016-04-11 13:58:45 +000093
Teresa Johnsond5033a42016-11-14 16:40:19 +000094 bool HasInlineAsmMaybeReferencingInternal = false;
Teresa Johnson2d5487c2016-04-11 13:58:45 +000095 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
Teresa Johnsond5033a42016-11-14 16:40:19 +0000108 // assembly, conservatively mark the function as possibly referencing
109 // a local value from inline assembly to ensure we don't export a
110 // reference (which would require renaming and promotion of the
111 // referenced value).
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000112 if (HasLocalsInUsed && CI && CI->isInlineAsm())
Teresa Johnsond5033a42016-11-14 16:40:19 +0000113 HasInlineAsmMaybeReferencingInternal = true;
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000114
Teresa Johnson897bab92016-10-08 16:11:42 +0000115 auto *CalledValue = CS.getCalledValue();
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000116 auto *CalledFunction = CS.getCalledFunction();
Teresa Johnson897bab92016-10-08 16:11:42 +0000117 // Check if this is an alias to a function. If so, get the
118 // called aliasee for the checks below.
119 if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
120 assert(!CalledFunction && "Expected null called function in callsite for alias");
121 CalledFunction = dyn_cast<Function>(GA->getBaseObject());
122 }
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000123 // Check if this is a direct call to a known function.
124 if (CalledFunction) {
Teresa Johnson02563cd2016-10-28 02:39:38 +0000125 // Skip intrinsics.
126 if (CalledFunction->isIntrinsic())
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000127 continue;
Teresa Johnson02563cd2016-10-28 02:39:38 +0000128 // We should have named any anonymous globals
129 assert(CalledFunction->hasName());
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000130 auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
Teresa Johnson897bab92016-10-08 16:11:42 +0000131 // Use the original CalledValue, in case it was an alias. We want
132 // to record the call edge to the alias in that case. Eventually
133 // an alias summary will be created to associate the alias and
134 // aliasee.
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000135 auto *CalleeId =
Teresa Johnson897bab92016-10-08 16:11:42 +0000136 M.getValueSymbolTable().lookup(CalledValue->getName());
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000137
138 auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
139 : CalleeInfo::HotnessType::Unknown;
140 CallGraphEdges[CalleeId].updateHotness(Hotness);
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000141 } else {
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000142 // Skip inline assembly calls.
143 if (CI && CI->isInlineAsm())
144 continue;
145 // Skip direct calls.
146 if (!CS.getCalledValue() || isa<Constant>(CS.getCalledValue()))
147 continue;
148
149 uint32_t NumVals, NumCandidates;
150 uint64_t TotalCount;
151 auto CandidateProfileData =
152 ICallAnalysis.getPromotionCandidatesForInstruction(
153 &I, NumVals, TotalCount, NumCandidates);
154 for (auto &Candidate : CandidateProfileData)
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000155 IndirectCallEdges[Candidate.Value].updateHotness(
156 getHotness(Candidate.Count, PSI));
Piotr Padlewski442d38c2016-08-30 00:46:26 +0000157 }
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000158 }
159
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000160 GlobalValueSummary::GVFlags Flags(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000161 std::unique_ptr<FunctionSummary> FuncSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000162 llvm::make_unique<FunctionSummary>(Flags, NumInsts);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000163 FuncSummary->addCallGraphEdges(CallGraphEdges);
Teresa Johnsoncd21a642016-07-17 14:47:01 +0000164 FuncSummary->addCallGraphEdges(IndirectCallEdges);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000165 FuncSummary->addRefEdges(RefEdges);
Teresa Johnsond5033a42016-11-14 16:40:19 +0000166 if (HasInlineAsmMaybeReferencingInternal)
167 FuncSummary->setHasInlineAsmMaybeReferencingInternal();
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000168 Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000169}
170
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000171static void computeVariableSummary(ModuleSummaryIndex &Index,
172 const GlobalVariable &V) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000173 DenseSet<const Value *> RefEdges;
174 SmallPtrSet<const User *, 8> Visited;
175 findRefEdges(&V, RefEdges, Visited);
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000176 GlobalValueSummary::GVFlags Flags(V);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000177 std::unique_ptr<GlobalVarSummary> GVarSummary =
Mehdi Aminic3ed48c2016-04-24 03:18:18 +0000178 llvm::make_unique<GlobalVarSummary>(Flags);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000179 GVarSummary->addRefEdges(RefEdges);
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000180 Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000181}
182
Teresa Johnson02563cd2016-10-28 02:39:38 +0000183static void computeAliasSummary(ModuleSummaryIndex &Index,
184 const GlobalAlias &A) {
185 GlobalValueSummary::GVFlags Flags(A);
186 std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags);
187 auto *Aliasee = A.getBaseObject();
188 auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
189 assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
190 AS->setAliasee(AliaseeSummary);
191 Index.addGlobalValueSummary(A.getName(), std::move(AS));
192}
193
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000194ModuleSummaryIndex llvm::buildModuleSummaryIndex(
195 const Module &M,
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000196 std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
197 ProfileSummaryInfo *PSI) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000198 ModuleSummaryIndex Index;
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000199
Teresa Johnsona0811452016-11-10 16:57:32 +0000200 // Identify the local values in the llvm.used and llvm.compiler.used sets,
201 // which should not be exported as they would then require renaming and
202 // promotion, but we may have opaque uses e.g. in inline asm. We collect them
203 // here because we use this information to mark functions containing inline
204 // assembly calls as not importable.
Mehdi Aminib6a11a72016-11-09 01:45:13 +0000205 SmallPtrSet<GlobalValue *, 8> LocalsUsed;
Teresa Johnsona0811452016-11-10 16:57:32 +0000206 SmallPtrSet<GlobalValue *, 8> Used;
207 // First collect those in the llvm.used set.
208 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
209 for (auto *V : Used) {
210 if (V->hasLocalLinkage())
211 LocalsUsed.insert(V);
212 }
213 Used.clear();
214 // Next collect those in the llvm.compiler.used set.
215 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ true);
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000216 for (auto *V : Used) {
217 if (V->hasLocalLinkage())
218 LocalsUsed.insert(V);
219 }
Teresa Johnsonb35cc692016-04-20 14:39:45 +0000220
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000221 // Compute summaries for all functions defined in module, and save in the
222 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000223 for (auto &F : M) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000224 if (F.isDeclaration())
225 continue;
226
227 BlockFrequencyInfo *BFI = nullptr;
228 std::unique_ptr<BlockFrequencyInfo> BFIPtr;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000229 if (GetBFICallback)
230 BFI = GetBFICallback(F);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000231 else if (F.getEntryCount().hasValue()) {
232 LoopInfo LI{DominatorTree(const_cast<Function &>(F))};
233 BranchProbabilityInfo BPI{F, LI};
234 BFIPtr = llvm::make_unique<BlockFrequencyInfo>(F, BPI, LI);
235 BFI = BFIPtr.get();
236 }
237
Teresa Johnsond5033a42016-11-14 16:40:19 +0000238 computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty());
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000239 }
240
241 // Compute summaries for all variables defined in module, and save in the
242 // index.
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000243 for (const GlobalVariable &G : M.globals()) {
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000244 if (G.isDeclaration())
245 continue;
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000246 computeVariableSummary(Index, G);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000247 }
Teresa Johnson02563cd2016-10-28 02:39:38 +0000248
249 // Compute summaries for all aliases defined in module, and save in the
250 // index.
251 for (const GlobalAlias &A : M.aliases())
252 computeAliasSummary(Index, A);
253
Teresa Johnsonbf28c8f2016-10-30 05:40:44 +0000254 for (auto *V : LocalsUsed) {
255 auto *Summary = Index.getGlobalValueSummary(*V);
256 assert(Summary && "Missing summary for global value");
257 Summary->setNoRename();
258 }
259
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000260 return Index;
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000261}
262
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000263char ModuleSummaryIndexAnalysis::PassID;
264
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000265ModuleSummaryIndex
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000266ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000267 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000268 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000269 return buildModuleSummaryIndex(
270 M,
271 [&FAM](const Function &F) {
272 return &FAM.getResult<BlockFrequencyAnalysis>(
273 *const_cast<Function *>(&F));
274 },
275 &PSI);
Teresa Johnsonf93b2462016-08-12 13:53:02 +0000276}
277
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000278char ModuleSummaryIndexWrapperPass::ID = 0;
279INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
280 "Module Summary Analysis", false, true)
281INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
282INITIALIZE_PASS_END(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
283 "Module Summary Analysis", false, true)
284
285ModulePass *llvm::createModuleSummaryIndexWrapperPass() {
286 return new ModuleSummaryIndexWrapperPass();
287}
288
289ModuleSummaryIndexWrapperPass::ModuleSummaryIndexWrapperPass()
290 : ModulePass(ID) {
291 initializeModuleSummaryIndexWrapperPassPass(*PassRegistry::getPassRegistry());
292}
293
294bool ModuleSummaryIndexWrapperPass::runOnModule(Module &M) {
Dehao Chen5461d8b2016-09-28 21:00:58 +0000295 auto &PSI = *getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000296 Index = buildModuleSummaryIndex(
297 M,
298 [this](const Function &F) {
299 return &(this->getAnalysis<BlockFrequencyInfoWrapperPass>(
300 *const_cast<Function *>(&F))
301 .getBFI());
302 },
303 &PSI);
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000304 return false;
305}
306
307bool ModuleSummaryIndexWrapperPass::doFinalization(Module &M) {
Chandler Carruthb7be5b62016-08-19 07:49:19 +0000308 Index.reset();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000309 return false;
310}
311
312void ModuleSummaryIndexWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
313 AU.setPreservesAll();
314 AU.addRequired<BlockFrequencyInfoWrapperPass>();
Piotr Padlewskid9830eb2016-09-26 20:37:32 +0000315 AU.addRequired<ProfileSummaryInfoWrapperPass>();
Teresa Johnson2d5487c2016-04-11 13:58:45 +0000316}