[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