diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -93,6 +93,11 @@ DisableInlinedAllocaMerging("disable-inlined-alloca-merging", cl::init(false), cl::Hidden); +static cl::opt + InlineDeferralScale("inline-deferral-scale", + cl::desc("Scale to limit the cost of inline deferral"), + cl::init(2), cl::Hidden); + namespace { enum class InlinerFunctionImportStatsOpts { @@ -338,12 +343,8 @@ bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse(); // This bool tracks what happens if we DO inline C into B. bool InliningPreventsSomeOuterInline = false; + unsigned SecondaryUsers = 0; for (User *U : Caller->users()) { - // If the caller will not be removed (either because it does not have a - // local linkage or because the LastCallToStaticBonus has been already - // applied), then we can exit the loop early. - if (!ApplyLastCallBonus && TotalSecondaryCost >= IC.getCost()) - return false; CallBase *CS2 = dyn_cast(U); // If this isn't a call to Caller (it could be some other sort @@ -369,8 +370,13 @@ if (IC2.getCostDelta() <= CandidateCost) { InliningPreventsSomeOuterInline = true; TotalSecondaryCost += IC2.getCost(); + SecondaryUsers++; } } + + if (!InliningPreventsSomeOuterInline) + return false; + // If all outer calls to Caller would get inlined, the cost for the last // one is set very low by getInlineCost, in anticipation that Caller will // be removed entirely. We did not account for this above unless there @@ -378,7 +384,9 @@ if (ApplyLastCallBonus) TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus; - return InliningPreventsSomeOuterInline && TotalSecondaryCost < IC.getCost(); + int TotalCost = TotalSecondaryCost + IC.getCost() * SecondaryUsers; + int Allowance = IC.getCost() * InlineDeferralScale; + return TotalCost < Allowance; } static std::basic_ostream &operator<<(std::basic_ostream &R,