blob: eee250c4d54c623249605d56753199f1f5f6d242 [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 Li0b7d8582017-06-02 22:08:04 +0000584 // The code extractor introduces a new root and exit stub blocks with
585 // additional unconditional branches. Those branches will be eliminated
586 // later with bb layout. The cost should be adjusted accordingly:
587 OutlinedFunctionCost -= 2 * InlineConstants::InstrCost;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000588
589 assert(OutlinedFunctionCost >= OutlinedRegionCost &&
590 "Outlined function cost should be no less than the outlined region");
Xinliang David Li0b7d8582017-06-02 22:08:04 +0000591 int OutliningRuntimeOverhead = OutliningFuncCallCost +
592 (OutlinedFunctionCost - OutlinedRegionCost) +
593 ExtraOutliningPenalty;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000594
595 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead,
596 OutlinedRegionCost);
597}
598
599// Create the callsite to profile count map which is
600// used to update the original function's entry count,
601// after the function is partially inlined into the callsite.
602void PartialInlinerImpl::computeCallsiteToProfCountMap(
603 Function *DuplicateFunction,
604 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) {
605 std::vector<User *> Users(DuplicateFunction->user_begin(),
606 DuplicateFunction->user_end());
607 Function *CurrentCaller = nullptr;
Vitaly Bukaa6374892017-05-27 05:32:09 +0000608 std::unique_ptr<BlockFrequencyInfo> TempBFI;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000609 BlockFrequencyInfo *CurrentCallerBFI = nullptr;
610
611 auto ComputeCurrBFI = [&,this](Function *Caller) {
612 // For the old pass manager:
613 if (!GetBFI) {
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000614 DominatorTree DT(*Caller);
615 LoopInfo LI(DT);
616 BranchProbabilityInfo BPI(*Caller, LI);
Vitaly Bukaa6374892017-05-27 05:32:09 +0000617 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, LI));
618 CurrentCallerBFI = TempBFI.get();
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000619 } else {
620 // New pass manager:
621 CurrentCallerBFI = &(*GetBFI)(*Caller);
622 }
623 };
624
625 for (User *User : Users) {
626 CallSite CS = getCallSite(User);
627 Function *Caller = CS.getCaller();
628 if (CurrentCaller != Caller) {
629 CurrentCaller = Caller;
630 ComputeCurrBFI(Caller);
631 } else {
632 assert(CurrentCallerBFI && "CallerBFI is not set");
633 }
634 BasicBlock *CallBB = CS.getInstruction()->getParent();
635 auto Count = CurrentCallerBFI->getBlockProfileCount(CallBB);
636 if (Count)
637 CallSiteToProfCountMap[User] = *Count;
638 else
639 CallSiteToProfCountMap[User] = 0;
640 }
641}
642
Xinliang David Lid21601a2017-04-27 16:34:00 +0000643Function *PartialInlinerImpl::unswitchFunction(Function *F) {
644
645 if (F->hasAddressTaken())
646 return nullptr;
647
Xinliang David Liab8722f2017-05-02 18:43:21 +0000648 // Let inliner handle it
649 if (F->hasFnAttribute(Attribute::AlwaysInline))
650 return nullptr;
651
652 if (F->hasFnAttribute(Attribute::NoInline))
653 return nullptr;
654
655 if (PSI->isFunctionEntryCold(F))
656 return nullptr;
657
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000658 if (F->user_begin() == F->user_end())
659 return nullptr;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000660
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000661 std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
662
663 if (!OI)
Craig Topperf40110f2014-04-25 05:29:35 +0000664 return nullptr;
Sean Silvafe5abd52016-07-25 05:00:00 +0000665
Owen Anderson2f82e272009-06-14 08:26:32 +0000666 // Clone the function, so that we can hack away on it.
Rafael Espindola229e38f2010-10-13 01:36:30 +0000667 ValueToValueMapTy VMap;
Sean Silva519323d2016-07-25 05:57:59 +0000668 Function *DuplicateFunction = CloneFunction(F, VMap);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000669 BasicBlock *NewReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
670 BasicBlock *NewNonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
Xinliang David Lid21601a2017-04-27 16:34:00 +0000671 DenseSet<BasicBlock *> NewEntries;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000672 for (BasicBlock *BB : OI->Entries) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000673 NewEntries.insert(cast<BasicBlock>(VMap[BB]));
674 }
Sean Silvafe5abd52016-07-25 05:00:00 +0000675
Owen Anderson2f82e272009-06-14 08:26:32 +0000676 // Go ahead and update all uses to the duplicate, so that we can just
677 // use the inliner functionality when we're done hacking.
Sean Silva519323d2016-07-25 05:57:59 +0000678 F->replaceAllUsesWith(DuplicateFunction);
Sean Silvafe5abd52016-07-25 05:00:00 +0000679
Xinliang David Lid21601a2017-04-27 16:34:00 +0000680 auto getFirstPHI = [](BasicBlock *BB) {
681 BasicBlock::iterator I = BB->begin();
682 PHINode *FirstPhi = nullptr;
683 while (I != BB->end()) {
684 PHINode *Phi = dyn_cast<PHINode>(I);
685 if (!Phi)
686 break;
687 if (!FirstPhi) {
688 FirstPhi = Phi;
689 break;
690 }
691 }
692 return FirstPhi;
693 };
Owen Anderson2f82e272009-06-14 08:26:32 +0000694 // Special hackery is needed with PHI nodes that have inputs from more than
695 // one extracted block. For simplicity, just split the PHIs into a two-level
696 // sequence of PHIs, some of which will go in the extracted region, and some
697 // of which will go outside.
Sean Silva519323d2016-07-25 05:57:59 +0000698 BasicBlock *PreReturn = NewReturnBlock;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000699 // only split block when necessary:
700 PHINode *FirstPhi = getFirstPHI(PreReturn);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000701 unsigned NumPredsFromEntries = OI->ReturnBlockPreds.size();
Xinliang David Li32c5e802017-06-01 00:12:41 +0000702 auto IsTrivialPhi = [](PHINode *PN) -> Value * {
703 Value *CommonValue = PN->getIncomingValue(0);
704 if (all_of(PN->incoming_values(),
705 [&](Value *V) { return V == CommonValue; }))
706 return CommonValue;
707 return nullptr;
708 };
709
Xinliang David Lid21601a2017-04-27 16:34:00 +0000710 if (FirstPhi && FirstPhi->getNumIncomingValues() > NumPredsFromEntries + 1) {
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000711
Xinliang David Lid21601a2017-04-27 16:34:00 +0000712 NewReturnBlock = NewReturnBlock->splitBasicBlock(
713 NewReturnBlock->getFirstNonPHI()->getIterator());
714 BasicBlock::iterator I = PreReturn->begin();
715 Instruction *Ins = &NewReturnBlock->front();
Xinliang David Li32c5e802017-06-01 00:12:41 +0000716 SmallVector<Instruction *, 4> DeadPhis;
Xinliang David Lid21601a2017-04-27 16:34:00 +0000717 while (I != PreReturn->end()) {
718 PHINode *OldPhi = dyn_cast<PHINode>(I);
719 if (!OldPhi)
720 break;
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000721
Xinliang David Lid21601a2017-04-27 16:34:00 +0000722 PHINode *RetPhi =
723 PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins);
724 OldPhi->replaceAllUsesWith(RetPhi);
725 Ins = NewReturnBlock->getFirstNonPHI();
Sean Silvafe5abd52016-07-25 05:00:00 +0000726
Xinliang David Lid21601a2017-04-27 16:34:00 +0000727 RetPhi->addIncoming(&*I, PreReturn);
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000728 for (BasicBlock *E : OI->ReturnBlockPreds) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000729 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
730 RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(NewE), NewE);
731 OldPhi->removeIncomingValue(NewE);
732 }
Xinliang David Li32c5e802017-06-01 00:12:41 +0000733
734 // After incoming values splitting, the old phi may become trivial.
735 // Keeping the trivial phi can introduce definition inside the outline
736 // region which is live-out, causing necessary overhead (load, store
737 // arg passing etc).
738 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
739 OldPhi->replaceAllUsesWith(OldPhiVal);
740 DeadPhis.push_back(OldPhi);
741 }
742
Xinliang David Lid21601a2017-04-27 16:34:00 +0000743 ++I;
744 }
Xinliang David Li32c5e802017-06-01 00:12:41 +0000745
746 for (auto *DP : DeadPhis)
747 DP->eraseFromParent();
748
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000749 for (auto E : OI->ReturnBlockPreds) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000750 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
751 NewE->getTerminator()->replaceUsesOfWith(PreReturn, NewReturnBlock);
752 }
Owen Anderson2f82e272009-06-14 08:26:32 +0000753 }
Sean Silvafe5abd52016-07-25 05:00:00 +0000754
Xinliang David Lid21601a2017-04-27 16:34:00 +0000755 // Returns true if the block is to be partial inlined into the caller
756 // (i.e. not to be extracted to the out of line function)
Davide Italianoaa42a102017-05-08 20:44:01 +0000757 auto ToBeInlined = [&](BasicBlock *BB) {
Xinliang David Lid21601a2017-04-27 16:34:00 +0000758 return BB == NewReturnBlock || NewEntries.count(BB);
759 };
Owen Anderson2f82e272009-06-14 08:26:32 +0000760 // Gather up the blocks that we're going to extract.
Sean Silva519323d2016-07-25 05:57:59 +0000761 std::vector<BasicBlock *> ToExtract;
762 ToExtract.push_back(NewNonReturnBlock);
763 for (BasicBlock &BB : *DuplicateFunction)
Xinliang David Lid21601a2017-04-27 16:34:00 +0000764 if (!ToBeInlined(&BB) && &BB != NewNonReturnBlock)
Sean Silva519323d2016-07-25 05:57:59 +0000765 ToExtract.push_back(&BB);
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000766
Owen Anderson2f82e272009-06-14 08:26:32 +0000767 // The CodeExtractor needs a dominator tree.
768 DominatorTree DT;
Sean Silva519323d2016-07-25 05:57:59 +0000769 DT.recalculate(*DuplicateFunction);
Chandler Carruth73523022014-01-13 13:07:17 +0000770
Sean Silvaf8015752016-08-02 02:15:45 +0000771 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
772 LoopInfo LI(DT);
773 BranchProbabilityInfo BPI(*DuplicateFunction, LI);
774 BlockFrequencyInfo BFI(*DuplicateFunction, BPI, LI);
775
Dan Gohman4a618822010-02-10 16:03:48 +0000776 // Extract the body of the if.
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000777 Function *OutlinedFunction =
Sean Silvaf8015752016-08-02 02:15:45 +0000778 CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false, &BFI, &BPI)
779 .extractCodeRegion();
Sean Silvafe5abd52016-07-25 05:00:00 +0000780
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000781 bool AnyInline =
782 tryPartialInline(DuplicateFunction, F, OI.get(), OutlinedFunction, &BFI);
Sean Silvafe5abd52016-07-25 05:00:00 +0000783
Owen Anderson2f82e272009-06-14 08:26:32 +0000784 // Ditch the duplicate, since we're done with it, and rewrite all remaining
785 // users (function pointers, etc.) back to the original function.
Sean Silva519323d2016-07-25 05:57:59 +0000786 DuplicateFunction->replaceAllUsesWith(F);
787 DuplicateFunction->eraseFromParent();
Xinliang David Li392e9752017-05-14 02:54:02 +0000788
789 if (AnyInline)
790 return OutlinedFunction;
791
792 // Remove the function that is speculatively created:
793 if (OutlinedFunction)
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000794 OutlinedFunction->eraseFromParent();
Xinliang David Li392e9752017-05-14 02:54:02 +0000795
796 return nullptr;
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000797}
Sean Silvafe5abd52016-07-25 05:00:00 +0000798
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000799bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction,
800 Function *F,
801 FunctionOutliningInfo *OI,
802 Function *OutlinedFunction,
803 BlockFrequencyInfo *CalleeBFI) {
804 if (OutlinedFunction == nullptr)
805 return false;
Sean Silvafe5abd52016-07-25 05:00:00 +0000806
Xinliang David Li66bdfca2017-05-12 23:41:43 +0000807 int NonWeightedRcost;
808 int SizeCost;
809 int OutlinedRegionSizeCost;
810
811 auto OutliningCallBB =
812 getOneCallSiteTo(OutlinedFunction).getInstruction()->getParent();
813
814 std::tie(SizeCost, NonWeightedRcost, OutlinedRegionSizeCost) =
815 computeOutliningCosts(F, OI, OutlinedFunction, OutliningCallBB);
816
817 // The call sequence to the outlined function is larger than the original
818 // outlined region size, it does not increase the chances of inlining
819 // 'F' with outlining (The inliner usies the size increase to model the
820 // the cost of inlining a callee).
821 if (!SkipCostAnalysis && OutlinedRegionSizeCost < SizeCost) {
822 OptimizationRemarkEmitter ORE(F);
823 DebugLoc DLoc;
824 BasicBlock *Block;
825 std::tie(DLoc, Block) = getOneDebugLoc(DuplicateFunction);
826 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
827 DLoc, Block)
828 << ore::NV("Function", F)
829 << " not partially inlined into callers (Original Size = "
830 << ore::NV("OutlinedRegionOriginalSize", OutlinedRegionSizeCost)
831 << ", Size of call sequence to outlined function = "
832 << ore::NV("NewSize", SizeCost) << ")");
833 return false;
834 }
835
836 assert(F->user_begin() == F->user_end() &&
837 "F's users should all be replaced!");
838 std::vector<User *> Users(DuplicateFunction->user_begin(),
839 DuplicateFunction->user_end());
840
841 DenseMap<User *, uint64_t> CallSiteToProfCountMap;
842 if (F->getEntryCount())
843 computeCallsiteToProfCountMap(DuplicateFunction, CallSiteToProfCountMap);
844
845 auto CalleeEntryCount = F->getEntryCount();
846 uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0);
847 bool AnyInline = false;
848 for (User *User : Users) {
849 CallSite CS = getCallSite(User);
850
851 if (IsLimitReached())
852 continue;
853
854 OptimizationRemarkEmitter ORE(CS.getCaller());
855
856 if (!shouldPartialInline(CS, F, OI, CalleeBFI, OutliningCallBB,
857 NonWeightedRcost, ORE))
858 continue;
859
860 ORE.emit(
861 OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", CS.getInstruction())
862 << ore::NV("Callee", F) << " partially inlined into "
863 << ore::NV("Caller", CS.getCaller()));
864
865 InlineFunctionInfo IFI(nullptr, GetAssumptionCache, PSI);
866 InlineFunction(CS, IFI);
867
868 // Now update the entry count:
869 if (CalleeEntryCountV && CallSiteToProfCountMap.count(User)) {
870 uint64_t CallSiteCount = CallSiteToProfCountMap[User];
871 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);
872 }
873
874 AnyInline = true;
875 NumPartialInlining++;
876 // Update the stats
877 NumPartialInlined++;
878 }
879
880 if (AnyInline && CalleeEntryCount)
881 F->setEntryCount(CalleeEntryCountV);
882
883 return AnyInline;
Owen Anderson2f82e272009-06-14 08:26:32 +0000884}
885
Sean Silvafe5abd52016-07-25 05:00:00 +0000886bool PartialInlinerImpl::run(Module &M) {
Xinliang David Lidb8d09b2017-04-23 23:39:04 +0000887 if (DisablePartialInlining)
888 return false;
889
Sean Silva519323d2016-07-25 05:57:59 +0000890 std::vector<Function *> Worklist;
891 Worklist.reserve(M.size());
Benjamin Kramer135f7352016-06-26 12:28:59 +0000892 for (Function &F : M)
893 if (!F.use_empty() && !F.isDeclaration())
Sean Silva519323d2016-07-25 05:57:59 +0000894 Worklist.push_back(&F);
Benjamin Kramer135f7352016-06-26 12:28:59 +0000895
Sean Silva519323d2016-07-25 05:57:59 +0000896 bool Changed = false;
897 while (!Worklist.empty()) {
898 Function *CurrFunc = Worklist.back();
899 Worklist.pop_back();
Sean Silvafe5abd52016-07-25 05:00:00 +0000900
Sean Silva519323d2016-07-25 05:57:59 +0000901 if (CurrFunc->use_empty())
902 continue;
Sean Silvafe5abd52016-07-25 05:00:00 +0000903
Sean Silva519323d2016-07-25 05:57:59 +0000904 bool Recursive = false;
905 for (User *U : CurrFunc->users())
906 if (Instruction *I = dyn_cast<Instruction>(U))
907 if (I->getParent()->getParent() == CurrFunc) {
908 Recursive = true;
Owen Anderson2f82e272009-06-14 08:26:32 +0000909 break;
910 }
Sean Silva519323d2016-07-25 05:57:59 +0000911 if (Recursive)
912 continue;
Sean Silvafe5abd52016-07-25 05:00:00 +0000913
Sean Silvaf8015752016-08-02 02:15:45 +0000914 if (Function *NewFunc = unswitchFunction(CurrFunc)) {
915 Worklist.push_back(NewFunc);
Sean Silva519323d2016-07-25 05:57:59 +0000916 Changed = true;
Owen Anderson2f82e272009-06-14 08:26:32 +0000917 }
Owen Anderson2f82e272009-06-14 08:26:32 +0000918 }
Easwaran Raman1832bf62016-06-27 16:50:18 +0000919
Sean Silva519323d2016-07-25 05:57:59 +0000920 return Changed;
Sean Silvafe5abd52016-07-25 05:00:00 +0000921}
922
923char PartialInlinerLegacyPass::ID = 0;
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000924INITIALIZE_PASS_BEGIN(PartialInlinerLegacyPass, "partial-inliner",
925 "Partial Inliner", false, false)
926INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
Xinliang David Li61338462017-05-02 02:44:14 +0000927INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
928INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000929INITIALIZE_PASS_END(PartialInlinerLegacyPass, "partial-inliner",
930 "Partial Inliner", false, false)
Sean Silvafe5abd52016-07-25 05:00:00 +0000931
932ModulePass *llvm::createPartialInliningPass() {
933 return new PartialInlinerLegacyPass();
934}
935
936PreservedAnalyses PartialInlinerPass::run(Module &M,
937 ModuleAnalysisManager &AM) {
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000938 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
Xinliang David Li61338462017-05-02 02:44:14 +0000939
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000940 std::function<AssumptionCache &(Function &)> GetAssumptionCache =
941 [&FAM](Function &F) -> AssumptionCache & {
942 return FAM.getResult<AssumptionAnalysis>(F);
943 };
Xinliang David Li61338462017-05-02 02:44:14 +0000944
945 std::function<BlockFrequencyInfo &(Function &)> GetBFI =
946 [&FAM](Function &F) -> BlockFrequencyInfo & {
947 return FAM.getResult<BlockFrequencyAnalysis>(F);
948 };
949
950 std::function<TargetTransformInfo &(Function &)> GetTTI =
951 [&FAM](Function &F) -> TargetTransformInfo & {
952 return FAM.getResult<TargetIRAnalysis>(F);
953 };
954
955 ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
956
957 if (PartialInlinerImpl(&GetAssumptionCache, &GetTTI, {GetBFI}, PSI).run(M))
Easwaran Raman1832bf62016-06-27 16:50:18 +0000958 return PreservedAnalyses::none();
959 return PreservedAnalyses::all();
Duncan Sands29c8efc2009-07-03 15:30:58 +0000960}