[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