File indexing completed on 2026-05-10 08:43:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0037
0038 const int OptSizeThreshold = 50;
0039
0040
0041 const int OptMinSizeThreshold = 5;
0042
0043
0044 const int OptAggressiveThreshold = 250;
0045
0046
0047 int getInstrCost();
0048 const int IndirectCallThreshold = 100;
0049 const int LoopPenalty = 25;
0050 const int ColdccPenalty = 2000;
0051
0052
0053 const unsigned TotalAllocaSizeRecursiveCaller = 1024;
0054
0055
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 }
0063
0064
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
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 class InlineCost {
0090 enum SentinelValues { AlwaysInlineCost = INT_MIN, NeverInlineCost = INT_MAX };
0091
0092
0093 int Cost = 0;
0094
0095
0096 int Threshold = 0;
0097
0098
0099 int StaticBonusApplied = 0;
0100
0101
0102 const char *Reason = nullptr;
0103
0104
0105 std::optional<CostBenefitPair> CostBenefit;
0106
0107
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
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
0143
0144 int getCost() const {
0145 assert(isVariable() && "Invalid access of InlineCost");
0146 return Cost;
0147 }
0148
0149
0150 int getThreshold() const {
0151 assert(isVariable() && "Invalid access of InlineCost");
0152 return Threshold;
0153 }
0154
0155
0156 int getStaticBonusApplied() const {
0157 assert(isVariable() && "Invalid access of InlineCost");
0158 return StaticBonusApplied;
0159 }
0160
0161
0162 std::optional<CostBenefitPair> getCostBenefit() const { return CostBenefit; }
0163
0164
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
0172
0173
0174 int getCostDelta() const { return Threshold - getCost(); }
0175 };
0176
0177
0178
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
0197
0198
0199
0200
0201
0202
0203
0204
0205 struct InlineParams {
0206
0207 int DefaultThreshold = -1;
0208
0209
0210 std::optional<int> HintThreshold;
0211
0212
0213 std::optional<int> ColdThreshold;
0214
0215
0216 std::optional<int> OptSizeThreshold;
0217
0218
0219 std::optional<int> OptMinSizeThreshold;
0220
0221
0222 std::optional<int> HotCallSiteThreshold;
0223
0224
0225
0226 std::optional<int> LocallyHotCallSiteThreshold;
0227
0228
0229 std::optional<int> ColdCallSiteThreshold;
0230
0231
0232 std::optional<bool> ComputeFullInlineCost;
0233
0234
0235 std::optional<bool> EnableDeferral;
0236
0237
0238 std::optional<bool> AllowRecursiveCall = false;
0239 };
0240
0241 std::optional<int> getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind);
0242
0243
0244
0245 InlineParams getInlineParams();
0246
0247
0248
0249
0250 InlineParams getInlineParams(int Threshold);
0251
0252
0253
0254
0255
0256
0257
0258 InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
0259
0260
0261
0262 int getCallsiteCost(const TargetTransformInfo &TTI, const CallBase &Call,
0263 const DataLayout &DL);
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
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
0286
0287
0288
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
0300
0301
0302
0303
0304
0305 std::optional<InlineResult> getAttributeBasedInliningDecision(
0306 CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
0307 function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
0308
0309
0310
0311
0312
0313
0314
0315
0316
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
0326
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
0336 InlineResult isInlineViable(Function &Callee);
0337
0338
0339
0340
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 }
0351
0352 #endif