Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:13

0001 //===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file implements heuristics for inlining decisions.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_ANALYSIS_INLINECOST_H
0014 #define LLVM_ANALYSIS_INLINECOST_H
0015 
0016 #include "llvm/ADT/APInt.h"
0017 #include "llvm/ADT/STLFunctionalExtras.h"
0018 #include "llvm/Analysis/InlineModelFeatureMaps.h"
0019 #include "llvm/IR/PassManager.h"
0020 #include <cassert>
0021 #include <climits>
0022 #include <optional>
0023 
0024 namespace llvm {
0025 class AssumptionCache;
0026 class OptimizationRemarkEmitter;
0027 class BlockFrequencyInfo;
0028 class CallBase;
0029 class DataLayout;
0030 class Function;
0031 class ProfileSummaryInfo;
0032 class TargetTransformInfo;
0033 class TargetLibraryInfo;
0034 
0035 namespace InlineConstants {
0036 // Various thresholds used by inline cost analysis.
0037 /// Use when optsize (-Os) is specified.
0038 const int OptSizeThreshold = 50;
0039 
0040 /// Use when minsize (-Oz) is specified.
0041 const int OptMinSizeThreshold = 5;
0042 
0043 /// Use when -O3 is specified.
0044 const int OptAggressiveThreshold = 250;
0045 
0046 // Various magic constants used to adjust heuristics.
0047 int getInstrCost();
0048 const int IndirectCallThreshold = 100;
0049 const int LoopPenalty = 25;
0050 const int ColdccPenalty = 2000;
0051 /// Do not inline functions which allocate this many bytes on the stack
0052 /// when the caller is recursive.
0053 const unsigned TotalAllocaSizeRecursiveCaller = 1024;
0054 /// Do not inline dynamic allocas that have been constant propagated to be
0055 /// static allocas above this amount in bytes.
0056 const uint64_t MaxSimplifiedDynamicAllocaToInline = 65536;
0057 
0058 const char FunctionInlineCostMultiplierAttributeName[] =
0059     "function-inline-cost-multiplier";
0060 
0061 const char MaxInlineStackSizeAttributeName[] = "inline-max-stacksize";
0062 } // namespace InlineConstants
0063 
0064 // The cost-benefit pair computed by cost-benefit analysis.
0065 class CostBenefitPair {
0066 public:
0067   CostBenefitPair(APInt Cost, APInt Benefit)
0068       : Cost(std::move(Cost)), Benefit(std::move(Benefit)) {}
0069 
0070   const APInt &getCost() const { return Cost; }
0071 
0072   const APInt &getBenefit() const { return Benefit; }
0073 
0074 private:
0075   APInt Cost;
0076   APInt Benefit;
0077 };
0078 
0079 /// Represents the cost of inlining a function.
0080 ///
0081 /// This supports special values for functions which should "always" or
0082 /// "never" be inlined. Otherwise, the cost represents a unitless amount;
0083 /// smaller values increase the likelihood of the function being inlined.
0084 ///
0085 /// Objects of this type also provide the adjusted threshold for inlining
0086 /// based on the information available for a particular callsite. They can be
0087 /// directly tested to determine if inlining should occur given the cost and
0088 /// threshold for this cost metric.
0089 class InlineCost {
0090   enum SentinelValues { AlwaysInlineCost = INT_MIN, NeverInlineCost = INT_MAX };
0091 
0092   /// The estimated cost of inlining this callsite.
0093   int Cost = 0;
0094 
0095   /// The adjusted threshold against which this cost was computed.
0096   int Threshold = 0;
0097 
0098   /// The amount of StaticBonus that has been applied.
0099   int StaticBonusApplied = 0;
0100 
0101   /// Must be set for Always and Never instances.
0102   const char *Reason = nullptr;
0103 
0104   /// The cost-benefit pair computed by cost-benefit analysis.
0105   std::optional<CostBenefitPair> CostBenefit;
0106 
0107   // Trivial constructor, interesting logic in the factory functions below.
0108   InlineCost(int Cost, int Threshold, int StaticBonusApplied,
0109              const char *Reason = nullptr,
0110              std::optional<CostBenefitPair> CostBenefit = std::nullopt)
0111       : Cost(Cost), Threshold(Threshold),
0112         StaticBonusApplied(StaticBonusApplied), Reason(Reason),
0113         CostBenefit(CostBenefit) {
0114     assert((isVariable() || Reason) &&
0115            "Reason must be provided for Never or Always");
0116   }
0117 
0118 public:
0119   static InlineCost get(int Cost, int Threshold, int StaticBonus = 0) {
0120     assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
0121     assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
0122     return InlineCost(Cost, Threshold, StaticBonus);
0123   }
0124   static InlineCost
0125   getAlways(const char *Reason,
0126             std::optional<CostBenefitPair> CostBenefit = std::nullopt) {
0127     return InlineCost(AlwaysInlineCost, 0, 0, Reason, CostBenefit);
0128   }
0129   static InlineCost
0130   getNever(const char *Reason,
0131            std::optional<CostBenefitPair> CostBenefit = std::nullopt) {
0132     return InlineCost(NeverInlineCost, 0, 0, Reason, CostBenefit);
0133   }
0134 
0135   /// Test whether the inline cost is low enough for inlining.
0136   explicit operator bool() const { return Cost < Threshold; }
0137 
0138   bool isAlways() const { return Cost == AlwaysInlineCost; }
0139   bool isNever() const { return Cost == NeverInlineCost; }
0140   bool isVariable() const { return !isAlways() && !isNever(); }
0141 
0142   /// Get the inline cost estimate.
0143   /// It is an error to call this on an "always" or "never" InlineCost.
0144   int getCost() const {
0145     assert(isVariable() && "Invalid access of InlineCost");
0146     return Cost;
0147   }
0148 
0149   /// Get the threshold against which the cost was computed
0150   int getThreshold() const {
0151     assert(isVariable() && "Invalid access of InlineCost");
0152     return Threshold;
0153   }
0154 
0155   /// Get the amount of StaticBonus applied.
0156   int getStaticBonusApplied() const {
0157     assert(isVariable() && "Invalid access of InlineCost");
0158     return StaticBonusApplied;
0159   }
0160 
0161   /// Get the cost-benefit pair which was computed by cost-benefit analysis
0162   std::optional<CostBenefitPair> getCostBenefit() const { return CostBenefit; }
0163 
0164   /// Get the reason of Always or Never.
0165   const char *getReason() const {
0166     assert((Reason || isVariable()) &&
0167            "InlineCost reason must be set for Always or Never");
0168     return Reason;
0169   }
0170 
0171   /// Get the cost delta from the threshold for inlining.
0172   /// Only valid if the cost is of the variable kind. Returns a negative
0173   /// value if the cost is too high to inline.
0174   int getCostDelta() const { return Threshold - getCost(); }
0175 };
0176 
0177 /// InlineResult is basically true or false. For false results the message
0178 /// describes a reason.
0179 class InlineResult {
0180   const char *Message = nullptr;
0181   InlineResult(const char *Message = nullptr) : Message(Message) {}
0182 
0183 public:
0184   static InlineResult success() { return {}; }
0185   static InlineResult failure(const char *Reason) {
0186     return InlineResult(Reason);
0187   }
0188   bool isSuccess() const { return Message == nullptr; }
0189   const char *getFailureReason() const {
0190     assert(!isSuccess() &&
0191            "getFailureReason should only be called in failure cases");
0192     return Message;
0193   }
0194 };
0195 
0196 /// Thresholds to tune inline cost analysis. The inline cost analysis decides
0197 /// the condition to apply a threshold and applies it. Otherwise,
0198 /// DefaultThreshold is used. If a threshold is Optional, it is applied only
0199 /// when it has a valid value. Typically, users of inline cost analysis
0200 /// obtain an InlineParams object through one of the \c getInlineParams methods
0201 /// and pass it to \c getInlineCost. Some specialized versions of inliner
0202 /// (such as the pre-inliner) might have custom logic to compute \c InlineParams
0203 /// object.
0204 
0205 struct InlineParams {
0206   /// The default threshold to start with for a callee.
0207   int DefaultThreshold = -1;
0208 
0209   /// Threshold to use for callees with inline hint.
0210   std::optional<int> HintThreshold;
0211 
0212   /// Threshold to use for cold callees.
0213   std::optional<int> ColdThreshold;
0214 
0215   /// Threshold to use when the caller is optimized for size.
0216   std::optional<int> OptSizeThreshold;
0217 
0218   /// Threshold to use when the caller is optimized for minsize.
0219   std::optional<int> OptMinSizeThreshold;
0220 
0221   /// Threshold to use when the callsite is considered hot.
0222   std::optional<int> HotCallSiteThreshold;
0223 
0224   /// Threshold to use when the callsite is considered hot relative to function
0225   /// entry.
0226   std::optional<int> LocallyHotCallSiteThreshold;
0227 
0228   /// Threshold to use when the callsite is considered cold.
0229   std::optional<int> ColdCallSiteThreshold;
0230 
0231   /// Compute inline cost even when the cost has exceeded the threshold.
0232   std::optional<bool> ComputeFullInlineCost;
0233 
0234   /// Indicate whether we should allow inline deferral.
0235   std::optional<bool> EnableDeferral;
0236 
0237   /// Indicate whether we allow inlining for recursive call.
0238   std::optional<bool> AllowRecursiveCall = false;
0239 };
0240 
0241 std::optional<int> getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind);
0242 
0243 /// Generate the parameters to tune the inline cost analysis based only on the
0244 /// commandline options.
0245 InlineParams getInlineParams();
0246 
0247 /// Generate the parameters to tune the inline cost analysis based on command
0248 /// line options. If -inline-threshold option is not explicitly passed,
0249 /// \p Threshold is used as the default threshold.
0250 InlineParams getInlineParams(int Threshold);
0251 
0252 /// Generate the parameters to tune the inline cost analysis based on command
0253 /// line options. If -inline-threshold option is not explicitly passed,
0254 /// the default threshold is computed from \p OptLevel and \p SizeOptLevel.
0255 /// An \p OptLevel value above 3 is considered an aggressive optimization mode.
0256 /// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to
0257 /// the -Oz flag.
0258 InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
0259 
0260 /// Return the cost associated with a callsite, including parameter passing
0261 /// and the call/return instruction.
0262 int getCallsiteCost(const TargetTransformInfo &TTI, const CallBase &Call,
0263                     const DataLayout &DL);
0264 
0265 /// Get an InlineCost object representing the cost of inlining this
0266 /// callsite.
0267 ///
0268 /// Note that a default threshold is passed into this function. This threshold
0269 /// could be modified based on callsite's properties and only costs below this
0270 /// new threshold are computed with any accuracy. The new threshold can be
0271 /// used to bound the computation necessary to determine whether the cost is
0272 /// sufficiently low to warrant inlining.
0273 ///
0274 /// Also note that calling this function *dynamically* computes the cost of
0275 /// inlining the callsite. It is an expensive, heavyweight call.
0276 InlineCost
0277 getInlineCost(CallBase &Call, const InlineParams &Params,
0278               TargetTransformInfo &CalleeTTI,
0279               function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
0280               function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
0281               function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
0282               ProfileSummaryInfo *PSI = nullptr,
0283               OptimizationRemarkEmitter *ORE = nullptr);
0284 
0285 /// Get an InlineCost with the callee explicitly specified.
0286 /// This allows you to calculate the cost of inlining a function via a
0287 /// pointer. This behaves exactly as the version with no explicit callee
0288 /// parameter in all other respects.
0289 //
0290 InlineCost
0291 getInlineCost(CallBase &Call, Function *Callee, const InlineParams &Params,
0292               TargetTransformInfo &CalleeTTI,
0293               function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
0294               function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
0295               function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
0296               ProfileSummaryInfo *PSI = nullptr,
0297               OptimizationRemarkEmitter *ORE = nullptr);
0298 
0299 /// Returns InlineResult::success() if the call site should be always inlined
0300 /// because of user directives, and the inlining is viable. Returns
0301 /// InlineResult::failure() if the inlining may never happen because of user
0302 /// directives or incompatibilities detectable without needing callee traversal.
0303 /// Otherwise returns std::nullopt, meaning that inlining should be decided
0304 /// based on other criteria (e.g. cost modeling).
0305 std::optional<InlineResult> getAttributeBasedInliningDecision(
0306     CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
0307     function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
0308 
0309 /// Get the cost estimate ignoring thresholds. This is similar to getInlineCost
0310 /// when passed InlineParams::ComputeFullInlineCost, or a non-null ORE. It
0311 /// uses default InlineParams otherwise.
0312 /// Contrary to getInlineCost, which makes a threshold-based final evaluation of
0313 /// should/shouldn't inline, captured in InlineResult, getInliningCostEstimate
0314 /// returns:
0315 /// - std::nullopt, if the inlining cannot happen (is illegal)
0316 /// - an integer, representing the cost.
0317 std::optional<int> getInliningCostEstimate(
0318     CallBase &Call, TargetTransformInfo &CalleeTTI,
0319     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
0320     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
0321     function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
0322     ProfileSummaryInfo *PSI = nullptr,
0323     OptimizationRemarkEmitter *ORE = nullptr);
0324 
0325 /// Get the expanded cost features. The features are returned unconditionally,
0326 /// even if inlining is impossible.
0327 std::optional<InlineCostFeatures> getInliningCostFeatures(
0328     CallBase &Call, TargetTransformInfo &CalleeTTI,
0329     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
0330     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
0331     function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
0332     ProfileSummaryInfo *PSI = nullptr,
0333     OptimizationRemarkEmitter *ORE = nullptr);
0334 
0335 /// Minimal filter to detect invalid constructs for inlining.
0336 InlineResult isInlineViable(Function &Callee);
0337 
0338 // This pass is used to annotate instructions during the inline process for
0339 // debugging and analysis. The main purpose of the pass is to see and test
0340 // inliner's decisions when creating new optimizations to InlineCost.
0341 struct InlineCostAnnotationPrinterPass
0342     : PassInfoMixin<InlineCostAnnotationPrinterPass> {
0343   raw_ostream &OS;
0344 
0345 public:
0346   explicit InlineCostAnnotationPrinterPass(raw_ostream &OS) : OS(OS) {}
0347   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
0348   static bool isRequired() { return true; }
0349 };
0350 } // namespace llvm
0351 
0352 #endif