[llvm] [PredicateInfo] Insert copy instructions from assume in dependency order (PR #219344)
Iris Shi via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 18:53:46 PDT 2026
https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/219344
- Resolves #219130.
When there are multiple predicates from the same assume, PredicateInfo used to insert the second copy before the first one.
Since #146321, IPSCCP decides to process instructions in program order. When the second copy is visited, its operand has not been evaluated yet and is still unknown; therefore, half of the predicates are lost.
>From 370c3caefb16dd640976426a45d7c6fc1e9e615f Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Fri, 28 Aug 2026 09:26:46 +0800
Subject: [PATCH 1/2] pre-commit test
---
.../SCCP/issue219130-assume-range.ll | 71 +++++++++++++++++++
.../Util/PredicateInfo/assume-range-order.ll | 22 ++++++
2 files changed, 93 insertions(+)
create mode 100644 llvm/test/Transforms/SCCP/issue219130-assume-range.ll
create mode 100644 llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
diff --git a/llvm/test/Transforms/SCCP/issue219130-assume-range.ll b/llvm/test/Transforms/SCCP/issue219130-assume-range.ll
new file mode 100644
index 0000000000000..b1c887100e951
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/issue219130-assume-range.ll
@@ -0,0 +1,71 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=ipsccp < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @assume_range(i32 %a) {
+; CHECK-LABEL: define void @assume_range(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A]], 100
+; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], 20
+; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 [[GT]], i1 false
+; CHECK-NEXT: call void @llvm.assume(i1 [[BC]])
+; CHECK-NEXT: call void @use(i1 true)
+; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[A]], 105
+; CHECK-NEXT: call void @use(i1 [[T_2]])
+; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i32 [[A]], 105
+; CHECK-NEXT: call void @use(i1 [[F_1]])
+; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[A]], 50
+; CHECK-NEXT: call void @use(i1 [[C_1]])
+; CHECK-NEXT: ret void
+;
+ %lt = icmp ult i32 %a, 100
+ %gt = icmp ugt i32 %a, 20
+ %bc = select i1 %lt, i1 %gt, i1 false
+ call void @llvm.assume(i1 %bc)
+ %t.1 = icmp ugt i32 %a, 10
+ call void @use(i1 %t.1)
+ %t.2 = icmp ult i32 %a, 105
+ call void @use(i1 %t.2)
+ %f.1 = icmp ugt i32 %a, 105
+ call void @use(i1 %f.1)
+ %c.1 = icmp ugt i32 %a, 50
+ call void @use(i1 %c.1)
+ ret void
+}
+
+define i32 @issue219130(i32 %v0, i32 %v1, i32 %v2) {
+; CHECK-LABEL: define range(i32 -2, 195) i32 @issue219130(
+; CHECK-SAME: i32 [[V0:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 39, [[V0]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i32 [[V0]], 46
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 false
+; CHECK-NEXT: call void @llvm.assume(i1 [[OR_COND]])
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 1, [[V1]]
+; CHECK-NEXT: [[CMP4:%.*]] = icmp ule i32 [[V1]], 2
+; CHECK-NEXT: [[OR_COND12:%.*]] = select i1 [[CMP2]], i1 [[CMP4]], i1 false
+; CHECK-NEXT: call void @llvm.assume(i1 [[OR_COND12]])
+; CHECK-NEXT: [[CMP7:%.*]] = icmp ule i32 184, [[V2]]
+; CHECK-NEXT: [[CMP9:%.*]] = icmp ule i32 [[V2]], 194
+; CHECK-NEXT: [[OR_COND13:%.*]] = select i1 [[CMP7]], i1 [[CMP9]], i1 false
+; CHECK-NEXT: call void @llvm.assume(i1 [[OR_COND13]])
+; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[V2]], [[V0]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[DIV]], [[V1]]
+; CHECK-NEXT: ret i32 [[SUB]]
+;
+ %cmp = icmp ule i32 39, %v0
+ %cmp1 = icmp ule i32 %v0, 46
+ %or.cond = select i1 %cmp, i1 %cmp1, i1 false
+ call void @llvm.assume(i1 %or.cond)
+ %cmp2 = icmp ule i32 1, %v1
+ %cmp4 = icmp ule i32 %v1, 2
+ %or.cond12 = select i1 %cmp2, i1 %cmp4, i1 false
+ call void @llvm.assume(i1 %or.cond12)
+ %cmp7 = icmp ule i32 184, %v2
+ %cmp9 = icmp ule i32 %v2, 194
+ %or.cond13 = select i1 %cmp7, i1 %cmp9, i1 false
+ call void @llvm.assume(i1 %or.cond13)
+ %div = udiv i32 %v2, %v0
+ %sub = sub i32 %div, %v1
+ ret i32 %sub
+}
diff --git a/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll b/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
new file mode 100644
index 0000000000000..348cfa81df48b
--- /dev/null
+++ b/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='print<predicate-info>' -disable-output < %s 2>&1 | FileCheck %s
+
+define i32 @assume_range(i32 %v0, i32 %v2) {
+; CHECK-LABEL: define i32 @assume_range(
+; CHECK-SAME: i32 [[V0:%.*]], i32 [[V2:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = icmp ule i32 39, [[V0]]
+; CHECK-NEXT: [[C2:%.*]] = icmp ule i32 [[V0]], 46
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
+; CHECK-NEXT: call void @llvm.assume(i1 [[AND]])
+; CHECK: [[TMP2:%.*]] = bitcast i32 [[TMP1:%.*]] to i32
+; CHECK: [[TMP1]] = bitcast i32 [[V0]] to i32
+; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[V2]], [[TMP2]]
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+ %c1 = icmp ule i32 39, %v0
+ %c2 = icmp ule i32 %v0, 46
+ %and = select i1 %c1, i1 %c2, i1 false
+ call void @llvm.assume(i1 %and)
+ %div = udiv i32 %v2, %v0
+ ret i32 %div
+}
>From d2a9262741f3d72dca4162d1528ba5288d090a73 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Fri, 28 Aug 2026 09:31:50 +0800
Subject: [PATCH 2/2] [PredicateInfo] Insert copy instructions from assume in
dependency order
---
llvm/lib/Transforms/Utils/PredicateInfo.cpp | 15 ++++++++++++---
.../Transforms/SCCP/issue219130-assume-range.ll | 11 ++++-------
.../Util/PredicateInfo/assume-range-order.ll | 4 ++--
3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
index 7a86d310f0f93..b18299a454e15 100644
--- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
@@ -552,9 +552,18 @@ Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter,
auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
assert(PAssume &&
"Should not have gotten here without it being an assume");
- // Insert the predicate directly after the assume. While it also holds
- // directly before it, assume(i1 true) is not a useful fact.
- BitCastInst *PIC = CreateSSACopy(PAssume->AssumeInst->getNextNode(), Op);
+ // Insert the predicate directly after the assume. While the predicate
+ // also holds directly before the assume, assume(i1 true) is not a useful
+ // fact.
+ // When there are multiple predicates from the same assume, insert after
+ // the previous one so the copy does not appear before its operand's
+ // definition.
+ Instruction *InsertPt = PAssume->AssumeInst;
+ if (auto *OpI = dyn_cast<BitCastInst>(Op))
+ if (OpI->getParent() == InsertPt->getParent() &&
+ InsertPt->comesBefore(OpI))
+ InsertPt = OpI;
+ BitCastInst *PIC = CreateSSACopy(InsertPt->getNextNode(), Op);
PI.PredicateMap.insert({PIC, ValInfo});
Result.Def = PIC;
}
diff --git a/llvm/test/Transforms/SCCP/issue219130-assume-range.ll b/llvm/test/Transforms/SCCP/issue219130-assume-range.ll
index b1c887100e951..6422a6e560f6c 100644
--- a/llvm/test/Transforms/SCCP/issue219130-assume-range.ll
+++ b/llvm/test/Transforms/SCCP/issue219130-assume-range.ll
@@ -11,10 +11,8 @@ define void @assume_range(i32 %a) {
; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 [[GT]], i1 false
; CHECK-NEXT: call void @llvm.assume(i1 [[BC]])
; CHECK-NEXT: call void @use(i1 true)
-; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[A]], 105
-; CHECK-NEXT: call void @use(i1 [[T_2]])
-; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i32 [[A]], 105
-; CHECK-NEXT: call void @use(i1 [[F_1]])
+; CHECK-NEXT: call void @use(i1 true)
+; CHECK-NEXT: call void @use(i1 false)
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[A]], 50
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: ret void
@@ -35,7 +33,7 @@ define void @assume_range(i32 %a) {
}
define i32 @issue219130(i32 %v0, i32 %v1, i32 %v2) {
-; CHECK-LABEL: define range(i32 -2, 195) i32 @issue219130(
+; CHECK-LABEL: define range(i32 2, 4) i32 @issue219130(
; CHECK-SAME: i32 [[V0:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]]) {
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 39, [[V0]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i32 [[V0]], 46
@@ -49,8 +47,7 @@ define i32 @issue219130(i32 %v0, i32 %v1, i32 %v2) {
; CHECK-NEXT: [[CMP9:%.*]] = icmp ule i32 [[V2]], 194
; CHECK-NEXT: [[OR_COND13:%.*]] = select i1 [[CMP7]], i1 [[CMP9]], i1 false
; CHECK-NEXT: call void @llvm.assume(i1 [[OR_COND13]])
-; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[V2]], [[V0]]
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[DIV]], [[V1]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 4, [[V1]]
; CHECK-NEXT: ret i32 [[SUB]]
;
%cmp = icmp ule i32 39, %v0
diff --git a/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll b/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
index 348cfa81df48b..4174a32bdf84a 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/assume-range-order.ll
@@ -8,8 +8,8 @@ define i32 @assume_range(i32 %v0, i32 %v2) {
; CHECK-NEXT: [[C2:%.*]] = icmp ule i32 [[V0]], 46
; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
; CHECK-NEXT: call void @llvm.assume(i1 [[AND]])
-; CHECK: [[TMP2:%.*]] = bitcast i32 [[TMP1:%.*]] to i32
-; CHECK: [[TMP1]] = bitcast i32 [[V0]] to i32
+; CHECK: [[TMP1:%.*]] = bitcast i32 [[V0]] to i32
+; CHECK: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to i32
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[V2]], [[TMP2]]
; CHECK-NEXT: ret i32 [[DIV]]
;
More information about the llvm-commits
mailing list