[llvm] [ConstraintElimination] Add additional facts for bitwise AND OR (PR #132124)

Lee Wei via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 28 14:07:22 PDT 2025


https://github.com/leewei05 updated https://github.com/llvm/llvm-project/pull/132124

>From 66839d85cf5486cc2a93d175042d4dd2c5e7927e Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Thu, 6 Mar 2025 16:38:08 -0700
Subject: [PATCH 1/5] Add bitwise and or tests

---
 .../Transforms/ConstraintElimination/and.ll   | 136 ++++++++++++++++++
 .../Transforms/ConstraintElimination/or.ll    | 136 ++++++++++++++++++
 2 files changed, 272 insertions(+)

diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll
index f9824df3975e9..ccc1b6e29d536 100644
--- a/llvm/test/Transforms/ConstraintElimination/and.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and.ll
@@ -603,3 +603,139 @@ exit:
 
   ret i1 %r.10
 }
+
+define void @test_decompose_bitwise_and(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_and(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[F_1:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[F_2:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[F_1]])
+; CHECK-NEXT:    call void @use(i1 [[F_2]])
+; CHECK-NEXT:    ret void
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %1 = and i4 %y, %x
+  %and = icmp slt i4 %1, 0
+  br i1 %and, label %bb1, label %exit
+
+bb1:
+  %f.1 = icmp slt i4 %x, 0
+  %f.2 = icmp slt i4 %y, 0
+  call void @use(i1 %f.1)
+  call void @use(i1 %f.2)
+  ret void
+
+exit:
+  ret void
+}
+
+define i1 @test_decompose_bitwise_and2(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_and2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[AND_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
+; CHECK-NEXT:    br i1 [[AND_NOT]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK:       end:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %0 = and i4 %x, %y
+  %and.not = icmp sgt i4 %0, -1
+  br i1 %and.not, label %end, label %then
+
+then:
+  %cmp = icmp slt i4 %x, 0
+  ret i1 %cmp
+
+end:
+  ret i1 false
+}
+
+define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z, i4 %w) {
+; CHECK-LABEL: @test_decompose_nested_bitwise_and(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[TMP0]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[TMP1]], [[W:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP2]], 0
+; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[F_4:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[F_5:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    [[F_6:%.*]] = icmp slt i4 [[Z]], 0
+; CHECK-NEXT:    [[F_7:%.*]] = icmp slt i4 [[W]], 0
+; CHECK-NEXT:    call void @use(i1 [[F_4]])
+; CHECK-NEXT:    call void @use(i1 [[F_5]])
+; CHECK-NEXT:    call void @use(i1 [[F_6]])
+; CHECK-NEXT:    call void @use(i1 [[F_7]])
+; CHECK-NEXT:    ret void
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %1 = and i4 %y, %x
+  %2 = and i4 %1, %z
+  %3 = and i4 %2, %w
+  %and = icmp slt i4 %3, 0
+  br i1 %and, label %bb1, label %exit
+
+bb1:
+  %f.1 = icmp slt i4 %x, 0
+  %f.2 = icmp slt i4 %y, 0
+  %f.3 = icmp slt i4 %z, 0
+  %f.4 = icmp slt i4 %w, 0
+  call void @use(i1 %f.1)
+  call void @use(i1 %f.2)
+  call void @use(i1 %f.3)
+  call void @use(i1 %f.4)
+  ret void
+
+exit:
+  ret void
+}
+
+define void @test_decompose_nested_bitwise_and2(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_nested_bitwise_and2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[TMP0]], [[Z:%.*]]
+; CHECK-NEXT:    [[AND_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
+; CHECK-NEXT:    br i1 [[AND_2_NOT]], label [[F:%.*]], label [[T:%.*]]
+; CHECK:       t:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    call void @use(i1 [[CMP]])
+; CHECK-NEXT:    [[CMP_2:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[CMP_2]])
+; CHECK-NEXT:    [[CMP_3:%.*]] = icmp slt i4 [[Z]], 0
+; CHECK-NEXT:    call void @use(i1 [[CMP_3]])
+; CHECK-NEXT:    ret void
+; CHECK:       f:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = and i4 %x, %y
+  %1 = and i4 %0, %z
+  %and.2.not = icmp sgt i4 %1, -1
+  br i1 %and.2.not, label %f, label %t
+
+t:
+  %cmp = icmp slt i4 %x, 0
+  call void @use(i1 %cmp)
+  %cmp.2 = icmp slt i4 %y, 0
+  call void @use(i1 %cmp.2)
+  %cmp.3 = icmp slt i4 %z, 0
+  call void @use(i1 %cmp.3)
+  ret void
+
+f:
+  ret void
+}
diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll
index b401d6f181369..234af0c09c651 100644
--- a/llvm/test/Transforms/ConstraintElimination/or.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or.ll
@@ -808,3 +808,139 @@ end:                                           ; preds = %entry
 
   ret void
 }
+
+define void @test_decompose_bitwise_or(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_or(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret void
+; CHECK:       exit:
+; CHECK-NEXT:    [[F_3:%.*]] = icmp sge i4 [[X]], 0
+; CHECK-NEXT:    [[F_4:%.*]] = icmp sge i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[F_3]])
+; CHECK-NEXT:    call void @use(i1 [[F_4]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = or i4 %y, %x
+  %or = icmp slt i4 %0, 0
+  br i1 %or, label %bb1, label %exit
+
+bb1:
+  ret void
+
+exit:
+  %f.3 = icmp sge i4 %x, 0
+  %f.4 = icmp sge i4 %y, 0
+  call void @use(i1 %f.3)
+  call void @use(i1 %f.4)
+  ret void
+}
+
+define i1 @test_decompose_bitwise_or2(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_or2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OR_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
+; CHECK-NEXT:    br i1 [[OR_NOT]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       end:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i4 [[X]], -1
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %0 = or i4 %x, %y
+  %or.not = icmp sgt i4 %0, -1
+  br i1 %or.not, label %end, label %then
+
+then:
+  ret i1 false
+
+end:
+  %cmp = icmp sgt i4 %x, -1
+  ret i1 %cmp
+}
+
+define void @test_decompose_nested_bitwise_or(i4 %x, i4 %y, i4 %z, i4 %w) {
+; CHECK-LABEL: @test_decompose_nested_bitwise_or(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i4 [[TMP1]], [[W:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP2]], 0
+; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret void
+; CHECK:       exit:
+; CHECK-NEXT:    [[F_4:%.*]] = icmp sge i4 [[X]], 0
+; CHECK-NEXT:    [[F_5:%.*]] = icmp sge i4 [[Y]], 0
+; CHECK-NEXT:    [[F_6:%.*]] = icmp sge i4 [[Z]], 0
+; CHECK-NEXT:    [[F_7:%.*]] = icmp sge i4 [[W]], 0
+; CHECK-NEXT:    call void @use(i1 [[F_4]])
+; CHECK-NEXT:    call void @use(i1 [[F_5]])
+; CHECK-NEXT:    call void @use(i1 [[F_6]])
+; CHECK-NEXT:    call void @use(i1 [[F_7]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %1 = or i4 %y, %x
+  %2 = or i4 %1, %z
+  %3 = or i4 %2, %w
+  %or = icmp slt i4 %3, 0
+  br i1 %or, label %bb1, label %exit
+
+bb1:
+  ret void
+
+exit:
+  %f.4 = icmp sge i4 %x, 0
+  %f.5 = icmp sge i4 %y, 0
+  %f.6 = icmp sge i4 %z, 0
+  %f.7 = icmp sge i4 %w, 0
+  call void @use(i1 %f.4)
+  call void @use(i1 %f.5)
+  call void @use(i1 %f.6)
+  call void @use(i1 %f.7)
+  ret void
+}
+
+define void @test_decompose_nested_bitwise_or2(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_nested_bitwise_or2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]]
+; CHECK-NEXT:    [[OR_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
+; CHECK-NEXT:    br i1 [[OR_2_NOT]], label [[F:%.*]], label [[T:%.*]]
+; CHECK:       t:
+; CHECK-NEXT:    ret void
+; CHECK:       f:
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp sgt i4 [[X]], -1
+; CHECK-NEXT:    call void @use(i1 [[CMP_1]])
+; CHECK-NEXT:    [[CMP_2:%.*]] = icmp sgt i4 [[Y]], -1
+; CHECK-NEXT:    call void @use(i1 [[CMP_2]])
+; CHECK-NEXT:    [[CMP_3:%.*]] = icmp sgt i4 [[Z]], -1
+; CHECK-NEXT:    call void @use(i1 [[CMP_3]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = or i4 %x, %y
+  %1 = or i4 %0, %z
+  %or.2.not = icmp sgt i4 %1, -1
+  br i1 %or.2.not, label %f, label %t
+
+t:                                                ; preds = %entry
+  ret void
+
+f:                                                ; preds = %entry
+  %cmp.1 = icmp sgt i4 %x, -1
+  call void @use(i1 %cmp.1)
+  %cmp.2 = icmp sgt i4 %y, -1
+  call void @use(i1 %cmp.2)
+  %cmp.3 = icmp sgt i4 %z, -1
+  call void @use(i1 %cmp.3)
+  ret void
+}

>From e4a8b219c4d16b5fcbb35edab5601e1aea89d318 Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Wed, 19 Mar 2025 00:34:01 -0600
Subject: [PATCH 2/5] Add additional facts

---
 .../Scalar/ConstraintElimination.cpp          | 24 +++++++++++++++
 .../Transforms/ConstraintElimination/and.ll   | 30 +++++++------------
 .../Transforms/ConstraintElimination/or.ll    | 30 +++++++------------
 3 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 267eb319a5616..7980348a999e0 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1605,6 +1605,30 @@ void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
                              unsigned NumIn, unsigned NumOut,
                              SmallVectorImpl<StackEntry> &DFSInStack) {
   addFactImpl(Pred, A, B, NumIn, NumOut, DFSInStack, false);
+
+  Value *LHS;
+  Value *RHS;
+  if (match(A, m_Or(m_Value(LHS), m_Value(RHS)))) {
+    // (LHS | RHS >= 0) =>  LHS >= 0 && RHS >= 0
+    // (LHS | RHS > -1) =>  LHS >= 0 && RHS >= 0
+    if ((match(B, m_Zero()) && Pred == CmpInst::ICMP_SGE) ||
+        (match(B, m_AllOnes()) && Pred == CmpInst::ICMP_SGT)) {
+      addFact(CmpInst::ICMP_SGE, LHS, ConstantInt::get(LHS->getType(), 0),
+              NumIn, NumOut, DFSInStack);
+      addFact(CmpInst::ICMP_SGE, RHS, ConstantInt::get(RHS->getType(), 0),
+              NumIn, NumOut, DFSInStack);
+    }
+  } else if (match(A, m_And(m_Value(LHS), m_Value(RHS)))) {
+    // (LHS & RHS < 0)   =>  LHS < 0 && RHS < 0
+    // (LHS & RHS <= -1) =>  LHS < 0 && RHS < 0
+    if ((match(B, m_Zero()) && Pred == CmpInst::ICMP_SLT) ||
+        (match(B, m_AllOnes()) && Pred == CmpInst::ICMP_SLE)) {
+      addFact(CmpInst::ICMP_SLT, LHS, ConstantInt::get(LHS->getType(), 0),
+              NumIn, NumOut, DFSInStack);
+      addFact(CmpInst::ICMP_SLT, RHS, ConstantInt::get(RHS->getType(), 0),
+              NumIn, NumOut, DFSInStack);
+    }
+  }
   // If the Pred is eq/ne, also add the fact to signed system.
   if (CmpInst::isEquality(Pred))
     addFactImpl(Pred, A, B, NumIn, NumOut, DFSInStack, true);
diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll
index ccc1b6e29d536..80273aea03ea5 100644
--- a/llvm/test/Transforms/ConstraintElimination/and.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and.ll
@@ -611,10 +611,8 @@ define void @test_decompose_bitwise_and(i4 %x, i4 %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP0]], 0
 ; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[F_1:%.*]] = icmp slt i4 [[X]], 0
-; CHECK-NEXT:    [[F_2:%.*]] = icmp slt i4 [[Y]], 0
-; CHECK-NEXT:    call void @use(i1 [[F_1]])
-; CHECK-NEXT:    call void @use(i1 [[F_2]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -642,8 +640,7 @@ define i1 @test_decompose_bitwise_and2(i4 %x, i4 %y) {
 ; CHECK-NEXT:    [[AND_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
 ; CHECK-NEXT:    br i1 [[AND_NOT]], label [[END:%.*]], label [[THEN:%.*]]
 ; CHECK:       then:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i4 [[X]], 0
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ; CHECK:       end:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -669,14 +666,10 @@ define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z, i4 %w) {
 ; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP2]], 0
 ; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[F_4:%.*]] = icmp slt i4 [[X]], 0
-; CHECK-NEXT:    [[F_5:%.*]] = icmp slt i4 [[Y]], 0
-; CHECK-NEXT:    [[F_6:%.*]] = icmp slt i4 [[Z]], 0
-; CHECK-NEXT:    [[F_7:%.*]] = icmp slt i4 [[W]], 0
-; CHECK-NEXT:    call void @use(i1 [[F_4]])
-; CHECK-NEXT:    call void @use(i1 [[F_5]])
-; CHECK-NEXT:    call void @use(i1 [[F_6]])
-; CHECK-NEXT:    call void @use(i1 [[F_7]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -711,12 +704,9 @@ define void @test_decompose_nested_bitwise_and2(i4 %x, i4 %y, i4 %z) {
 ; CHECK-NEXT:    [[AND_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
 ; CHECK-NEXT:    br i1 [[AND_2_NOT]], label [[F:%.*]], label [[T:%.*]]
 ; CHECK:       t:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i4 [[X]], 0
-; CHECK-NEXT:    call void @use(i1 [[CMP]])
-; CHECK-NEXT:    [[CMP_2:%.*]] = icmp slt i4 [[Y]], 0
-; CHECK-NEXT:    call void @use(i1 [[CMP_2]])
-; CHECK-NEXT:    [[CMP_3:%.*]] = icmp slt i4 [[Z]], 0
-; CHECK-NEXT:    call void @use(i1 [[CMP_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ; CHECK:       f:
 ; CHECK-NEXT:    ret void
diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll
index 234af0c09c651..002f2fffebb56 100644
--- a/llvm/test/Transforms/ConstraintElimination/or.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or.ll
@@ -818,10 +818,8 @@ define void @test_decompose_bitwise_or(i4 %x, i4 %y) {
 ; CHECK:       bb1:
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit:
-; CHECK-NEXT:    [[F_3:%.*]] = icmp sge i4 [[X]], 0
-; CHECK-NEXT:    [[F_4:%.*]] = icmp sge i4 [[Y]], 0
-; CHECK-NEXT:    call void @use(i1 [[F_3]])
-; CHECK-NEXT:    call void @use(i1 [[F_4]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -849,8 +847,7 @@ define i1 @test_decompose_bitwise_or2(i4 %x, i4 %y) {
 ; CHECK:       then:
 ; CHECK-NEXT:    ret i1 false
 ; CHECK:       end:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i4 [[X]], -1
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %0 = or i4 %x, %y
@@ -876,14 +873,10 @@ define void @test_decompose_nested_bitwise_or(i4 %x, i4 %y, i4 %z, i4 %w) {
 ; CHECK:       bb1:
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit:
-; CHECK-NEXT:    [[F_4:%.*]] = icmp sge i4 [[X]], 0
-; CHECK-NEXT:    [[F_5:%.*]] = icmp sge i4 [[Y]], 0
-; CHECK-NEXT:    [[F_6:%.*]] = icmp sge i4 [[Z]], 0
-; CHECK-NEXT:    [[F_7:%.*]] = icmp sge i4 [[W]], 0
-; CHECK-NEXT:    call void @use(i1 [[F_4]])
-; CHECK-NEXT:    call void @use(i1 [[F_5]])
-; CHECK-NEXT:    call void @use(i1 [[F_6]])
-; CHECK-NEXT:    call void @use(i1 [[F_7]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -918,12 +911,9 @@ define void @test_decompose_nested_bitwise_or2(i4 %x, i4 %y, i4 %z) {
 ; CHECK:       t:
 ; CHECK-NEXT:    ret void
 ; CHECK:       f:
-; CHECK-NEXT:    [[CMP_1:%.*]] = icmp sgt i4 [[X]], -1
-; CHECK-NEXT:    call void @use(i1 [[CMP_1]])
-; CHECK-NEXT:    [[CMP_2:%.*]] = icmp sgt i4 [[Y]], -1
-; CHECK-NEXT:    call void @use(i1 [[CMP_2]])
-; CHECK-NEXT:    [[CMP_3:%.*]] = icmp sgt i4 [[Z]], -1
-; CHECK-NEXT:    call void @use(i1 [[CMP_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ;
 entry:

>From 3eadf70318b20aa020aa5d44da96960d229fe906 Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Mon, 24 Mar 2025 15:13:05 -0600
Subject: [PATCH 3/5] Update tests

Use named values and rename branches
---
 .../Transforms/ConstraintElimination/and.ll   | 117 +++++++-------
 .../Transforms/ConstraintElimination/or.ll    | 147 ++++++++++--------
 2 files changed, 142 insertions(+), 122 deletions(-)

diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll
index 80273aea03ea5..ee74bf347909c 100644
--- a/llvm/test/Transforms/ConstraintElimination/and.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and.ll
@@ -610,51 +610,59 @@ define void @test_decompose_bitwise_and(i4 %x, i4 %y) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP0]], 0
 ; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
-; CHECK:       bb1:
+; CHECK:       then:
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
-; CHECK:       exit:
+; CHECK:       end:
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %1 = and i4 %y, %x
-  %and = icmp slt i4 %1, 0
-  br i1 %and, label %bb1, label %exit
+  %and.1 = and i4 %y, %x
+  %c.1= icmp slt i4 %and.1, 0
+  br i1 %c.1, label %then, label %end
 
-bb1:
-  %f.1 = icmp slt i4 %x, 0
-  %f.2 = icmp slt i4 %y, 0
-  call void @use(i1 %f.1)
-  call void @use(i1 %f.2)
+then:
+  ; fact: %and.1 < 0
+  %t.1 = icmp slt i4 %x, 0
+  %t.2 = icmp slt i4 %y, 0
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
   ret void
 
-exit:
+end:
   ret void
 }
 
-define i1 @test_decompose_bitwise_and2(i4 %x, i4 %y) {
+define void @test_decompose_bitwise_and2(i4 %x, i4 %y) {
 ; CHECK-LABEL: @test_decompose_bitwise_and2(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[AND_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
 ; CHECK-NEXT:    br i1 [[AND_NOT]], label [[END:%.*]], label [[THEN:%.*]]
 ; CHECK:       then:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret void
 ; CHECK:       end:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
 ;
 entry:
-  %0 = and i4 %x, %y
-  %and.not = icmp sgt i4 %0, -1
-  br i1 %and.not, label %end, label %then
+  %and.1 = and i4 %x, %y
+  %c.1 = icmp sgt i4 %and.1, -1
+  br i1 %c.1, label %then, label %end
 
 then:
-  %cmp = icmp slt i4 %x, 0
-  ret i1 %cmp
+  ; fact: %and.1 > -1
+  ret void
 
 end:
-  ret i1 false
+  ; fact: %and.1 <= -1
+  %t.1 = icmp slt i4 %x, 0
+  %t.2 = icmp slt i4 %y, 0
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  ret void
 }
 
 define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z, i4 %w) {
@@ -665,34 +673,35 @@ define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z, i4 %w) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[TMP1]], [[W:%.*]]
 ; CHECK-NEXT:    [[AND:%.*]] = icmp slt i4 [[TMP2]], 0
 ; CHECK-NEXT:    br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
-; CHECK:       bb1:
+; CHECK:       then:
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
-; CHECK:       exit:
+; CHECK:       end:
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %1 = and i4 %y, %x
-  %2 = and i4 %1, %z
-  %3 = and i4 %2, %w
-  %and = icmp slt i4 %3, 0
-  br i1 %and, label %bb1, label %exit
+  %and.1 = and i4 %y, %x
+  %and.2 = and i4 %and.1, %z
+  %and.3 = and i4 %and.2, %w
+  %c.1= icmp slt i4 %and.3, 0
+  br i1 %c.1, label %then, label %end
 
-bb1:
-  %f.1 = icmp slt i4 %x, 0
-  %f.2 = icmp slt i4 %y, 0
-  %f.3 = icmp slt i4 %z, 0
-  %f.4 = icmp slt i4 %w, 0
-  call void @use(i1 %f.1)
-  call void @use(i1 %f.2)
-  call void @use(i1 %f.3)
-  call void @use(i1 %f.4)
+then:
+  ; fact: %and.3 < 0
+  %t.1 = icmp slt i4 %x, 0
+  %t.2 = icmp slt i4 %y, 0
+  %t.3 = icmp slt i4 %z, 0
+  %t.4 = icmp slt i4 %w, 0
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  call void @use(i1 %t.3)
+  call void @use(i1 %t.4)
   ret void
 
-exit:
+end:
   ret void
 }
 
@@ -703,29 +712,31 @@ define void @test_decompose_nested_bitwise_and2(i4 %x, i4 %y, i4 %z) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[TMP0]], [[Z:%.*]]
 ; CHECK-NEXT:    [[AND_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
 ; CHECK-NEXT:    br i1 [[AND_2_NOT]], label [[F:%.*]], label [[T:%.*]]
-; CHECK:       t:
+; CHECK:       then:
+; CHECK-NEXT:    ret void
+; CHECK:       end:
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
-; CHECK:       f:
-; CHECK-NEXT:    ret void
 ;
 entry:
-  %0 = and i4 %x, %y
-  %1 = and i4 %0, %z
-  %and.2.not = icmp sgt i4 %1, -1
-  br i1 %and.2.not, label %f, label %t
-
-t:
-  %cmp = icmp slt i4 %x, 0
-  call void @use(i1 %cmp)
-  %cmp.2 = icmp slt i4 %y, 0
-  call void @use(i1 %cmp.2)
-  %cmp.3 = icmp slt i4 %z, 0
-  call void @use(i1 %cmp.3)
+  %and.1 = and i4 %x, %y
+  %and.2 = and i4 %and.1, %z
+  %c.1 = icmp sgt i4 %and.2, -1
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %and.2 > -1
   ret void
 
-f:
+end:
+  ; fact: %and.2 <= -1 same as %and.2 < 0
+  %t.1 = icmp slt i4 %x, 0
+  %t.2 = icmp slt i4 %y, 0
+  %t.3 = icmp slt i4 %z, 0
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  call void @use(i1 %t.3)
   ret void
 }
diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll
index 002f2fffebb56..adbc442c0ed9f 100644
--- a/llvm/test/Transforms/ConstraintElimination/or.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or.ll
@@ -812,125 +812,134 @@ end:                                           ; preds = %entry
 define void @test_decompose_bitwise_or(i4 %x, i4 %y) {
 ; CHECK-LABEL: @test_decompose_bitwise_or(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    ret void
-; CHECK:       exit:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OR_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
+; CHECK-NEXT:    br i1 [[OR_NOT]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
 ;
 entry:
-  %0 = or i4 %y, %x
-  %or = icmp slt i4 %0, 0
-  br i1 %or, label %bb1, label %exit
+  %or.1 = or i4 %x, %y
+  %c.1 = icmp sgt i4 %or.1, -1
+  br i1 %c.1, label %then, label %end
 
-bb1:
+then:
+  %t.1 = icmp sgt i4 %x, -1
+  %t.2 = icmp sgt i4 %y, -1
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
   ret void
 
-exit:
-  %f.3 = icmp sge i4 %x, 0
-  %f.4 = icmp sge i4 %y, 0
-  call void @use(i1 %f.3)
-  call void @use(i1 %f.4)
+end:
   ret void
 }
 
-define i1 @test_decompose_bitwise_or2(i4 %x, i4 %y) {
+define void @test_decompose_bitwise_or2(i4 %x, i4 %y) {
 ; CHECK-LABEL: @test_decompose_bitwise_or2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[OR_NOT:%.*]] = icmp sgt i4 [[TMP0]], -1
-; CHECK-NEXT:    br i1 [[OR_NOT]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
 ; CHECK:       then:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    ret void
 ; CHECK:       end:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
 ;
 entry:
-  %0 = or i4 %x, %y
-  %or.not = icmp sgt i4 %0, -1
-  br i1 %or.not, label %end, label %then
+  %or.1 = or i4 %y, %x
+  %c.1 = icmp slt i4 %or.1, 0
+  br i1 %c.1, label %then, label %end
 
 then:
-  ret i1 false
+  ; fact: %or.1 < 0
+  ret void
 
 end:
-  %cmp = icmp sgt i4 %x, -1
-  ret i1 %cmp
+  ; fact: %or.1 >= 0
+  %t.1 = icmp sgt i4 %x, -1
+  %t.2 = icmp sgt i4 %y, -1
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  ret void
 }
 
-define void @test_decompose_nested_bitwise_or(i4 %x, i4 %y, i4 %z, i4 %w) {
+define void @test_decompose_nested_bitwise_or(i4 %x, i4 %y, i4 %z) {
 ; CHECK-LABEL: @test_decompose_nested_bitwise_or(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = or i4 [[TMP1]], [[W:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP2]], 0
-; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    ret void
-; CHECK:       exit:
-; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    [[OR_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
+; CHECK-NEXT:    br i1 [[OR_2_NOT]], label [[F:%.*]], label [[T:%.*]]
+; CHECK:       then:
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
 ;
 entry:
-  %1 = or i4 %y, %x
-  %2 = or i4 %1, %z
-  %3 = or i4 %2, %w
-  %or = icmp slt i4 %3, 0
-  br i1 %or, label %bb1, label %exit
+  %or.1 = or i4 %x, %y
+  %or.2 = or i4 %or.1, %z
+  %c.1 = icmp sgt i4 %or.2, -1
+  br i1 %c.1, label %then, label %end
 
-bb1:
+then:                                                ; preds = %entry
+  %t.1 = icmp sgt i4 %x, -1
+  %t.2 = icmp sgt i4 %y, -1
+  %t.3 = icmp sgt i4 %z, -1
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  call void @use(i1 %t.3)
   ret void
 
-exit:
-  %f.4 = icmp sge i4 %x, 0
-  %f.5 = icmp sge i4 %y, 0
-  %f.6 = icmp sge i4 %z, 0
-  %f.7 = icmp sge i4 %w, 0
-  call void @use(i1 %f.4)
-  call void @use(i1 %f.5)
-  call void @use(i1 %f.6)
-  call void @use(i1 %f.7)
+end:                                                ; preds = %entry
   ret void
 }
 
-define void @test_decompose_nested_bitwise_or2(i4 %x, i4 %y, i4 %z) {
+define void @test_decompose_nested_bitwise_or2(i4 %x, i4 %y, i4 %z, i4 %w) {
 ; CHECK-LABEL: @test_decompose_nested_bitwise_or2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]]
-; CHECK-NEXT:    [[OR_2_NOT:%.*]] = icmp sgt i4 [[TMP1]], -1
-; CHECK-NEXT:    br i1 [[OR_2_NOT]], label [[F:%.*]], label [[T:%.*]]
-; CHECK:       t:
+; CHECK-NEXT:    [[TMP2:%.*]] = or i4 [[TMP1]], [[W:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = icmp slt i4 [[TMP2]], 0
+; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       then:
 ; CHECK-NEXT:    ret void
-; CHECK:       f:
+; CHECK:       end:
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %0 = or i4 %x, %y
-  %1 = or i4 %0, %z
-  %or.2.not = icmp sgt i4 %1, -1
-  br i1 %or.2.not, label %f, label %t
+  %or.1 = or i4 %y, %x
+  %or.2 = or i4 %or.1, %z
+  %or.3 = or i4 %or.2, %w
+  %c.1 = icmp slt i4 %or.3, 0
+  br i1 %c.1, label %then, label %end
 
-t:                                                ; preds = %entry
+then:
+  ; fact: %or.3 < 0
   ret void
 
-f:                                                ; preds = %entry
-  %cmp.1 = icmp sgt i4 %x, -1
-  call void @use(i1 %cmp.1)
-  %cmp.2 = icmp sgt i4 %y, -1
-  call void @use(i1 %cmp.2)
-  %cmp.3 = icmp sgt i4 %z, -1
-  call void @use(i1 %cmp.3)
+end:
+  ; fact: %or.3 >= 0 same as %or.3 > -1
+  %t.1 = icmp sgt i4 %x, -1
+  %t.2 = icmp sgt i4 %y, -1
+  %t.3 = icmp sgt i4 %z, -1
+  %t.4 = icmp sgt i4 %w, -1
+  call void @use(i1 %t.1)
+  call void @use(i1 %t.2)
+  call void @use(i1 %t.3)
+  call void @use(i1 %t.4)
   ret void
 }

>From 40fc76572d0376956bbf4353ed75f5a8a6e8b597 Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Fri, 28 Mar 2025 14:04:28 -0600
Subject: [PATCH 4/5] Add negative test cases

---
 .../Transforms/ConstraintElimination/and.ll   | 68 +++++++++++++++++++
 .../Transforms/ConstraintElimination/or.ll    | 68 +++++++++++++++++++
 2 files changed, 136 insertions(+)

diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll
index ee74bf347909c..03d98c0396326 100644
--- a/llvm/test/Transforms/ConstraintElimination/and.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and.ll
@@ -740,3 +740,71 @@ end:
   call void @use(i1 %t.3)
   ret void
 }
+
+define void @test_decompose_bitwise_and_negative(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_and_negative(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i4 [[AND_1]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %and.1 = and i4 %y, %x
+  %c.1= icmp slt i4 %and.1, 0
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %and.1 < 0
+  ret void
+
+end:
+  ; fact: %and.1 >= 0
+  ; %c.2, %c.3 should only be replaced in the bitwise OR case
+  %c.2 = icmp sgt i4 %x, 0
+  %c.3 = icmp sgt i4 %y, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ret void
+}
+
+define void @test_decompose_bitwise_and_negative_2(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_and_negative_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i4 [[AND_1]], -1
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %and.1 = and i4 %x, %y
+  %c.1 = icmp sgt i4 %and.1, -1
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %and.1 > -1
+  ; %c.1, %c.2 should only be replaced in the bitwise OR case
+  %c.2 = icmp sgt i4 %x, 0
+  %c.3 = icmp sgt i4 %y, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ret void
+
+end:
+  ; fact: %and.1 <= -1
+  ret void
+}
diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll
index adbc442c0ed9f..51abf034bd62c 100644
--- a/llvm/test/Transforms/ConstraintElimination/or.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or.ll
@@ -943,3 +943,71 @@ end:
   call void @use(i1 %t.4)
   ret void
 }
+
+define void @test_decompose_bitwise_or_negative(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_or_negative(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i4 [[OR_1]], -1
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %or.1 = or i4 %x, %y
+  %c.1 = icmp sgt i4 %or.1, -1
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %or.1 > -1
+  ret void
+
+end:
+  ; fact: %or.1 <= -1
+  ; %c.2, %c.3 should only be replaced in the bitwise AND case
+  %c.2 = icmp slt i4 %x, 0
+  %c.3 = icmp slt i4 %y, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ret void
+}
+
+define void @test_decompose_bitwise_or_negative2(i4 %x, i4 %y) {
+; CHECK-LABEL: @test_decompose_bitwise_or_negative2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i4 [[OR_1]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %or.1 = or i4 %y, %x
+  %c.1 = icmp slt i4 %or.1, 0
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %or.1 < 0
+  ; %c.2, %c.3 should only be replaced in the bitwise AND case
+  %c.2 = icmp slt i4 %x, 0
+  %c.3 = icmp slt i4 %y, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ret void
+
+end:
+  ; fact: %or.1 >= 0
+  ret void
+}

>From 3368e4acedf74b050916a63b7cba353235314132 Mon Sep 17 00:00:00 2001
From: Lee <lee10202013 at gmail.com>
Date: Fri, 28 Mar 2025 14:56:56 -0600
Subject: [PATCH 5/5] Add mixed bitwise and or test cases

---
 .../ConstraintElimination/mixed-and-or.ll     | 162 ++++++++++++++++++
 1 file changed, 162 insertions(+)
 create mode 100644 llvm/test/Transforms/ConstraintElimination/mixed-and-or.ll

diff --git a/llvm/test/Transforms/ConstraintElimination/mixed-and-or.ll b/llvm/test/Transforms/ConstraintElimination/mixed-and-or.ll
new file mode 100644
index 0000000000000..4c847077d3be4
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/mixed-and-or.ll
@@ -0,0 +1,162 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @test_decompose_mixed_bitwise_and_or(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_mixed_bitwise_and_or(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[AND_1]], [[Z:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i4 [[OR_1]], -1
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i4 [[X]], -1
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i4 [[Y]], -1
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %and.1 = and i4 %y, %x
+  %or.1 = or i4 %and.1, %z
+  %c.1= icmp sgt i4 %or.1, -1
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %or.1 > -1 => %and.1 >= 0 && %z >= 0
+  ; %and.1 >= 0 => %x >= 0 || %y >= 0 (constraint system doesn't support logical OR)
+  %c.2 = icmp sgt i4 %x, -1
+  %c.3 = icmp sgt i4 %y, -1
+  %t.1 = icmp sgt i4 %z, -1
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ; only %t.1 can be replaced
+  call void @use(i1 %t.1)
+  ret void
+
+end:
+  ret void
+}
+
+define void @test_decompose_mixed_bitwise_and_or2(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_mixed_bitwise_and_or2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[AND_1]], [[Z:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i4 [[OR_1]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i4 [[X]], -1
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i4 [[Y]], -1
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+;
+entry:
+  %and.1 = and i4 %y, %x
+  %or.1 = or i4 %and.1, %z
+  %c.1 = icmp slt i4 %or.1, 0
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %or.1 < 0
+  ret void
+
+end:
+  ; fact: %or.1 >= 0 => %and.1 >= 0 && %z >= 0
+  ; %and.1 >= 0 => %x >= 0 || %y >= 0 (constraint system doesn't support logical OR)
+  %c.2 = icmp sgt i4 %x, -1
+  %c.3 = icmp sgt i4 %y, -1
+  %t.1 = icmp sgt i4 %z, -1
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ; only %t.1 can be replaced
+  call void @use(i1 %t.1)
+  ret void
+}
+
+define void @test_decompose_mixed_bitwise_and_or3(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_mixed_bitwise_and_or3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[OR_1]], [[Z:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i4 [[AND_1]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %or.1 = or i4 %y, %x
+  %and.1 = and i4 %or.1, %z
+  %c.1= icmp slt i4 %and.1, 0
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %and.1 < 0 => %or.1 < 0 && %z < 0
+  ; %or.1 < 0 => %x < 0 || %y < 0 (constraint system doesn't support logical OR)
+  %c.2 = icmp slt i4 %x, 0
+  %c.3 = icmp slt i4 %y, 0
+  %t.1 = icmp slt i4 %z, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ; only %t.1 can be replaced
+  call void @use(i1 %t.1)
+  ret void
+
+end:
+  ret void
+}
+
+define void @test_decompose_mixed_bitwise_and_or4(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @test_decompose_mixed_bitwise_and_or4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[OR_1:%.*]] = or i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[AND_1:%.*]] = and i4 [[OR_1]], [[Z:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i4 [[AND_1]], -1
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    ret void
+; CHECK:       end:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 [[C_3]])
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+;
+entry:
+  %or.1 = or i4 %y, %x
+  %and.1 = and i4 %or.1, %z
+  %c.1 = icmp sgt i4 %and.1, -1
+  br i1 %c.1, label %then, label %end
+
+then:
+  ; fact: %and.1 > -1
+  ret void
+
+end:
+  ; fact: %and.1 <= -1 => %or.1 < 0 && %z < 0
+  ; %or.1 < 0 => %x < 0 || %y < 0 (constraint system doesn't support logical OR)
+  %c.2 = icmp slt i4 %x, 0
+  %c.3 = icmp slt i4 %y, 0
+  %t.1 = icmp slt i4 %z, 0
+  call void @use(i1 %c.2)
+  call void @use(i1 %c.3)
+  ; only %t.1 can be replaced
+  call void @use(i1 %t.1)
+  ret void
+}



More information about the llvm-commits mailing list