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 @@ -54,6 +54,22 @@ const uint64_t MaxSimplifiedDynamicAllocaToInline = 65536; } // namespace InlineConstants +// The cost-benefit pair computed by cost-benefit analysis. +class CostBenefitPair { +public: + CostBenefitPair(APInt Cost, APInt Benefit) : Cost(Cost), Benefit(Benefit) {} + CostBenefitPair(const CostBenefitPair &CBP) + : Cost(CBP.getCost()), Benefit(CBP.getBenefit()) {} + + const APInt &getCost() const { return Cost; } + + const APInt &getBenefit() const { return Benefit; } + +private: + APInt Cost; + APInt Benefit; +}; + /// Represents the cost of inlining a function. /// /// This supports special values for functions which should "always" or @@ -76,9 +92,14 @@ /// Must be set for Always and Never instances. const char *Reason = nullptr; + /// The cost-benefit pair computed by cost-benefit analysis. + Optional CostBenefit = None; + // Trivial constructor, interesting logic in the factory functions below. - InlineCost(int Cost, int Threshold, const char *Reason = nullptr) - : Cost(Cost), Threshold(Threshold), Reason(Reason) { + InlineCost(int Cost, int Threshold, const char *Reason = nullptr, + Optional CostBenefit = None) + : Cost(Cost), Threshold(Threshold), Reason(Reason), + CostBenefit(CostBenefit) { assert((isVariable() || Reason) && "Reason must be provided for Never or Always"); } @@ -89,11 +110,13 @@ assert(Cost < NeverInlineCost && "Cost crosses sentinel value"); return InlineCost(Cost, Threshold); } - static InlineCost getAlways(const char *Reason) { - return InlineCost(AlwaysInlineCost, 0, Reason); + static InlineCost getAlways(const char *Reason, + Optional CostBenefit = None) { + return InlineCost(AlwaysInlineCost, 0, Reason, CostBenefit); } - static InlineCost getNever(const char *Reason) { - return InlineCost(NeverInlineCost, 0, Reason); + static InlineCost getNever(const char *Reason, + Optional CostBenefit = None) { + return InlineCost(NeverInlineCost, 0, Reason, CostBenefit); } /// Test whether the inline cost is low enough for inlining. @@ -116,6 +139,9 @@ return Threshold; } + /// Get the cost-benefit pair which was computed by cost-benefit analysis + Optional getCostBenefit() const { return CostBenefit; } + /// Get the reason of Always or Never. const char *getReason() const { assert((Reason || isVariable()) && 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 @@ -491,6 +491,9 @@ // Whether inlining is decided by cost-benefit analysis. bool DecidedByCostBenefit = false; + // The cost-benefit pair computed by cost-benefit analysis. + Optional CostBenefit = None; + bool SingleBB = true; unsigned SROACostSavings = 0; @@ -788,6 +791,8 @@ // savings threshold. Size = Size > InlineSizeAllowance ? Size - InlineSizeAllowance : 1; + CostBenefit.emplace(APInt(128, Size), CycleSavings); + // Return true if the savings justify the cost of inlining. Specifically, // we evaluate the following inequality: // @@ -935,6 +940,7 @@ virtual ~InlineCostCallAnalyzer() {} int getThreshold() { return Threshold; } int getCost() { return Cost; } + Optional getCostBenefitPair() { return CostBenefit; } bool wasDecidedByCostBenefit() { return DecidedByCostBenefit; } }; } // namespace @@ -2614,9 +2620,10 @@ // as it's not what drives cost-benefit analysis. if (CA.wasDecidedByCostBenefit()) { if (ShouldInline.isSuccess()) - return InlineCost::getAlways("benefit over cost"); + return InlineCost::getAlways("benefit over cost", + CA.getCostBenefitPair()); else - return InlineCost::getNever("cost over benefit"); + return InlineCost::getNever("cost over benefit", CA.getCostBenefitPair()); } // Check if there was a reason to force inlining or no inlining.