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 @@ -236,6 +236,15 @@ function_ref GetTLI, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE); +/// 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. +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 @@ -407,7 +407,8 @@ /// FIXME: if it is necessary to derive from InlineCostCallAnalyzer, note /// the FIXME in onLoweredCall, when instantiating an InlineCostCallAnalyzer -class InlineCostCallAnalyzer final : public CallAnalyzer { +class InlineCostCallAnalyzer : public CallAnalyzer { +protected: const int CostUpperBound = INT_MAX - InlineConstants::InstrCost - 1; const bool ComputeFullInlineCost; int LoadEliminationCost = 0; @@ -710,6 +711,58 @@ int getThreshold() { return Threshold; } int getCost() { return Cost; } }; + +/// Calculate inline cost irrespective of thresholds. +class CompleteInlineCostAnalyzer final : public InlineCostCallAnalyzer { +public: + CompleteInlineCostAnalyzer( + const TargetTransformInfo &TTI, + std::function &GetAssumptionCache, + Optional> &GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee, + CallBase &Call, + const InlineParams Params = {/* DefaultThreshold*/ 0, + /*HintThreshold*/ {}, + /*ColdThreshold*/ {}, + /*OptSizeThreshold*/ {}, + /*OptMinSizeThreshold*/ {}, + /*HotCallSiteThreshold*/ {}, + /*LocallyHotCallSiteThreshold*/ {}, + /*ColdCallSiteThreshold*/ {}, + /* ComputeFullInlineCost*/ true}, + bool BoostIndirect = true) + : InlineCostCallAnalyzer(TTI, GetAssumptionCache, GetBFI, PSI, ORE, + Callee, Call, Params, BoostIndirect) {} + + // Ignore parent's result, and just return success. + InlineResult finalizeAnalysis() override { + InlineCostCallAnalyzer::finalizeAnalysis(); + return InlineResult::success(); + } + + // Same as parent's onLoweredCall, just that it uses itself internally. Not + // worth doing something more elegant, because this implementation will go + // away. + void onLoweredCall(Function *F, CallBase &Call, + bool IsIndirectCall) override { + addCost(Call.arg_size() * InlineConstants::InstrCost); + + if (IsIndirectCall && BoostIndirectCalls) { + auto IndirectCallParams = Params; + IndirectCallParams.DefaultThreshold = + InlineConstants::IndirectCallThreshold; + CompleteInlineCostAnalyzer CA(TTI, GetAssumptionCache, GetBFI, PSI, ORE, + *F, Call, IndirectCallParams, false); + if (CA.analyze().isSuccess()) { + // We were able to inline the indirect call! Subtract the cost from the + // threshold to get the bonus we want to apply, but don't go below zero. + Cost -= std::max(0, CA.getThreshold() - CA.getCost()); + } + } else + // Otherwise simply add the cost for merely making the call. + addCost(InlineConstants::CallPenalty); + } +}; } // namespace /// Test whether the given value is an Alloca-derived function argument. @@ -2215,6 +2268,19 @@ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE); } +Optional llvm::getInliningCostEstimate( + CallBase &Call, TargetTransformInfo &CalleeTTI, + std::function &GetAssumptionCache, + Optional> GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) { + CompleteInlineCostAnalyzer CA(CalleeTTI, GetAssumptionCache, GetBFI, PSI, ORE, + *Call.getCalledFunction(), Call); + auto R = CA.analyze(); + if (!R.isSuccess()) + return llvm::None; + return CA.getCost(); +} + InlineCost llvm::getInlineCost( CallBase &Call, Function *Callee, const InlineParams &Params, TargetTransformInfo &CalleeTTI,