blob: ea805efc66b79f9538cc5290c11ee90382dded6c [file] [log] [blame]
Owen Anderson2f82e272009-06-14 08:26:32 +00001//===- PartialInlining.cpp - Inline parts of functions --------------------===//
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 performs partial inlining, typically by inlining an if statement
11// that surrounds the body of the function.
12//
13//===----------------------------------------------------------------------===//
14
Easwaran Raman1832bf62016-06-27 16:50:18 +000015#include "llvm/Transforms/IPO/PartialInlining.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/Statistic.h"
Sean Silvaf8015752016-08-02 02:15:45 +000017#include "llvm/Analysis/BlockFrequencyInfo.h"
18#include "llvm/Analysis/BranchProbabilityInfo.h"
Xinliang David Li66bdfca2017-05-12 23:41:43 +000019#include "llvm/Analysis/CodeMetrics.h"
Xinliang David Li61338462017-05-02 02:44:14 +000020#include "llvm/Analysis/InlineCost.h"
Sean Silvaf8015752016-08-02 02:15:45 +000021#include "llvm/Analysis/LoopInfo.h"
Xinliang David Li15744ad2017-04-23 21:40:58 +000022#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
Xinliang David Li61338462017-05-02 02:44:14 +000023#include "llvm/Analysis/ProfileSummaryInfo.h"
24#include "llvm/Analysis/TargetLibraryInfo.h"
25#include "llvm/Analysis/TargetTransformInfo.h"
Chandler Carruth1305dc32014-03-04 11:45:46 +000026#include "llvm/IR/CFG.h"
Xinliang David Li15744ad2017-04-23 21:40:58 +000027#include "llvm/IR/DiagnosticInfo.h"
Chandler Carruth5ad5f152014-01-13 09:26:24 +000028#include "llvm/IR/Dominators.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000029#include "llvm/IR/Instructions.h"
30#include "llvm/IR/Module.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000031#include "llvm/Pass.h"
Easwaran Raman1832bf62016-06-27 16:50:18 +000032#include "llvm/Transforms/IPO.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000033#include "llvm/Transforms/Utils/Cloning.h"
Chandler Carruth0fde0012012-05-04 10:18:49 +000034#include "llvm/Transforms/Utils/CodeExtractor.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000035using namespace llvm;
36
Xinliang David Li15744ad2017-04-23 21:40:58 +000037#define DEBUG_TYPE "partial-inlining"
Chandler Carruth964daaa2014-04-22 02:55:47 +000038
Xinliang David Li61338462017-05-02 02:44:14 +000039STATISTIC(NumPartialInlined,
40 "Number of callsites functions partially inlined into.");
Owen Andersonbd6a2132009-06-15 20:50:26 +000041
Xinliang David Lidb8d09b2017-04-23 23:39:04 +000042// Command line option to disable partial-inlining. The default is false:
43static cl::opt<bool>
44 DisablePartialInlining("disable-partial-inlining", cl::init(false),
45 cl::Hidden, cl::desc("Disable partial ininling"));
Xinliang David Li66bdfca2017-05-12 23:41:43 +000046// This is an option used by testing:
47static cl::opt<bool> SkipCostAnalysis("skip-partial-inlining-cost-analysis",
48 cl::init(false), cl::ZeroOrMore,
49 cl::ReallyHidden,
50 cl::desc("Skip Cost Analysis"));
Xinliang David Lidb8d09b2017-04-23 23:39:04 +000051
Xinliang David Lid21601a2017-04-27 16:34:00 +000052static cl::opt<unsigned> MaxNumInlineBlocks(
53 "max-num-inline-blocks", cl::init(5), cl::Hidden,
54 cl::desc("Max Number of Blocks To be Partially Inlined"));
55
Xinliang David Lidb8d09b2017-04-23 23:39:04 +000056// Command line option to set the maximum number of partial inlining allowed
57// for the module. The default value of -1 means no limit.
58static cl::opt<int> MaxNumPartialInlining(
59 "max-partial-inlining", cl::init(-1), cl::Hidden, cl::ZeroOrMore,
60 cl::desc("Max number of partial inlining. The default is unlimited"));
61
Xinliang David Li66bdfca2017-05-12 23:41:43 +000062// Used only when PGO or user annotated branch data is absent. It is
63// the least value that is used to weigh the outline region. If BFI
64// produces larger value, the BFI value will be used.
65static cl::opt<int>
66 OutlineRegionFreqPercent("outline-region-freq-percent", cl::init(75),
67 cl::Hidden, cl::ZeroOrMore,
68 cl::desc("Relative frequency of outline region to "
69 "the entry block"));
70
Xinliang David Li0b7d8582017-06-02 22:08:04 +000071static cl::opt<unsigned> ExtraOutliningPenalty(
72 "partial-inlining-extra-penalty", cl::init(0), cl::Hidden,
73 cl::desc("A debug option to add additional penalty to the computed one."));
74
Owen Anderson2f82e272009-06-14 08:26:32 +000075namespace {
Xinliang David Lid21601a2017-04-27 16:34:00 +000076
77struct FunctionOutliningInfo {
78 FunctionOutliningInfo()
79 : Entries(), ReturnBlock(nullptr), NonReturnBlock(nullptr),
80 ReturnBlockPreds() {}
81 // Returns the number of blocks to be inlined including all blocks
82 // in Entries and one return block.
83 unsigned GetNumInlinedBlocks() const { return Entries.size() + 1; }
84
85 // A set of blocks including the function entry that guard
86 // the region to be outlined.
87 SmallVector<BasicBlock *, 4> Entries;
88 // The return block that is not included in the outlined region.
89 BasicBlock *ReturnBlock;
Xinliang David Li0b7d8582017-06-02 22:08:04 +000090 // The dominating block of the region to be outlined.
Xinliang David Lid21601a2017-04-27 16:34:00 +000091 BasicBlock *NonReturnBlock;
92 // The set of blocks in Entries that that are predecessors to ReturnBlock
93 SmallVector<BasicBlock *, 4> ReturnBlockPreds;
94};
95
Sean Silvafe5abd52016-07-25 05:00:00 +000096struct PartialInlinerImpl {
Xinliang David Li61338462017-05-02 02:44:14 +000097 PartialInlinerImpl(
98 std::function<AssumptionCache &(Function &)> *GetAC,
99 std::function<TargetTransformInfo &(Function &)> *GTTI,
100 Optional<function_ref<BlockFrequencyInfo &(Function &)>> GBFI,
101 ProfileSummaryInfo *ProfSI)
102 : GetAssumptionCache(GetAC), GetTTI(GTTI), GetBFI(GBFI), PSI(ProfSI) {}
Sean Silvafe5abd52016-07-25 05:00:00 +0000103 bool run(Module &M);
104 Function *unswitchFunction(Function *F);
105
106private:
Xinliang David Lidb8d09b2017-04-23 23:39:04 +0000107 int NumPartialInlining = 0;
Xinliang David Li61338462017-05-02 02:44:14 +0000108 std::function<AssumptionCache &(Function &)> *GetAssumptionCache;
109 std::function<TargetTransformInfo &(Function &)> *GetTTI;
110 Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI;
111 ProfileSummaryInfo *PSI;
Xinliang David Lidb8d09b2017-04-23 23:39:04 +0000112
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000113 // Return the frequency of the OutlininingBB relative to F's entry point.
114 // The result is no larger than 1 and is represented using BP.
115 // (Note that the outlined region's 'head' block can only have incoming
116 // edges from the guarding entry blocks).
117 BranchProbability getOutliningCallBBRelativeFreq(Function *F,
118 FunctionOutliningInfo *OI,
119 Function *DuplicateFunction,
120 BlockFrequencyInfo *BFI,
121 BasicBlock *OutliningCallBB);
122
123 // Return true if the callee of CS should be partially inlined with
124 // profit.
125 bool shouldPartialInline(CallSite CS, Function *F, FunctionOutliningInfo *OI,
126 BlockFrequencyInfo *CalleeBFI,
127 BasicBlock *OutliningCallBB,
128 int OutliningCallOverhead,
129 OptimizationRemarkEmitter &ORE);
130
131 // Try to inline DuplicateFunction (cloned from F with call to
132 // the OutlinedFunction into its callers. Return true
133 // if there is any successful inlining.
134 bool tryPartialInline(Function *DuplicateFunction,
135 Function *F, /*orignal function */
136 FunctionOutliningInfo *OI, Function *OutlinedFunction,
137 BlockFrequencyInfo *CalleeBFI);
138
139 // Compute the mapping from use site of DuplicationFunction to the enclosing
140 // BB's profile count.
141 void computeCallsiteToProfCountMap(Function *DuplicateFunction,
142 DenseMap<User *, uint64_t> &SiteCountMap);
143
Xinliang David Lidb8d09b2017-04-23 23:39:04 +0000144 bool IsLimitReached() {
145 return (MaxNumPartialInlining != -1 &&
146 NumPartialInlining >= MaxNumPartialInlining);
147 }
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000148
149 CallSite getCallSite(User *U) {
150 CallSite CS;
151 if (CallInst *CI = dyn_cast<CallInst>(U))
152 CS = CallSite(CI);
153 else if (InvokeInst *II = dyn_cast<InvokeInst>(U))
154 CS = CallSite(II);
155 else
156 llvm_unreachable("All uses must be calls");
157 return CS;
158 }
159
160 CallSite getOneCallSiteTo(Function *F) {
161 User *User = *F->user_begin();
162 return getCallSite(User);
163 }
164
165 std::tuple<DebugLoc, BasicBlock *> getOneDebugLoc(Function *F) {
166 CallSite CS = getOneCallSiteTo(F);
167 DebugLoc DLoc = CS.getInstruction()->getDebugLoc();
168 BasicBlock *Block = CS.getParent();
169 return std::make_tuple(DLoc, Block);
170 }
171
172 // Returns the costs associated with function outlining:
173 // - The first value is the non-weighted runtime cost for making the call
174 // to the outlined function 'OutlinedFunction', including the addtional
175 // setup cost in the outlined function itself;
176 // - The second value is the estimated size of the new call sequence in
177 // basic block 'OutliningCallBB';
178 // - The third value is the estimated size of the original code from
179 // function 'F' that is extracted into the outlined function.
180 std::tuple<int, int, int>
181 computeOutliningCosts(Function *F, const FunctionOutliningInfo *OutliningInfo,
182 Function *OutlinedFunction,
183 BasicBlock *OutliningCallBB);
184 // Compute the 'InlineCost' of block BB. InlineCost is a proxy used to
185 // approximate both the size and runtime cost (Note that in the current
186 // inline cost analysis, there is no clear distinction there either).
187 int computeBBInlineCost(BasicBlock *BB);
188
189 std::unique_ptr<FunctionOutliningInfo> computeOutliningInfo(Function *F);
190
Sean Silvafe5abd52016-07-25 05:00:00 +0000191};
Xinliang David Lid21601a2017-04-27 16:34:00 +0000192
Easwaran Raman1832bf62016-06-27 16:50:18 +0000193struct PartialInlinerLegacyPass : public ModulePass {
194 static char ID; // Pass identification, replacement for typeid
195 PartialInlinerLegacyPass() : ModulePass(ID) {
196 initializePartialInlinerLegacyPassPass(*PassRegistry::getPassRegistry());
197 }
Craig Topper3e4c6972014-03-05 09:10:37 +0000198
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000199 void getAnalysisUsage(AnalysisUsage &AU) const override {
200 AU.addRequired<AssumptionCacheTracker>();
Xinliang David Li61338462017-05-02 02:44:14 +0000201 AU.addRequired<ProfileSummaryInfoWrapperPass>();
202 AU.addRequired<TargetTransformInfoWrapperPass>();
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000203 }
Easwaran Raman1832bf62016-06-27 16:50:18 +0000204 bool runOnModule(Module &M) override {
205 if (skipModule(M))
206 return false;
Craig Topper3e4c6972014-03-05 09:10:37 +0000207
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000208 AssumptionCacheTracker *ACT = &getAnalysis<AssumptionCacheTracker>();
Xinliang David Li61338462017-05-02 02:44:14 +0000209 TargetTransformInfoWrapperPass *TTIWP =
210 &getAnalysis<TargetTransformInfoWrapperPass>();
211 ProfileSummaryInfo *PSI =
212 getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
213
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000214 std::function<AssumptionCache &(Function &)> GetAssumptionCache =
215 [&ACT](Function &F) -> AssumptionCache & {
216 return ACT->getAssumptionCache(F);
217 };
Xinliang David Li61338462017-05-02 02:44:14 +0000218
219 std::function<TargetTransformInfo &(Function &)> GetTTI =
220 [&TTIWP](Function &F) -> TargetTransformInfo & {
221 return TTIWP->getTTI(F);
222 };
223
224 return PartialInlinerImpl(&GetAssumptionCache, &GetTTI, None, PSI).run(M);
Sean Silvafe5abd52016-07-25 05:00:00 +0000225 }
Sean Silva519323d2016-07-25 05:57:59 +0000226};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000227}
Owen Anderson2f82e272009-06-14 08:26:32 +0000228
Xinliang David Lid21601a2017-04-27 16:34:00 +0000229std::unique_ptr<FunctionOutliningInfo>
230PartialInlinerImpl::computeOutliningInfo(Function *F) {
Sean Silva519323d2016-07-25 05:57:59 +0000231 BasicBlock *EntryBlock = &F->front();
232 BranchInst *BR = dyn_cast<BranchInst>(EntryBlock->getTerminator());
Owen Andersonf0081db2009-09-08 19:53:15 +0000233 if (!BR || BR->isUnconditional())
Xinliang David Lid21601a2017-04-27 16:34:00 +0000234 return std::unique_ptr<FunctionOutliningInfo>();
Sean Silvafe5abd52016-07-25 05:00:00 +0000235
Xinliang David Lid21601a2017-04-27 16:34:00 +0000236 // Returns true if Succ is BB's successor
237 auto IsSuccessor = [](BasicBlock *Succ, BasicBlock *BB) {
238 return is_contained(successors(BB), Succ);
239 };
240
241 auto SuccSize = [](BasicBlock *BB) {
242 return std::distance(succ_begin(BB), succ_end(BB));
243 };
244
245 auto IsReturnBlock = [](BasicBlock *BB) {
246 TerminatorInst *TI = BB->getTerminator();
247 return isa<ReturnInst>(TI);
248 };
249
Davide Italianoaa42a102017-05-08 20:44:01 +0000250 auto GetReturnBlock = [&](BasicBlock *Succ1, BasicBlock *Succ2) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000251 if (IsReturnBlock(Succ1))
252 return std::make_tuple(Succ1, Succ2);
253 if (IsReturnBlock(Succ2))
254 return std::make_tuple(Succ2, Succ1);
255
256 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
257 };
258
259 // Detect a triangular shape:
Davide Italianoaa42a102017-05-08 20:44:01 +0000260 auto GetCommonSucc = [&](BasicBlock *Succ1, BasicBlock *Succ2) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000261 if (IsSuccessor(Succ1, Succ2))
262 return std::make_tuple(Succ1, Succ2);
263 if (IsSuccessor(Succ2, Succ1))
264 return std::make_tuple(Succ2, Succ1);
265
266 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
267 };
268
269 std::unique_ptr<FunctionOutliningInfo> OutliningInfo =
270 llvm::make_unique<FunctionOutliningInfo>();
271
272 BasicBlock *CurrEntry = EntryBlock;
273 bool CandidateFound = false;
274 do {
275 // The number of blocks to be inlined has already reached
276 // the limit. When MaxNumInlineBlocks is set to 0 or 1, this
277 // disables partial inlining for the function.
278 if (OutliningInfo->GetNumInlinedBlocks() >= MaxNumInlineBlocks)
279 break;
280
281 if (SuccSize(CurrEntry) != 2)
282 break;
283
284 BasicBlock *Succ1 = *succ_begin(CurrEntry);
285 BasicBlock *Succ2 = *(succ_begin(CurrEntry) + 1);
286
287 BasicBlock *ReturnBlock, *NonReturnBlock;
288 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
289
290 if (ReturnBlock) {
291 OutliningInfo->Entries.push_back(CurrEntry);
292 OutliningInfo->ReturnBlock = ReturnBlock;
293 OutliningInfo->NonReturnBlock = NonReturnBlock;
294 CandidateFound = true;
295 break;
296 }
297
298 BasicBlock *CommSucc;
299 BasicBlock *OtherSucc;
300 std::tie(CommSucc, OtherSucc) = GetCommonSucc(Succ1, Succ2);
301
302 if (!CommSucc)
303 break;
304
305 OutliningInfo->Entries.push_back(CurrEntry);
306 CurrEntry = OtherSucc;
307
308 } while (true);
309
310 if (!CandidateFound)
311 return std::unique_ptr<FunctionOutliningInfo>();
312
313 // Do sanity check of the entries: threre should not
314 // be any successors (not in the entry set) other than
315 // {ReturnBlock, NonReturnBlock}
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000316 assert(OutliningInfo->Entries[0] == &F->front() &&
317 "Function Entry must be the first in Entries vector");
Xinliang David Lid21601a2017-04-27 16:34:00 +0000318 DenseSet<BasicBlock *> Entries;
319 for (BasicBlock *E : OutliningInfo->Entries)
320 Entries.insert(E);
321
322 // Returns true of BB has Predecessor which is not
323 // in Entries set.
324 auto HasNonEntryPred = [Entries](BasicBlock *BB) {
325 for (auto Pred : predecessors(BB)) {
326 if (!Entries.count(Pred))
327 return true;
328 }
329 return false;
330 };
331 auto CheckAndNormalizeCandidate =
332 [Entries, HasNonEntryPred](FunctionOutliningInfo *OutliningInfo) {
333 for (BasicBlock *E : OutliningInfo->Entries) {
334 for (auto Succ : successors(E)) {
335 if (Entries.count(Succ))
336 continue;
337 if (Succ == OutliningInfo->ReturnBlock)
338 OutliningInfo->ReturnBlockPreds.push_back(E);
339 else if (Succ != OutliningInfo->NonReturnBlock)
340 return false;
341 }
342 // There should not be any outside incoming edges either:
343 if (HasNonEntryPred(E))
344 return false;
345 }
346 return true;
347 };
348
349 if (!CheckAndNormalizeCandidate(OutliningInfo.get()))
350 return std::unique_ptr<FunctionOutliningInfo>();
351
352 // Now further growing the candidate's inlining region by
353 // peeling off dominating blocks from the outlining region:
354 while (OutliningInfo->GetNumInlinedBlocks() < MaxNumInlineBlocks) {
355 BasicBlock *Cand = OutliningInfo->NonReturnBlock;
356 if (SuccSize(Cand) != 2)
357 break;
358
359 if (HasNonEntryPred(Cand))
360 break;
361
362 BasicBlock *Succ1 = *succ_begin(Cand);
363 BasicBlock *Succ2 = *(succ_begin(Cand) + 1);
364
365 BasicBlock *ReturnBlock, *NonReturnBlock;
366 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
367 if (!ReturnBlock || ReturnBlock != OutliningInfo->ReturnBlock)
368 break;
369
370 if (NonReturnBlock->getSinglePredecessor() != Cand)
371 break;
372
373 // Now grow and update OutlininigInfo:
374 OutliningInfo->Entries.push_back(Cand);
375 OutliningInfo->NonReturnBlock = NonReturnBlock;
376 OutliningInfo->ReturnBlockPreds.push_back(Cand);
377 Entries.insert(Cand);
Reid Klecknerc26a17a2015-02-04 19:14:57 +0000378 }
Sean Silvafe5abd52016-07-25 05:00:00 +0000379
Xinliang David Lid21601a2017-04-27 16:34:00 +0000380 return OutliningInfo;
381}
382
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000383// Check if there is PGO data or user annoated branch data:
384static bool hasProfileData(Function *F, FunctionOutliningInfo *OI) {
385 if (F->getEntryCount())
386 return true;
387 // Now check if any of the entry block has MD_prof data:
388 for (auto *E : OI->Entries) {
389 BranchInst *BR = dyn_cast<BranchInst>(E->getTerminator());
390 if (!BR || BR->isUnconditional())
391 continue;
392 uint64_t T, F;
393 if (BR->extractProfMetadata(T, F))
394 return true;
395 }
396 return false;
397}
398
399BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(
400 Function *F, FunctionOutliningInfo *OI, Function *DuplicateFunction,
401 BlockFrequencyInfo *BFI, BasicBlock *OutliningCallBB) {
402
403 auto EntryFreq =
404 BFI->getBlockFreq(&DuplicateFunction->getEntryBlock());
405 auto OutliningCallFreq = BFI->getBlockFreq(OutliningCallBB);
406
407 auto OutlineRegionRelFreq =
408 BranchProbability::getBranchProbability(OutliningCallFreq.getFrequency(),
409 EntryFreq.getFrequency());
410
411 if (hasProfileData(F, OI))
412 return OutlineRegionRelFreq;
413
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000414 // When profile data is not available, we need to be conservative in
415 // estimating the overall savings. Static branch prediction can usually
416 // guess the branch direction right (taken/non-taken), but the guessed
417 // branch probability is usually not biased enough. In case when the
418 // outlined region is predicted to be likely, its probability needs
419 // to be made higher (more biased) to not under-estimate the cost of
420 // function outlining. On the other hand, if the outlined region
421 // is predicted to be less likely, the predicted probablity is usually
422 // higher than the actual. For instance, the actual probability of the
423 // less likely target is only 5%, but the guessed probablity can be
424 // 40%. In the latter case, there is no need for further adjustement.
425 // FIXME: add an option for this.
426 if (OutlineRegionRelFreq < BranchProbability(45, 100))
427 return OutlineRegionRelFreq;
428
429 OutlineRegionRelFreq = std::max(
430 OutlineRegionRelFreq, BranchProbability(OutlineRegionFreqPercent, 100));
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000431
432 return OutlineRegionRelFreq;
433}
434
435bool PartialInlinerImpl::shouldPartialInline(
436 CallSite CS, Function *F /* Original Callee */, FunctionOutliningInfo *OI,
437 BlockFrequencyInfo *CalleeBFI, BasicBlock *OutliningCallBB,
438 int NonWeightedOutliningRcost, OptimizationRemarkEmitter &ORE) {
Xinliang David Li61338462017-05-02 02:44:14 +0000439 using namespace ore;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000440 if (SkipCostAnalysis)
441 return true;
442
Xinliang David Li61338462017-05-02 02:44:14 +0000443 Instruction *Call = CS.getInstruction();
444 Function *Callee = CS.getCalledFunction();
445 Function *Caller = CS.getCaller();
446 auto &CalleeTTI = (*GetTTI)(*Callee);
447 InlineCost IC = getInlineCost(CS, getInlineParams(), CalleeTTI,
448 *GetAssumptionCache, GetBFI, PSI);
449
450 if (IC.isAlways()) {
451 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", Call)
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000452 << NV("Callee", F)
Xinliang David Li61338462017-05-02 02:44:14 +0000453 << " should always be fully inlined, not partially");
454 return false;
455 }
456
457 if (IC.isNever()) {
458 ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000459 << NV("Callee", F) << " not partially inlined into "
Xinliang David Li61338462017-05-02 02:44:14 +0000460 << NV("Caller", Caller)
461 << " because it should never be inlined (cost=never)");
462 return false;
463 }
464
465 if (!IC) {
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000466 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", Call)
467 << NV("Callee", F) << " not partially inlined into "
Xinliang David Li61338462017-05-02 02:44:14 +0000468 << NV("Caller", Caller) << " because too costly to inline (cost="
469 << NV("Cost", IC.getCost()) << ", threshold="
470 << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
471 return false;
472 }
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000473 const DataLayout &DL = Caller->getParent()->getDataLayout();
474 // The savings of eliminating the call:
475 int NonWeightedSavings = getCallsiteCost(CS, DL);
476 BlockFrequency NormWeightedSavings(NonWeightedSavings);
477
478 auto RelativeFreq =
479 getOutliningCallBBRelativeFreq(F, OI, Callee, CalleeBFI, OutliningCallBB);
480 auto NormWeightedRcost =
481 BlockFrequency(NonWeightedOutliningRcost) * RelativeFreq;
482
483 // Weighted saving is smaller than weighted cost, return false
484 if (NormWeightedSavings < NormWeightedRcost) {
485 ORE.emit(
486 OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh", Call)
487 << NV("Callee", F) << " not partially inlined into "
488 << NV("Caller", Caller) << " runtime overhead (overhead="
489 << NV("Overhead", (unsigned)NormWeightedRcost.getFrequency())
490 << ", savings="
491 << NV("Savings", (unsigned)NormWeightedSavings.getFrequency()) << ")"
492 << " of making the outlined call is too high");
493
494 return false;
495 }
Xinliang David Li61338462017-05-02 02:44:14 +0000496
497 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", Call)
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000498 << NV("Callee", F) << " can be partially inlined into "
Xinliang David Li61338462017-05-02 02:44:14 +0000499 << NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())
500 << " (threshold="
501 << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
502 return true;
503}
504
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000505// TODO: Ideally we should share Inliner's InlineCost Analysis code.
506// For now use a simplified version. The returned 'InlineCost' will be used
507// to esimate the size cost as well as runtime cost of the BB.
508int PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB) {
509 int InlineCost = 0;
510 const DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
511 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
512 if (isa<DbgInfoIntrinsic>(I))
513 continue;
514
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000515 switch (I->getOpcode()) {
516 case Instruction::BitCast:
517 case Instruction::PtrToInt:
518 case Instruction::IntToPtr:
519 case Instruction::Alloca:
520 continue;
521 case Instruction::GetElementPtr:
522 if (cast<GetElementPtrInst>(I)->hasAllZeroIndices())
523 continue;
524 default:
525 break;
526 }
527
528 IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(I);
529 if (IntrInst) {
530 if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start ||
531 IntrInst->getIntrinsicID() == Intrinsic::lifetime_end)
532 continue;
533 }
534
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000535 if (CallInst *CI = dyn_cast<CallInst>(I)) {
536 InlineCost += getCallsiteCost(CallSite(CI), DL);
537 continue;
538 }
539
540 if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
541 InlineCost += getCallsiteCost(CallSite(II), DL);
542 continue;
543 }
544
545 if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
546 InlineCost += (SI->getNumCases() + 1) * InlineConstants::InstrCost;
547 continue;
548 }
549 InlineCost += InlineConstants::InstrCost;
550 }
551 return InlineCost;
552}
553
554std::tuple<int, int, int> PartialInlinerImpl::computeOutliningCosts(
555 Function *F, const FunctionOutliningInfo *OI, Function *OutlinedFunction,
556 BasicBlock *OutliningCallBB) {
557 // First compute the cost of the outlined region 'OI' in the original
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000558 // function 'F'.
559 // FIXME: The code extractor (outliner) can now do code sinking/hoisting
560 // to reduce outlining cost. The hoisted/sunk code currently do not
561 // incur any runtime cost so it is still OK to compare the outlined
562 // function cost with the outlined region in the original function.
563 // If this ever changes, we will need to introduce new extractor api
564 // to pass the information.
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000565 int OutlinedRegionCost = 0;
566 for (BasicBlock &BB : *F) {
567 if (&BB != OI->ReturnBlock &&
568 // Assuming Entry set is small -- do a linear search here:
569 std::find(OI->Entries.begin(), OI->Entries.end(), &BB) ==
570 OI->Entries.end()) {
571 OutlinedRegionCost += computeBBInlineCost(&BB);
572 }
573 }
574
575 // Now compute the cost of the call sequence to the outlined function
576 // 'OutlinedFunction' in BB 'OutliningCallBB':
577 int OutliningFuncCallCost = computeBBInlineCost(OutliningCallBB);
578
579 // Now compute the cost of the extracted/outlined function itself:
580 int OutlinedFunctionCost = 0;
581 for (BasicBlock &BB : *OutlinedFunction) {
582 OutlinedFunctionCost += computeBBInlineCost(&BB);
583 }
Xinliang David Li5fdc75a2017-06-02 22:38:48 +0000584
585 assert(OutlinedFunctionCost >= OutlinedRegionCost &&
586 "Outlined function cost should be no less than the outlined region");
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000587 // The code extractor introduces a new root and exit stub blocks with
588 // additional unconditional branches. Those branches will be eliminated
589 // later with bb layout. The cost should be adjusted accordingly:
590 OutlinedFunctionCost -= 2 * InlineConstants::InstrCost;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000591
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000592 int OutliningRuntimeOverhead = OutliningFuncCallCost +
593 (OutlinedFunctionCost - OutlinedRegionCost) +
594 ExtraOutliningPenalty;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000595
596 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead,
597 OutlinedRegionCost);
598}
599
600// Create the callsite to profile count map which is
601// used to update the original function's entry count,
602// after the function is partially inlined into the callsite.
603void PartialInlinerImpl::computeCallsiteToProfCountMap(
604 Function *DuplicateFunction,
605 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) {
606 std::vector<User *> Users(DuplicateFunction->user_begin(),
607 DuplicateFunction->user_end());
608 Function *CurrentCaller = nullptr;
Vitaly Bukaa6374892017-05-27 05:32:09 +0000609 std::unique_ptr<BlockFrequencyInfo> TempBFI;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000610 BlockFrequencyInfo *CurrentCallerBFI = nullptr;
611
612 auto ComputeCurrBFI = [&,this](Function *Caller) {
613 // For the old pass manager:
614 if (!GetBFI) {
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000615 DominatorTree DT(*Caller);
616 LoopInfo LI(DT);
617 BranchProbabilityInfo BPI(*Caller, LI);
Vitaly Bukaa6374892017-05-27 05:32:09 +0000618 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, LI));
619 CurrentCallerBFI = TempBFI.get();
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000620 } else {
621 // New pass manager:
622 CurrentCallerBFI = &(*GetBFI)(*Caller);
623 }
624 };
625
626 for (User *User : Users) {
627 CallSite CS = getCallSite(User);
628 Function *Caller = CS.getCaller();
629 if (CurrentCaller != Caller) {
630 CurrentCaller = Caller;
631 ComputeCurrBFI(Caller);
632 } else {
633 assert(CurrentCallerBFI && "CallerBFI is not set");
634 }
635 BasicBlock *CallBB = CS.getInstruction()->getParent();
636 auto Count = CurrentCallerBFI->getBlockProfileCount(CallBB);
637 if (Count)
638 CallSiteToProfCountMap[User] = *Count;
639 else
640 CallSiteToProfCountMap[User] = 0;
641 }
642}
643
Xinliang David Lid21601a2017-04-27 16:34:00 +0000644Function *PartialInlinerImpl::unswitchFunction(Function *F) {
645
646 if (F->hasAddressTaken())
647 return nullptr;
648
Xinliang David Liab8722f2017-05-02 18:43:21 +0000649 // Let inliner handle it
650 if (F->hasFnAttribute(Attribute::AlwaysInline))
651 return nullptr;
652
653 if (F->hasFnAttribute(Attribute::NoInline))
654 return nullptr;
655
656 if (PSI->isFunctionEntryCold(F))
657 return nullptr;
658
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000659 if (F->user_begin() == F->user_end())
660 return nullptr;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000661
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000662 std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
663
664 if (!OI)
Craig Topperf40110f2014-04-25 05:29:35 +0000665 return nullptr;
Sean Silvafe5abd52016-07-25 05:00:00 +0000666
Owen Anderson2f82e272009-06-14 08:26:32 +0000667 // Clone the function, so that we can hack away on it.
Rafael Espindola229e38f2010-10-13 01:36:30 +0000668 ValueToValueMapTy VMap;
Sean Silva519323d2016-07-25 05:57:59 +0000669 Function *DuplicateFunction = CloneFunction(F, VMap);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000670 BasicBlock *NewReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
671 BasicBlock *NewNonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
Xinliang David Lid21601a2017-04-27 16:34:00 +0000672 DenseSet<BasicBlock *> NewEntries;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000673 for (BasicBlock *BB : OI->Entries) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000674 NewEntries.insert(cast<BasicBlock>(VMap[BB]));
675 }
Sean Silvafe5abd52016-07-25 05:00:00 +0000676
Owen Anderson2f82e272009-06-14 08:26:32 +0000677 // Go ahead and update all uses to the duplicate, so that we can just
678 // use the inliner functionality when we're done hacking.
Sean Silva519323d2016-07-25 05:57:59 +0000679 F->replaceAllUsesWith(DuplicateFunction);
Sean Silvafe5abd52016-07-25 05:00:00 +0000680
Xinliang David Lid21601a2017-04-27 16:34:00 +0000681 auto getFirstPHI = [](BasicBlock *BB) {
682 BasicBlock::iterator I = BB->begin();
683 PHINode *FirstPhi = nullptr;
684 while (I != BB->end()) {
685 PHINode *Phi = dyn_cast<PHINode>(I);
686 if (!Phi)
687 break;
688 if (!FirstPhi) {
689 FirstPhi = Phi;
690 break;
691 }
692 }
693 return FirstPhi;
694 };
Owen Anderson2f82e272009-06-14 08:26:32 +0000695 // Special hackery is needed with PHI nodes that have inputs from more than
696 // one extracted block. For simplicity, just split the PHIs into a two-level
697 // sequence of PHIs, some of which will go in the extracted region, and some
698 // of which will go outside.
Sean Silva519323d2016-07-25 05:57:59 +0000699 BasicBlock *PreReturn = NewReturnBlock;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000700 // only split block when necessary:
701 PHINode *FirstPhi = getFirstPHI(PreReturn);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000702 unsigned NumPredsFromEntries = OI->ReturnBlockPreds.size();
Xinliang David Li32c5e802017-06-01 00:12:41 +0000703 auto IsTrivialPhi = [](PHINode *PN) -> Value * {
704 Value *CommonValue = PN->getIncomingValue(0);
705 if (all_of(PN->incoming_values(),
706 [&](Value *V) { return V == CommonValue; }))
707 return CommonValue;
708 return nullptr;
709 };
710
Xinliang David Lid21601a2017-04-27 16:34:00 +0000711 if (FirstPhi && FirstPhi->getNumIncomingValues() > NumPredsFromEntries + 1) {
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000712
Xinliang David Lid21601a2017-04-27 16:34:00 +0000713 NewReturnBlock = NewReturnBlock->splitBasicBlock(
714 NewReturnBlock->getFirstNonPHI()->getIterator());
715 BasicBlock::iterator I = PreReturn->begin();
716 Instruction *Ins = &NewReturnBlock->front();
Xinliang David Li32c5e802017-06-01 00:12:41 +0000717 SmallVector<Instruction *, 4> DeadPhis;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000718 while (I != PreReturn->end()) {
719 PHINode *OldPhi = dyn_cast<PHINode>(I);
720 if (!OldPhi)
721 break;
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000722
Xinliang David Lid21601a2017-04-27 16:34:00 +0000723 PHINode *RetPhi =
724 PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins);
725 OldPhi->replaceAllUsesWith(RetPhi);
726 Ins = NewReturnBlock->getFirstNonPHI();
Sean Silvafe5abd52016-07-25 05:00:00 +0000727
Xinliang David Lid21601a2017-04-27 16:34:00 +0000728 RetPhi->addIncoming(&*I, PreReturn);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000729 for (BasicBlock *E : OI->ReturnBlockPreds) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000730 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
731 RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(NewE), NewE);
732 OldPhi->removeIncomingValue(NewE);
733 }
Xinliang David Li32c5e802017-06-01 00:12:41 +0000734
735 // After incoming values splitting, the old phi may become trivial.
736 // Keeping the trivial phi can introduce definition inside the outline
737 // region which is live-out, causing necessary overhead (load, store
738 // arg passing etc).
739 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
740 OldPhi->replaceAllUsesWith(OldPhiVal);
741 DeadPhis.push_back(OldPhi);
742 }
743
Xinliang David Lid21601a2017-04-27 16:34:00 +0000744 ++I;
745 }
Xinliang David Li32c5e802017-06-01 00:12:41 +0000746
747 for (auto *DP : DeadPhis)
748 DP->eraseFromParent();
749
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000750 for (auto E : OI->ReturnBlockPreds) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000751 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
752 NewE->getTerminator()->replaceUsesOfWith(PreReturn, NewReturnBlock);
753 }
Owen Anderson2f82e272009-06-14 08:26:32 +0000754 }
Sean Silvafe5abd52016-07-25 05:00:00 +0000755
Xinliang David Lid21601a2017-04-27 16:34:00 +0000756 // Returns true if the block is to be partial inlined into the caller
757 // (i.e. not to be extracted to the out of line function)
Davide Italianoaa42a102017-05-08 20:44:01 +0000758 auto ToBeInlined = [&](BasicBlock *BB) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000759 return BB == NewReturnBlock || NewEntries.count(BB);
760 };
Owen Anderson2f82e272009-06-14 08:26:32 +0000761 // Gather up the blocks that we're going to extract.
Sean Silva519323d2016-07-25 05:57:59 +0000762 std::vector<BasicBlock *> ToExtract;
763 ToExtract.push_back(NewNonReturnBlock);
764 for (BasicBlock &BB : *DuplicateFunction)
Xinliang David Lid21601a2017-04-27 16:34:00 +0000765 if (!ToBeInlined(&BB) && &BB != NewNonReturnBlock)
Sean Silva519323d2016-07-25 05:57:59 +0000766 ToExtract.push_back(&BB);
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000767
Owen Anderson2f82e272009-06-14 08:26:32 +0000768 // The CodeExtractor needs a dominator tree.
769 DominatorTree DT;
Sean Silva519323d2016-07-25 05:57:59 +0000770 DT.recalculate(*DuplicateFunction);
Chandler Carruth73523022014-01-13 13:07:17 +0000771
Sean Silvaf8015752016-08-02 02:15:45 +0000772 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
773 LoopInfo LI(DT);
774 BranchProbabilityInfo BPI(*DuplicateFunction, LI);
775 BlockFrequencyInfo BFI(*DuplicateFunction, BPI, LI);
776
Dan Gohman4a618822010-02-10 16:03:48 +0000777 // Extract the body of the if.
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000778 Function *OutlinedFunction =
Sean Silvaf8015752016-08-02 02:15:45 +0000779 CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false, &BFI, &BPI)
780 .extractCodeRegion();
Sean Silvafe5abd52016-07-25 05:00:00 +0000781
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000782 bool AnyInline =
783 tryPartialInline(DuplicateFunction, F, OI.get(), OutlinedFunction, &BFI);
Sean Silvafe5abd52016-07-25 05:00:00 +0000784
Owen Anderson2f82e272009-06-14 08:26:32 +0000785 // Ditch the duplicate, since we're done with it, and rewrite all remaining
786 // users (function pointers, etc.) back to the original function.
Sean Silva519323d2016-07-25 05:57:59 +0000787 DuplicateFunction->replaceAllUsesWith(F);
788 DuplicateFunction->eraseFromParent();
Xinliang David Li392e9752017-05-14 02:54:02 +0000789
790 if (AnyInline)
791 return OutlinedFunction;
792
793 // Remove the function that is speculatively created:
794 if (OutlinedFunction)
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000795 OutlinedFunction->eraseFromParent();
Xinliang David Li392e9752017-05-14 02:54:02 +0000796
797 return nullptr;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000798}
Sean Silvafe5abd52016-07-25 05:00:00 +0000799
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000800bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction,
801 Function *F,
802 FunctionOutliningInfo *OI,
803 Function *OutlinedFunction,
804 BlockFrequencyInfo *CalleeBFI) {
805 if (OutlinedFunction == nullptr)
806 return false;
Sean Silvafe5abd52016-07-25 05:00:00 +0000807
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000808 int NonWeightedRcost;
809 int SizeCost;
810 int OutlinedRegionSizeCost;
811
812 auto OutliningCallBB =
813 getOneCallSiteTo(OutlinedFunction).getInstruction()->getParent();
814
815 std::tie(SizeCost, NonWeightedRcost, OutlinedRegionSizeCost) =
816 computeOutliningCosts(F, OI, OutlinedFunction, OutliningCallBB);
817
818 // The call sequence to the outlined function is larger than the original
819 // outlined region size, it does not increase the chances of inlining
820 // 'F' with outlining (The inliner usies the size increase to model the
821 // the cost of inlining a callee).
822 if (!SkipCostAnalysis && OutlinedRegionSizeCost < SizeCost) {
823 OptimizationRemarkEmitter ORE(F);
824 DebugLoc DLoc;
825 BasicBlock *Block;
826 std::tie(DLoc, Block) = getOneDebugLoc(DuplicateFunction);
827 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
828 DLoc, Block)
829 << ore::NV("Function", F)
830 << " not partially inlined into callers (Original Size = "
831 << ore::NV("OutlinedRegionOriginalSize", OutlinedRegionSizeCost)
832 << ", Size of call sequence to outlined function = "
833 << ore::NV("NewSize", SizeCost) << ")");
834 return false;
835 }
836
837 assert(F->user_begin() == F->user_end() &&
838 "F's users should all be replaced!");
839 std::vector<User *> Users(DuplicateFunction->user_begin(),
840 DuplicateFunction->user_end());
841
842 DenseMap<User *, uint64_t> CallSiteToProfCountMap;
843 if (F->getEntryCount())
844 computeCallsiteToProfCountMap(DuplicateFunction, CallSiteToProfCountMap);
845
846 auto CalleeEntryCount = F->getEntryCount();
847 uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0);
848 bool AnyInline = false;
849 for (User *User : Users) {
850 CallSite CS = getCallSite(User);
851
852 if (IsLimitReached())
853 continue;
854
855 OptimizationRemarkEmitter ORE(CS.getCaller());
856
857 if (!shouldPartialInline(CS, F, OI, CalleeBFI, OutliningCallBB,
858 NonWeightedRcost, ORE))
859 continue;
860
861 ORE.emit(
862 OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", CS.getInstruction())
863 << ore::NV("Callee", F) << " partially inlined into "
864 << ore::NV("Caller", CS.getCaller()));
865
866 InlineFunctionInfo IFI(nullptr, GetAssumptionCache, PSI);
867 InlineFunction(CS, IFI);
868
869 // Now update the entry count:
870 if (CalleeEntryCountV && CallSiteToProfCountMap.count(User)) {
871 uint64_t CallSiteCount = CallSiteToProfCountMap[User];
872 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);
873 }
874
875 AnyInline = true;
876 NumPartialInlining++;
877 // Update the stats
878 NumPartialInlined++;
879 }
880
881 if (AnyInline && CalleeEntryCount)
882 F->setEntryCount(CalleeEntryCountV);
883
884 return AnyInline;
Owen Anderson2f82e272009-06-14 08:26:32 +0000885}
886
Sean Silvafe5abd52016-07-25 05:00:00 +0000887bool PartialInlinerImpl::run(Module &M) {
Xinliang David Lidb8d09b2017-04-23 23:39:04 +0000888 if (DisablePartialInlining)
889 return false;
890
Sean Silva519323d2016-07-25 05:57:59 +0000891 std::vector<Function *> Worklist;
892 Worklist.reserve(M.size());
Benjamin Kramer135f7352016-06-26 12:28:59 +0000893 for (Function &F : M)
894 if (!F.use_empty() && !F.isDeclaration())
Sean Silva519323d2016-07-25 05:57:59 +0000895 Worklist.push_back(&F);
Benjamin Kramer135f7352016-06-26 12:28:59 +0000896
Sean Silva519323d2016-07-25 05:57:59 +0000897 bool Changed = false;
898 while (!Worklist.empty()) {
899 Function *CurrFunc = Worklist.back();
900 Worklist.pop_back();
Sean Silvafe5abd52016-07-25 05:00:00 +0000901
Sean Silva519323d2016-07-25 05:57:59 +0000902 if (CurrFunc->use_empty())
903 continue;
Sean Silvafe5abd52016-07-25 05:00:00 +0000904
Sean Silva519323d2016-07-25 05:57:59 +0000905 bool Recursive = false;
906 for (User *U : CurrFunc->users())
907 if (Instruction *I = dyn_cast<Instruction>(U))
908 if (I->getParent()->getParent() == CurrFunc) {
909 Recursive = true;
Owen Anderson2f82e272009-06-14 08:26:32 +0000910 break;
911 }
Sean Silva519323d2016-07-25 05:57:59 +0000912 if (Recursive)
913 continue;
Sean Silvafe5abd52016-07-25 05:00:00 +0000914
Sean Silvaf8015752016-08-02 02:15:45 +0000915 if (Function *NewFunc = unswitchFunction(CurrFunc)) {
916 Worklist.push_back(NewFunc);
Sean Silva519323d2016-07-25 05:57:59 +0000917 Changed = true;
Owen Anderson2f82e272009-06-14 08:26:32 +0000918 }
Owen Anderson2f82e272009-06-14 08:26:32 +0000919 }
Easwaran Raman1832bf62016-06-27 16:50:18 +0000920
Sean Silva519323d2016-07-25 05:57:59 +0000921 return Changed;
Sean Silvafe5abd52016-07-25 05:00:00 +0000922}
923
924char PartialInlinerLegacyPass::ID = 0;
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000925INITIALIZE_PASS_BEGIN(PartialInlinerLegacyPass, "partial-inliner",
926 "Partial Inliner", false, false)
927INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
Xinliang David Li61338462017-05-02 02:44:14 +0000928INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
929INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000930INITIALIZE_PASS_END(PartialInlinerLegacyPass, "partial-inliner",
931 "Partial Inliner", false, false)
Sean Silvafe5abd52016-07-25 05:00:00 +0000932
933ModulePass *llvm::createPartialInliningPass() {
934 return new PartialInlinerLegacyPass();
935}
936
937PreservedAnalyses PartialInlinerPass::run(Module &M,
938 ModuleAnalysisManager &AM) {
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000939 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
Xinliang David Li61338462017-05-02 02:44:14 +0000940
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000941 std::function<AssumptionCache &(Function &)> GetAssumptionCache =
942 [&FAM](Function &F) -> AssumptionCache & {
943 return FAM.getResult<AssumptionAnalysis>(F);
944 };
Xinliang David Li61338462017-05-02 02:44:14 +0000945
946 std::function<BlockFrequencyInfo &(Function &)> GetBFI =
947 [&FAM](Function &F) -> BlockFrequencyInfo & {
948 return FAM.getResult<BlockFrequencyAnalysis>(F);
949 };
950
951 std::function<TargetTransformInfo &(Function &)> GetTTI =
952 [&FAM](Function &F) -> TargetTransformInfo & {
953 return FAM.getResult<TargetIRAnalysis>(F);
954 };
955
956 ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
957
958 if (PartialInlinerImpl(&GetAssumptionCache, &GetTTI, {GetBFI}, PSI).run(M))
Easwaran Raman1832bf62016-06-27 16:50:18 +0000959 return PreservedAnalyses::none();
960 return PreservedAnalyses::all();
Duncan Sands29c8efc2009-07-03 15:30:58 +0000961}