Skip to content

[InlineCost] Don't call collectEphemeralValues() if too many assumptions #129279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

vporpo
Copy link
Contributor

@vporpo vporpo commented Feb 28, 2025

CallAnalyzer::analyze() can take several hours to run if the function contains thousands of @llvm.assume() calls and there are thousands of callsites. The time is spent in collectEphemeralvalues(). This patch adds a check that disables the collection of ephemeral values if there are more assumptions than a limit controlled by the -inline-ephval-assumptions-limit flag. Disabling the collection of ephemeral values will increase the function cost, making it less likely to be inlined, but if there are too many calls to @llvm.assume() then the chances are that the function will be too big to inline anyway.

CallAnalyzer::analyze() can take several hours to run if the function
contains thousands of @llvm.assume() calls. The time is spent in
collectEphemeralvalues(). This patch adds a check that will disables
the collection of ephemeral values if there are more assumptions than
a limit controlled by the `-inline-ephval-assumptions-limit` flag.
@vporpo vporpo requested review from rnk and aeubanks February 28, 2025 18:10
@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Feb 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 28, 2025

@llvm/pr-subscribers-llvm-analysis

Author: vporpo (vporpo)

Changes

CallAnalyzer::analyze() can take several hours to run if the function contains thousands of @llvm.assume() calls and there are thousands of callsites. The time is spent in collectEphemeralvalues(). This patch adds a check that disables the collection of ephemeral values if there are more assumptions than a limit controlled by the -inline-ephval-assumptions-limit flag. Disabling the collection of ephemeral values will increase the function cost, making it less likely to be inlined, but if there are too many calls to @<!-- -->llvm.assume() then the chances are that the function will be too big to inline anyway.


Full diff: https://github.com/llvm/llvm-project/pull/129279.diff

1 Files Affected:

  • (modified) llvm/lib/Analysis/InlineCost.cpp (+15-1)
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index c6b927c8eee2f..3c5cf984861de 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -173,6 +173,12 @@ static cl::opt<bool> DisableGEPConstOperand(
     "disable-gep-const-evaluation", cl::Hidden, cl::init(false),
     cl::desc("Disables evaluation of GetElementPtr with constant operands"));
 
+static cl::opt<unsigned> EphValAssumptionsSzLimit(
+    "inline-ephval-assumptions-limit", cl::Hidden, cl::init(5000),
+    cl::desc("Collection of ephemeral values can be very expensive "
+             "compile-time wise, so don't collect them if the function "
+             "contains more than this many assumptions"));
+
 namespace llvm {
 std::optional<int> getStringFnAttrAsInt(const Attribute &Attr) {
   if (Attr.isValid()) {
@@ -2785,7 +2791,15 @@ InlineResult CallAnalyzer::analyze() {
   // the ephemeral values multiple times (and they're completely determined by
   // the callee, so this is purely duplicate work).
   SmallPtrSet<const Value *, 32> EphValues;
-  CodeMetrics::collectEphemeralValues(&F, &GetAssumptionCache(F), EphValues);
+  auto &AC = GetAssumptionCache(F);
+  // Don't collect ephemeral values if we have too many assumptions because the
+  // collection can be very expensive. Note that this will increase the cost of
+  // the function, making it less likely to be inlined. But if the function
+  // contains thousands of assumptions, then the chances are that it's too large
+  // to inline anyway.
+  bool TooExpensive = AC.assumptions().size() > EphValAssumptionsSzLimit;
+  if (!TooExpensive)
+    CodeMetrics::collectEphemeralValues(&F, &AC, EphValues);
 
   // The worklist of live basic blocks in the callee *after* inlining. We avoid
   // adding basic blocks of the callee which can be proven to be dead for this

@@ -2785,7 +2791,15 @@ InlineResult CallAnalyzer::analyze() {
// the ephemeral values multiple times (and they're completely determined by
// the callee, so this is purely duplicate work).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to resolve this FIXME instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would be ideal. Caching the EphValues set based on the callee would probably fix the issue. The problem is that I am not sure I will be able to catch all cases where caching would need to be invalidated. I don't see any tests for this code which would make it tricky to validate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants