[llvm-branch-commits] [llvm] 4a09f27 - [SCCP] Fix missing worklist push for recursive calls that update lattice values (#219826)
Tobias Hieta via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Sep 5 00:12:21 PDT 2026
Author: AZero13
Date: 2026-09-05T09:11:49+02:00
New Revision: 4a09f2722a56ee1ba01edb13c17339957f8c1edf
URL: https://github.com/llvm/llvm-project/commit/4a09f2722a56ee1ba01edb13c17339957f8c1edf
DIFF: https://github.com/llvm/llvm-project/commit/4a09f2722a56ee1ba01edb13c17339957f8c1edf.diff
LOG: [SCCP] Fix missing worklist push for recursive calls that update lattice values (#219826)
For a recursive call, the call instruction itself is a user of the
function's arguments. Because I == CurI, I->comesBefore(CurI) is false,
and the condition triggers an early return. The recursive call
instruction was skipped and never pushed back onto the worklist, halting
the solver prematurely before reaching a fixpoint. This caused the
solver to incorrectly believe arguments were hardcoded constants rather
than a wider constant range, resulting in invalid branch folding.
The Fix: This patch updates the condition to explicitly check if I comes
strictly after CurI.
Fixes: https://github.com/llvm/llvm-project/issues/219503
(cherry picked from commit 88f3a791ddb3886cb6fa8d8df1c19e821b7a49b2)
Added:
llvm/test/Transforms/SCCP/ipsccp-recursive-arg-update.ll
Modified:
llvm/lib/Transforms/Utils/SCCPSolver.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index f7e28132ec65c..054d1765f7ebc 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -1070,7 +1070,7 @@ void SCCPInstVisitor::pushToWorkList(Instruction *I) {
// same blocks that are after the current one, as they will be visited
// anyway. We do have to push updates to earlier instructions (e.g. phi
// nodes or loads of tracked globals).
- if (CurI && I->getParent() == CurI->getParent() && !I->comesBefore(CurI))
+ if (CurI && I->getParent() == CurI->getParent() && CurI->comesBefore(I))
return;
// Only push instructions in already visited blocks. Otherwise we'll handle
// it when we visit the block for the first time.
diff --git a/llvm/test/Transforms/SCCP/ipsccp-recursive-arg-update.ll b/llvm/test/Transforms/SCCP/ipsccp-recursive-arg-update.ll
new file mode 100644
index 0000000000000..750677077ea1e
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/ipsccp-recursive-arg-update.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=ipsccp < %s | FileCheck %s
+
+define void @caller() {
+; CHECK-LABEL: define void @caller() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CALL:%.*]] = call i32 @f2(i8 0, i8 0)
+; CHECK-NEXT: ret void
+;
+entry:
+ %call = call i32 @f2(i8 0, i8 0)
+ ret void
+}
+
+define internal i32 @f2(i8 %a0, i8 %a1) {
+; CHECK-LABEL: define internal i32 @f2(
+; CHECK-SAME: i8 range(i8 -9, 1) [[A0:%.*]], i8 range(i8 -9, 1) [[A1:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_NOT_NOT:%.*]] = icmp eq i8 [[A0]], -9
+; CHECK-NEXT: br i1 [[CMP_NOT_NOT]], label [[COMMON_RET1:%.*]], label [[IF_THEN3:%.*]]
+; CHECK: common.ret1:
+; CHECK-NEXT: ret i32 poison
+; CHECK: if.then3:
+; CHECK-NEXT: [[CALL:%.*]] = call i32 @f2(i8 [[A1]], i8 -9)
+; CHECK-NEXT: ret i32 poison
+;
+entry:
+ %cmp.not.not = icmp eq i8 %a0, -9
+ br i1 %cmp.not.not, label %common.ret1, label %if.then3
+
+common.ret1: ; preds = %entry
+ ret i32 0
+
+if.then3: ; preds = %entry
+ %call = call i32 @f2(i8 %a1, i8 -9)
+ ret i32 %call
+}
More information about the llvm-branch-commits
mailing list