[llvm] [SCEV] Refactor forgetLoop and forgetValue to improve compile time (PR #198759)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 03:23:55 PDT 2026


================
@@ -8835,13 +8792,37 @@ void ScalarEvolution::forgetValue(Value *V) {
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) return;
 
-  // Drop information about expressions based on loop-header PHIs.
-  SmallVector<Instruction *, 16> Worklist;
+  SmallVector<std::pair<Instruction *, const SCEV *>, 16> Worklist;
   SmallPtrSet<Instruction *, 8> Visited;
   SmallVector<SCEVUse, 8> ToForget;
-  Worklist.push_back(I);
-  Visited.insert(I);
-  visitAndClearUsers(Worklist, Visited, ToForget);
+
+  auto PushIntoWorklist = [&](Instruction *UI, bool AllowMissingSCEV = false) {
+    bool IsSCEVable = isSCEVable(UI->getType());
+    bool IsWO = isa<WithOverflowInst>(UI);
+    if ((!IsSCEVable && !IsWO) || !Visited.insert(UI).second)
+      return;
+    if (IsSCEVable) {
+      if (const SCEV *S = getExistingSCEV(UI))
----------------
nikic wrote:

Specifically, I don't think that this logic is correct. SCEV will generally not create intermediate SCEVs for all expressions. Consider if you have something like this:

```
%add1 = add i32 %x, 1
%add2 = add i32 %add1, 1
%add3 = add i32 %add2, 1
```
And then query SCEV for `%add3`. This will create SCEV for `%x` and `%add3`, but not the intermediate adds. So if you now invalidate `%add1` (e.g. because you changed the constant), then there will be no existing SCEV, and it will fail to invalidate `%add3`.

https://github.com/llvm/llvm-project/pull/198759


More information about the llvm-commits mailing list