diff --git a/llvm/include/llvm/Analysis/InlineCost.h b/llvm/include/llvm/Analysis/InlineCost.h --- a/llvm/include/llvm/Analysis/InlineCost.h +++ b/llvm/include/llvm/Analysis/InlineCost.h @@ -246,6 +246,20 @@ CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI, function_ref GetTLI); +/// Get the cost estimate ignoring thresholds. This is similar to getInlineCost +/// when passed InlineParams::ComputeFullInlineCost, or a non-null ORE. It +/// uses default InlineParams otherwise. +/// Contrary to getInlineCost, which makes a threshold-based final evaluation of +/// should/shouldn't inline, captured in InlineResult, getInliningCostEstimate +/// returns: +/// - None, if the inlining cannot happen (is illegal) +/// - an integer, representing the cost. +Optional getInliningCostEstimate( + CallBase &Call, TargetTransformInfo &CalleeTTI, + std::function &GetAssumptionCache, + Optional> GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE); + /// Minimal filter to detect invalid constructs for inlining. InlineResult isInlineViable(Function &Callee); } // namespace llvm diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -427,6 +427,9 @@ /// Attempt to evaluate indirect calls to boost its inline cost. const bool BoostIndirectCalls; + /// Ignore the threshold when finalizing analysis. + const bool IgnoreThreshold; + /// Inlining cost measured in abstract units, accounts for all the /// instructions expected to be executed for a given function invocation. /// Instructions that are statically proven to be dead based on call-site @@ -629,14 +632,14 @@ else if (NumVectorInstructions <= NumInstructions / 2) Threshold -= VectorBonus / 2; - if (Cost < std::max(1, Threshold)) + if (IgnoreThreshold || Cost < std::max(1, Threshold)) return InlineResult::success(); return InlineResult::failure("Cost over threshold."); } bool shouldStop() override { // Bail out the moment we cross the threshold. This means we'll under-count // the cost, but only when undercounting doesn't matter. - return Cost >= Threshold && !ComputeFullInlineCost; + return !IgnoreThreshold && Cost >= Threshold && !ComputeFullInlineCost; } void onLoadEliminationOpportunity() override { @@ -694,12 +697,13 @@ std::function &GetAssumptionCache, Optional> &GetBFI, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee, - CallBase &Call, const InlineParams &Params, bool BoostIndirect = true) + CallBase &Call, const InlineParams &Params, bool BoostIndirect = true, + bool IgnoreThreshold = false) : CallAnalyzer(TTI, GetAssumptionCache, GetBFI, PSI, ORE, Callee, Call), ComputeFullInlineCost(OptComputeFullInlineCost || Params.ComputeFullInlineCost || ORE), Params(Params), Threshold(Params.DefaultThreshold), - BoostIndirectCalls(BoostIndirect) {} + BoostIndirectCalls(BoostIndirect), IgnoreThreshold(IgnoreThreshold) {} /// Annotation Writer for cost annotation CostAnnotationWriter Writer; @@ -2215,6 +2219,30 @@ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE); } +Optional getInliningCostEstimate( + CallBase &Call, TargetTransformInfo &CalleeTTI, + std::function &GetAssumptionCache, + Optional> GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) { + const InlineParams Params = {/* DefaultThreshold*/ 0, + /*HintThreshold*/ {}, + /*ColdThreshold*/ {}, + /*OptSizeThreshold*/ {}, + /*OptMinSizeThreshold*/ {}, + /*HotCallSiteThreshold*/ {}, + /*LocallyHotCallSiteThreshold*/ {}, + /*ColdCallSiteThreshold*/ {}, + /* ComputeFullInlineCost*/ true}; + + InlineCostCallAnalyzer CA(CalleeTTI, GetAssumptionCache, GetBFI, PSI, ORE, + *Call.getCalledFunction(), Call, Params, true, + /*IgnoreThreshold*/ true); + auto R = CA.analyze(); + if (!R.isSuccess()) + return None; + return CA.getCost(); +} + Optional llvm::getAttributeBasedInliningDecision( CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI, function_ref GetTLI) {