xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Analysis/InlineCost.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements heuristics for inlining decisions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_ANALYSIS_INLINECOST_H
14 #define LLVM_ANALYSIS_INLINECOST_H
15 
16 #include "llvm/ADT/APInt.h"
17 #include "llvm/ADT/STLFunctionalExtras.h"
18 #include "llvm/Analysis/InlineModelFeatureMaps.h"
19 #include "llvm/IR/PassManager.h"
20 #include "llvm/Support/Compiler.h"
21 #include <cassert>
22 #include <climits>
23 #include <optional>
24 
25 namespace llvm {
26 class AssumptionCache;
27 class OptimizationRemarkEmitter;
28 class BlockFrequencyInfo;
29 class CallBase;
30 class DataLayout;
31 class Function;
32 class ProfileSummaryInfo;
33 class TargetTransformInfo;
34 class TargetLibraryInfo;
35 class EphemeralValuesCache;
36 
37 namespace InlineConstants {
38 // Various thresholds used by inline cost analysis.
39 /// Use when optsize (-Os) is specified.
40 const int OptSizeThreshold = 50;
41 
42 /// Use when minsize (-Oz) is specified.
43 const int OptMinSizeThreshold = 5;
44 
45 /// Use when -O3 is specified.
46 const int OptAggressiveThreshold = 250;
47 
48 // Various magic constants used to adjust heuristics.
49 LLVM_ABI int getInstrCost();
50 const int IndirectCallThreshold = 100;
51 const int LoopPenalty = 25;
52 const int ColdccPenalty = 2000;
53 /// Do not inline functions which allocate this many bytes on the stack
54 /// when the caller is recursive.
55 const unsigned TotalAllocaSizeRecursiveCaller = 1024;
56 /// Do not inline dynamic allocas that have been constant propagated to be
57 /// static allocas above this amount in bytes.
58 const uint64_t MaxSimplifiedDynamicAllocaToInline = 65536;
59 
60 const char FunctionInlineCostMultiplierAttributeName[] =
61     "function-inline-cost-multiplier";
62 
63 const char MaxInlineStackSizeAttributeName[] = "inline-max-stacksize";
64 } // namespace InlineConstants
65 
66 // The cost-benefit pair computed by cost-benefit analysis.
67 class CostBenefitPair {
68 public:
CostBenefitPair(APInt Cost,APInt Benefit)69   CostBenefitPair(APInt Cost, APInt Benefit)
70       : Cost(std::move(Cost)), Benefit(std::move(Benefit)) {}
71 
getCost()72   const APInt &getCost() const { return Cost; }
73 
getBenefit()74   const APInt &getBenefit() const { return Benefit; }
75 
76 private:
77   APInt Cost;
78   APInt Benefit;
79 };
80 
81 /// Represents the cost of inlining a function.
82 ///
83 /// This supports special values for functions which should "always" or
84 /// "never" be inlined. Otherwise, the cost represents a unitless amount;
85 /// smaller values increase the likelihood of the function being inlined.
86 ///
87 /// Objects of this type also provide the adjusted threshold for inlining
88 /// based on the information available for a particular callsite. They can be
89 /// directly tested to determine if inlining should occur given the cost and
90 /// threshold for this cost metric.
91 class InlineCost {
92   enum SentinelValues { AlwaysInlineCost = INT_MIN, NeverInlineCost = INT_MAX };
93 
94   /// The estimated cost of inlining this callsite.
95   int Cost = 0;
96 
97   /// The adjusted threshold against which this cost was computed.
98   int Threshold = 0;
99 
100   /// The amount of StaticBonus that has been applied.
101   int StaticBonusApplied = 0;
102 
103   /// Must be set for Always and Never instances.
104   const char *Reason = nullptr;
105 
106   /// The cost-benefit pair computed by cost-benefit analysis.
107   std::optional<CostBenefitPair> CostBenefit;
108 
109   // Trivial constructor, interesting logic in the factory functions below.
110   InlineCost(int Cost, int Threshold, int StaticBonusApplied,
111              const char *Reason = nullptr,
112              std::optional<CostBenefitPair> CostBenefit = std::nullopt)
Cost(Cost)113       : Cost(Cost), Threshold(Threshold),
114         StaticBonusApplied(StaticBonusApplied), Reason(Reason),
115         CostBenefit(CostBenefit) {
116     assert((isVariable() || Reason) &&
117            "Reason must be provided for Never or Always");
118   }
119 
120 public:
121   static InlineCost get(int Cost, int Threshold, int StaticBonus = 0) {
122     assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
123     assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
124     return InlineCost(Cost, Threshold, StaticBonus);
125   }
126   static InlineCost
127   getAlways(const char *Reason,
128             std::optional<CostBenefitPair> CostBenefit = std::nullopt) {
129     return InlineCost(AlwaysInlineCost, 0, 0, Reason, CostBenefit);
130   }
131   static InlineCost
132   getNever(const char *Reason,
133            std::optional<CostBenefitPair> CostBenefit = std::nullopt) {
134     return InlineCost(NeverInlineCost, 0, 0, Reason, CostBenefit);
135   }
136 
137   /// Test whether the inline cost is low enough for inlining.
138   explicit operator bool() const { return Cost < Threshold; }
139 
isAlways()140   bool isAlways() const { return Cost == AlwaysInlineCost; }
isNever()141   bool isNever() const { return Cost == NeverInlineCost; }
isVariable()142   bool isVariable() const { return !isAlways() && !isNever(); }
143 
144   /// Get the inline cost estimate.
145   /// It is an error to call this on an "always" or "never" InlineCost.
getCost()146   int getCost() const {
147     assert(isVariable() && "Invalid access of InlineCost");
148     return Cost;
149   }
150 
151   /// Get the threshold against which the cost was computed
getThreshold()152   int getThreshold() const {
153     assert(isVariable() && "Invalid access of InlineCost");
154     return Threshold;
155   }
156 
157   /// Get the amount of StaticBonus applied.
getStaticBonusApplied()158   int getStaticBonusApplied() const {
159     assert(isVariable() && "Invalid access of InlineCost");
160     return StaticBonusApplied;
161   }
162 
163   /// Get the cost-benefit pair which was computed by cost-benefit analysis
getCostBenefit()164   std::optional<CostBenefitPair> getCostBenefit() const { return CostBenefit; }
165 
166   /// Get the reason of Always or Never.
getReason()167   const char *getReason() const {
168     assert((Reason || isVariable()) &&
169            "InlineCost reason must be set for Always or Never");
170     return Reason;
171   }
172 
173   /// Get the cost delta from the threshold for inlining.
174   /// Only valid if the cost is of the variable kind. Returns a negative
175   /// value if the cost is too high to inline.
getCostDelta()176   int getCostDelta() const { return Threshold - getCost(); }
177 };
178 
179 /// InlineResult is basically true or false. For false results the message
180 /// describes a reason.
181 class InlineResult {
182   const char *Message = nullptr;
Message(Message)183   InlineResult(const char *Message = nullptr) : Message(Message) {}
184 
185 public:
success()186   static InlineResult success() { return {}; }
failure(const char * Reason)187   static InlineResult failure(const char *Reason) {
188     return InlineResult(Reason);
189   }
isSuccess()190   bool isSuccess() const { return Message == nullptr; }
getFailureReason()191   const char *getFailureReason() const {
192     assert(!isSuccess() &&
193            "getFailureReason should only be called in failure cases");
194     return Message;
195   }
196 };
197 
198 /// Thresholds to tune inline cost analysis. The inline cost analysis decides
199 /// the condition to apply a threshold and applies it. Otherwise,
200 /// DefaultThreshold is used. If a threshold is Optional, it is applied only
201 /// when it has a valid value. Typically, users of inline cost analysis
202 /// obtain an InlineParams object through one of the \c getInlineParams methods
203 /// and pass it to \c getInlineCost. Some specialized versions of inliner
204 /// (such as the pre-inliner) might have custom logic to compute \c InlineParams
205 /// object.
206 
207 struct InlineParams {
208   /// The default threshold to start with for a callee.
209   int DefaultThreshold = -1;
210 
211   /// Threshold to use for callees with inline hint.
212   std::optional<int> HintThreshold;
213 
214   /// Threshold to use for cold callees.
215   std::optional<int> ColdThreshold;
216 
217   /// Threshold to use when the caller is optimized for size.
218   std::optional<int> OptSizeThreshold;
219 
220   /// Threshold to use when the caller is optimized for minsize.
221   std::optional<int> OptMinSizeThreshold;
222 
223   /// Threshold to use when the callsite is considered hot.
224   std::optional<int> HotCallSiteThreshold;
225 
226   /// Threshold to use when the callsite is considered hot relative to function
227   /// entry.
228   std::optional<int> LocallyHotCallSiteThreshold;
229 
230   /// Threshold to use when the callsite is considered cold.
231   std::optional<int> ColdCallSiteThreshold;
232 
233   /// Compute inline cost even when the cost has exceeded the threshold.
234   std::optional<bool> ComputeFullInlineCost;
235 
236   /// Indicate whether we should allow inline deferral.
237   std::optional<bool> EnableDeferral;
238 
239   /// Indicate whether we allow inlining for recursive call.
240   std::optional<bool> AllowRecursiveCall = false;
241 };
242 
243 LLVM_ABI std::optional<int> getStringFnAttrAsInt(CallBase &CB,
244                                                  StringRef AttrKind);
245 
246 /// Generate the parameters to tune the inline cost analysis based only on the
247 /// commandline options.
248 LLVM_ABI InlineParams getInlineParams();
249 
250 /// Generate the parameters to tune the inline cost analysis based on command
251 /// line options. If -inline-threshold option is not explicitly passed,
252 /// \p Threshold is used as the default threshold.
253 LLVM_ABI InlineParams getInlineParams(int Threshold);
254 
255 /// Generate the parameters to tune the inline cost analysis based on command
256 /// line options. If -inline-threshold option is not explicitly passed,
257 /// the default threshold is computed from \p OptLevel and \p SizeOptLevel.
258 /// An \p OptLevel value above 3 is considered an aggressive optimization mode.
259 /// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to
260 /// the -Oz flag.
261 LLVM_ABI InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
262 
263 /// Return the cost associated with a callsite, including parameter passing
264 /// and the call/return instruction.
265 LLVM_ABI int getCallsiteCost(const TargetTransformInfo &TTI,
266                              const CallBase &Call, const DataLayout &DL);
267 
268 /// Get an InlineCost object representing the cost of inlining this
269 /// callsite.
270 ///
271 /// Note that a default threshold is passed into this function. This threshold
272 /// could be modified based on callsite's properties and only costs below this
273 /// new threshold are computed with any accuracy. The new threshold can be
274 /// used to bound the computation necessary to determine whether the cost is
275 /// sufficiently low to warrant inlining.
276 ///
277 /// Also note that calling this function *dynamically* computes the cost of
278 /// inlining the callsite. It is an expensive, heavyweight call.
279 LLVM_ABI InlineCost getInlineCost(
280     CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI,
281     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
282     function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
283     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
284     ProfileSummaryInfo *PSI = nullptr, OptimizationRemarkEmitter *ORE = nullptr,
285     function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache =
286         nullptr);
287 
288 /// Get an InlineCost with the callee explicitly specified.
289 /// This allows you to calculate the cost of inlining a function via a
290 /// pointer. This behaves exactly as the version with no explicit callee
291 /// parameter in all other respects.
292 //
293 LLVM_ABI InlineCost getInlineCost(
294     CallBase &Call, Function *Callee, const InlineParams &Params,
295     TargetTransformInfo &CalleeTTI,
296     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
297     function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
298     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
299     ProfileSummaryInfo *PSI = nullptr, OptimizationRemarkEmitter *ORE = nullptr,
300     function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache =
301         nullptr);
302 
303 /// Returns InlineResult::success() if the call site should be always inlined
304 /// because of user directives, and the inlining is viable. Returns
305 /// InlineResult::failure() if the inlining may never happen because of user
306 /// directives or incompatibilities detectable without needing callee traversal.
307 /// Otherwise returns std::nullopt, meaning that inlining should be decided
308 /// based on other criteria (e.g. cost modeling).
309 LLVM_ABI std::optional<InlineResult> getAttributeBasedInliningDecision(
310     CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
311     function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
312 
313 /// Get the cost estimate ignoring thresholds. This is similar to getInlineCost
314 /// when passed InlineParams::ComputeFullInlineCost, or a non-null ORE. It
315 /// uses default InlineParams otherwise.
316 /// Contrary to getInlineCost, which makes a threshold-based final evaluation of
317 /// should/shouldn't inline, captured in InlineResult, getInliningCostEstimate
318 /// returns:
319 /// - std::nullopt, if the inlining cannot happen (is illegal)
320 /// - an integer, representing the cost.
321 LLVM_ABI std::optional<int> getInliningCostEstimate(
322     CallBase &Call, TargetTransformInfo &CalleeTTI,
323     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
324     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
325     function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
326     ProfileSummaryInfo *PSI = nullptr,
327     OptimizationRemarkEmitter *ORE = nullptr);
328 
329 /// Get the expanded cost features. The features are returned unconditionally,
330 /// even if inlining is impossible.
331 LLVM_ABI std::optional<InlineCostFeatures> getInliningCostFeatures(
332     CallBase &Call, TargetTransformInfo &CalleeTTI,
333     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
334     function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
335     function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
336     ProfileSummaryInfo *PSI = nullptr,
337     OptimizationRemarkEmitter *ORE = nullptr);
338 
339 /// Minimal filter to detect invalid constructs for inlining.
340 LLVM_ABI InlineResult isInlineViable(Function &Callee);
341 
342 // This pass is used to annotate instructions during the inline process for
343 // debugging and analysis. The main purpose of the pass is to see and test
344 // inliner's decisions when creating new optimizations to InlineCost.
345 struct InlineCostAnnotationPrinterPass
346     : PassInfoMixin<InlineCostAnnotationPrinterPass> {
347   raw_ostream &OS;
348 
349 public:
InlineCostAnnotationPrinterPassInlineCostAnnotationPrinterPass350   explicit InlineCostAnnotationPrinterPass(raw_ostream &OS) : OS(OS) {}
351   LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
isRequiredInlineCostAnnotationPrinterPass352   static bool isRequired() { return true; }
353 };
354 } // namespace llvm
355 
356 #endif
357