Skip to content

Commit e8984fe

Browse files
[Inlining] Teach shouldBeDeferred to take the total cost into account
Summary: This patch teaches shouldBeDeferred to take into account the total cost of inlining. Suppose we have a call hierarchy {A1,A2,A3,...}->B->C. (Each of A1, A2, A3, ... calls B, which in turn calls C.) Without this patch, shouldBeDeferred essentially returns true if TotalSecondaryCost < IC.getCost() where TotalSecondaryCost is the total cost of inlining B into As. This means that if B is a small wraper function, for example, it would get inlined into all of As. In turn, C gets inlined into all of As. In other words, shouldBeDeferred ignores the cost of inlining C into each of As. This patch adds an option, inline-deferral-scale, to replace the expression above with: TotalCost < Allowance where - TotalCost is TotalSecondaryCost + IC.getCost() * # of As, and - Allowance is IC.getCost() * Scale For now, the new option defaults to -1, disabling the new scheme. Reviewers: davidxl Subscribers: eraman, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79138
1 parent 61d5b0e commit e8984fe

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

llvm/lib/Transforms/IPO/Inliner.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ static cl::opt<bool>
9393
DisableInlinedAllocaMerging("disable-inlined-alloca-merging",
9494
cl::init(false), cl::Hidden);
9595

96+
// An integer used to limit the cost of inline deferral. The default negative
97+
// number tells shouldBeDeferred to only take the secondary cost into account.
98+
static cl::opt<int>
99+
InlineDeferralScale("inline-deferral-scale",
100+
cl::desc("Scale to limit the cost of inline deferral"),
101+
cl::init(-1), cl::Hidden);
102+
96103
namespace {
97104

98105
enum class InlinerFunctionImportStatsOpts {
@@ -338,12 +345,8 @@ shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost,
338345
bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse();
339346
// This bool tracks what happens if we DO inline C into B.
340347
bool InliningPreventsSomeOuterInline = false;
348+
unsigned NumCallerUsers = 0;
341349
for (User *U : Caller->users()) {
342-
// If the caller will not be removed (either because it does not have a
343-
// local linkage or because the LastCallToStaticBonus has been already
344-
// applied), then we can exit the loop early.
345-
if (!ApplyLastCallBonus && TotalSecondaryCost >= IC.getCost())
346-
return false;
347350
CallBase *CS2 = dyn_cast<CallBase>(U);
348351

349352
// If this isn't a call to Caller (it could be some other sort
@@ -369,16 +372,28 @@ shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost,
369372
if (IC2.getCostDelta() <= CandidateCost) {
370373
InliningPreventsSomeOuterInline = true;
371374
TotalSecondaryCost += IC2.getCost();
375+
NumCallerUsers++;
372376
}
373377
}
378+
379+
if (!InliningPreventsSomeOuterInline)
380+
return false;
381+
374382
// If all outer calls to Caller would get inlined, the cost for the last
375383
// one is set very low by getInlineCost, in anticipation that Caller will
376384
// be removed entirely. We did not account for this above unless there
377385
// is only one caller of Caller.
378386
if (ApplyLastCallBonus)
379387
TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus;
380388

381-
return InliningPreventsSomeOuterInline && TotalSecondaryCost < IC.getCost();
389+
// If InlineDeferralScale is negative, then ignore the cost of primary
390+
// inlining -- IC.getCost() multiplied by the number of callers to Caller.
391+
if (InlineDeferralScale < 0)
392+
return TotalSecondaryCost < IC.getCost();
393+
394+
int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers;
395+
int Allowance = IC.getCost() * InlineDeferralScale;
396+
return TotalCost < Allowance;
382397
}
383398

384399
static std::basic_ostream<char> &operator<<(std::basic_ostream<char> &R,

0 commit comments

Comments
 (0)