@@ -173,6 +173,11 @@ static cl::opt<bool> DisableGEPConstOperand(
173173 " disable-gep-const-evaluation" , cl::Hidden, cl::init(false ),
174174 cl::desc(" Disables evaluation of GetElementPtr with constant operands" ));
175175
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+
176181namespace llvm {
177182std::optional<int > getStringFnAttrAsInt (const Attribute &Attr) {
178183 if (Attr.isValid ()) {
@@ -269,6 +274,10 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
269274 // / easily cacheable. Instead, use the cover function paramHasAttr.
270275 CallBase &CandidateCall;
271276
277+ // / Collecting the ephemeral values over and over again can be expensive, so
278+ // / cache them.
279+ EphValuesCacheT *EphValuesCache;
280+
272281 // / Extension points for handling callsite features.
273282 // Called before a basic block was analyzed.
274283 virtual void onBlockStart (const BasicBlock *BB) {}
@@ -510,10 +519,11 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
510519 function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
511520 function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
512521 ProfileSummaryInfo *PSI = nullptr ,
513- OptimizationRemarkEmitter *ORE = nullptr )
522+ OptimizationRemarkEmitter *ORE = nullptr ,
523+ EphValuesCacheT *EphValuesCache = nullptr )
514524 : TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI),
515525 GetTLI (GetTLI), PSI(PSI), F(Callee), DL(F.getDataLayout()), ORE(ORE),
516- CandidateCall(Call) {}
526+ CandidateCall(Call), EphValuesCache(EphValuesCache) {}
517527
518528 InlineResult analyze ();
519529
@@ -1126,9 +1136,9 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
11261136 function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
11271137 ProfileSummaryInfo *PSI = nullptr ,
11281138 OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
1129- bool IgnoreThreshold = false )
1139+ bool IgnoreThreshold = false , EphValuesCacheT *EphValuesCache = nullptr )
11301140 : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1131- ORE),
1141+ ORE, EphValuesCache ),
11321142 ComputeFullInlineCost (OptComputeFullInlineCost ||
11331143 Params.ComputeFullInlineCost || ORE ||
11341144 isCostBenefitAnalysisEnabled ()),
@@ -2781,11 +2791,27 @@ InlineResult CallAnalyzer::analyze() {
27812791 NumConstantOffsetPtrArgs = ConstantOffsetPtrs.size ();
27822792 NumAllocaArgs = SROAArgValues.size ();
27832793
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+ }
27892815
27902816 // The worklist of live basic blocks in the callee *after* inlining. We avoid
27912817 // adding basic blocks of the callee which can be proven to be dead for this
@@ -2824,7 +2850,7 @@ InlineResult CallAnalyzer::analyze() {
28242850
28252851 // Analyze the cost of this block. If we blow through the threshold, this
28262852 // returns false, and we can bail on out.
2827- InlineResult IR = analyzeBlock (BB, EphValues);
2853+ InlineResult IR = analyzeBlock (BB, * EphValues);
28282854 if (!IR.isSuccess ())
28292855 return IR;
28302856
@@ -2967,9 +2993,11 @@ InlineCost llvm::getInlineCost(
29672993 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
29682994 function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
29692995 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2970- ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2996+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
2997+ EphValuesCacheT *EphValuesCache) {
29712998 return getInlineCost (Call, Call.getCalledFunction (), Params, CalleeTTI,
2972- GetAssumptionCache, GetTLI, GetBFI, PSI, ORE);
2999+ GetAssumptionCache, GetTLI, GetBFI, PSI, ORE,
3000+ EphValuesCache);
29733001}
29743002
29753003std::optional<int > llvm::getInliningCostEstimate (
@@ -3089,7 +3117,8 @@ InlineCost llvm::getInlineCost(
30893117 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
30903118 function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
30913119 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3092- ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
3120+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
3121+ EphValuesCacheT *EphValuesCache) {
30933122
30943123 auto UserDecision =
30953124 llvm::getAttributeBasedInliningDecision (Call, Callee, CalleeTTI, GetTLI);
@@ -3105,7 +3134,9 @@ InlineCost llvm::getInlineCost(
31053134 << " )\n " );
31063135
31073136 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);
31093140 InlineResult ShouldInline = CA.analyze ();
31103141
31113142 LLVM_DEBUG (CA.dump ());
0 commit comments