@@ -173,6 +173,11 @@ static cl::opt<bool> DisableGEPConstOperand(
173
173
" disable-gep-const-evaluation" , cl::Hidden, cl::init(false ),
174
174
cl::desc(" Disables evaluation of GetElementPtr with constant operands" ));
175
175
176
+ static cl::opt<unsigned > EphValuesCacheSizeLimit (
177
+ " inline-ephvalues-cache-size-limit" , cl::Hidden, cl::init(8 ),
178
+ cl::desc(
179
+ " Clear the cache of ephemeral values if it grows larger than this" ));
180
+
176
181
namespace llvm {
177
182
std::optional<int > getStringFnAttrAsInt (const Attribute &Attr) {
178
183
if (Attr.isValid ()) {
@@ -269,6 +274,10 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
269
274
// / easily cacheable. Instead, use the cover function paramHasAttr.
270
275
CallBase &CandidateCall;
271
276
277
+ // / Collecting the ephemeral values over and over again can be expensive, so
278
+ // / cache them.
279
+ EphValuesCacheT *EphValuesCache;
280
+
272
281
// / Extension points for handling callsite features.
273
282
// Called before a basic block was analyzed.
274
283
virtual void onBlockStart (const BasicBlock *BB) {}
@@ -510,10 +519,11 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
510
519
function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
511
520
function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
512
521
ProfileSummaryInfo *PSI = nullptr ,
513
- OptimizationRemarkEmitter *ORE = nullptr )
522
+ OptimizationRemarkEmitter *ORE = nullptr ,
523
+ EphValuesCacheT *EphValuesCache = nullptr )
514
524
: TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI),
515
525
GetTLI (GetTLI), PSI(PSI), F(Callee), DL(F.getDataLayout()), ORE(ORE),
516
- CandidateCall(Call) {}
526
+ CandidateCall(Call), EphValuesCache(EphValuesCache) {}
517
527
518
528
InlineResult analyze ();
519
529
@@ -1126,9 +1136,9 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
1126
1136
function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
1127
1137
ProfileSummaryInfo *PSI = nullptr ,
1128
1138
OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
1129
- bool IgnoreThreshold = false )
1139
+ bool IgnoreThreshold = false , EphValuesCacheT *EphValuesCache = nullptr )
1130
1140
: CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1131
- ORE),
1141
+ ORE, EphValuesCache ),
1132
1142
ComputeFullInlineCost (OptComputeFullInlineCost ||
1133
1143
Params.ComputeFullInlineCost || ORE ||
1134
1144
isCostBenefitAnalysisEnabled ()),
@@ -2781,11 +2791,27 @@ InlineResult CallAnalyzer::analyze() {
2781
2791
NumConstantOffsetPtrArgs = ConstantOffsetPtrs.size ();
2782
2792
NumAllocaArgs = SROAArgValues.size ();
2783
2793
2784
- // FIXME: If a caller has multiple calls to a callee, we end up recomputing
2785
- // the ephemeral values multiple times (and they're completely determined by
2786
- // the callee, so this is purely duplicate work).
2787
- SmallPtrSet<const Value *, 32 > EphValues;
2788
- CodeMetrics::collectEphemeralValues (&F, &GetAssumptionCache (F), EphValues);
2794
+ // Collecting the ephemeral values of `F` can be expensive, so collect them
2795
+ // once per function and cache them for future reuse.
2796
+ SmallPtrSet<const Value *, 32 > EphValuesSet;
2797
+ SmallPtrSet<const Value *, 32 > *EphValues;
2798
+ auto &AC = GetAssumptionCache (F);
2799
+ if (EphValuesCache == nullptr ) {
2800
+ // No cache is being used, so collect the values every time.
2801
+ CodeMetrics::collectEphemeralValues (&F, &AC, EphValuesSet);
2802
+ EphValues = &EphValuesSet;
2803
+ } else {
2804
+ // If the ephemeral values for `F` are in the cache, then reuse them. Else
2805
+ // collect them from scratch.
2806
+ if (EphValuesCache->size () >= EphValuesCacheSizeLimit)
2807
+ // If the cache grows larger than a limit remove the first element.
2808
+ // NOTE: This is a linear-time operation so keep the cache size small!
2809
+ EphValuesCache->erase (EphValuesCache->begin ()->first );
2810
+ auto Pair = EphValuesCache->insert ({&F, {}});
2811
+ if (Pair.second )
2812
+ CodeMetrics::collectEphemeralValues (&F, &AC, Pair.first ->second );
2813
+ EphValues = &Pair.first ->second ;
2814
+ }
2789
2815
2790
2816
// The worklist of live basic blocks in the callee *after* inlining. We avoid
2791
2817
// adding basic blocks of the callee which can be proven to be dead for this
@@ -2824,7 +2850,7 @@ InlineResult CallAnalyzer::analyze() {
2824
2850
2825
2851
// Analyze the cost of this block. If we blow through the threshold, this
2826
2852
// returns false, and we can bail on out.
2827
- InlineResult IR = analyzeBlock (BB, EphValues);
2853
+ InlineResult IR = analyzeBlock (BB, * EphValues);
2828
2854
if (!IR.isSuccess ())
2829
2855
return IR;
2830
2856
@@ -2967,9 +2993,11 @@ InlineCost llvm::getInlineCost(
2967
2993
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
2968
2994
function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
2969
2995
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2970
- ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2996
+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
2997
+ EphValuesCacheT *EphValuesCache) {
2971
2998
return getInlineCost (Call, Call.getCalledFunction (), Params, CalleeTTI,
2972
- GetAssumptionCache, GetTLI, GetBFI, PSI, ORE);
2999
+ GetAssumptionCache, GetTLI, GetBFI, PSI, ORE,
3000
+ EphValuesCache);
2973
3001
}
2974
3002
2975
3003
std::optional<int > llvm::getInliningCostEstimate (
@@ -3089,7 +3117,8 @@ InlineCost llvm::getInlineCost(
3089
3117
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
3090
3118
function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
3091
3119
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3092
- ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
3120
+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
3121
+ EphValuesCacheT *EphValuesCache) {
3093
3122
3094
3123
auto UserDecision =
3095
3124
llvm::getAttributeBasedInliningDecision (Call, Callee, CalleeTTI, GetTLI);
@@ -3105,7 +3134,9 @@ InlineCost llvm::getInlineCost(
3105
3134
<< " )\n " );
3106
3135
3107
3136
InlineCostCallAnalyzer CA (*Callee, Call, Params, CalleeTTI,
3108
- GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
3137
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
3138
+ /* BoostIndirect=*/ true , /* IgnoreThreshold=*/ false ,
3139
+ EphValuesCache);
3109
3140
InlineResult ShouldInline = CA.analyze ();
3110
3141
3111
3142
LLVM_DEBUG (CA.dump ());
0 commit comments