[llvm] [ConstraintElimination] Decompose bitwise and or (PR #126158)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 6 15:52:22 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Lee Wei (leewei05)
<details>
<summary>Changes</summary>
Alive2: https://alive2.llvm.org/ce/z/XUp6KG
Fixes #<!-- -->118114
@<!-- -->regehr
---
Full diff: https://github.com/llvm/llvm-project/pull/126158.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+12)
- (modified) llvm/test/Transforms/ConstraintElimination/and.ll (+88)
- (modified) llvm/test/Transforms/ConstraintElimination/or.ll (+88)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index e0861fbedc560aa..78252ffa7ec785d 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -562,6 +562,18 @@ static Decomposition decompose(Value *V,
}
}
+ // (x | y) < 0 => (x < 0) || (y < 0)
+ if (match(V, m_Or(m_Value(Op0), m_Value(Op1)))) {
+ if (!isKnownNonNegative(Op0, DL) || !isKnownNonNegative(Op1, DL))
+ return MergeResults(Op0, Op1, IsSigned);
+ }
+
+ // (x & y) < 0 => (x < 0) && (y < 0)
+ if (match(V, m_And(m_Value(Op0), m_Value(Op1)))) {
+ if (!isKnownNonNegative(Op0, DL) && !isKnownNonNegative(Op1, DL))
+ return MergeResults(Op0, Op1, IsSigned);
+ }
+
return {V, IsKnownNonNegative};
}
diff --git a/llvm/test/Transforms/ConstraintElimination/and.ll b/llvm/test/Transforms/ConstraintElimination/and.ll
index f9824df3975e97a..9d89f8e5d372150 100644
--- a/llvm/test/Transforms/ConstraintElimination/and.ll
+++ b/llvm/test/Transforms/ConstraintElimination/and.ll
@@ -603,3 +603,91 @@ 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 sge i4 [[X]], 0
+; CHECK-NEXT: [[F_2:%.*]] = icmp sge i4 [[Y]], 0
+; CHECK-NEXT: [[F_AND:%.*]] = and i1 false, [[F_2]]
+; CHECK-NEXT: call void @use(i1 [[F_AND]])
+; CHECK-NEXT: ret void
+; CHECK: exit:
+; CHECK-NEXT: [[F_3:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT: [[F_4:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT: [[F_AND_2:%.*]] = and i1 false, [[F_4]]
+; CHECK-NEXT: call void @use(i1 [[F_AND_2]])
+; 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 sge i4 %x, 0
+ %f.2 = icmp sge i4 %y, 0
+ %f.and = and i1 %f.1, %f.2
+ call void @use(i1 %f.and)
+ ret void
+
+exit:
+ %f.3 = icmp slt i4 %x, 0
+ %f.4 = icmp slt i4 %y, 0
+ %f.and.2 = and i1 %f.3, %f.4
+ call void @use(i1 %f.and.2)
+ ret void
+}
+
+define void @test_decompose_nested_bitwise_and(i4 %x, i4 %y, i4 %z) {
+; 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: [[AND:%.*]] = icmp slt i4 [[TMP1]], 0
+; CHECK-NEXT: br i1 [[AND]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[F_1:%.*]] = icmp sge i4 [[X]], 0
+; CHECK-NEXT: [[F_2:%.*]] = icmp sge i4 [[Y]], 0
+; CHECK-NEXT: [[F_3:%.*]] = icmp sge i4 [[Z]], 0
+; CHECK-NEXT: [[F_AND:%.*]] = and i1 [[F_1]], [[F_2]]
+; CHECK-NEXT: [[F_AND_2:%.*]] = and i1 [[F_AND]], false
+; CHECK-NEXT: call void @use(i1 [[F_AND]])
+; CHECK-NEXT: ret void
+; CHECK: exit:
+; 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_AND_3:%.*]] = and i1 [[F_4]], [[F_5]]
+; CHECK-NEXT: [[F_AND_4:%.*]] = and i1 [[F_AND_3]], false
+; CHECK-NEXT: call void @use(i1 [[F_AND_4]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %1 = and i4 %y, %x
+ %2 = and i4 %1, %z
+ %and = icmp slt i4 %2, 0
+ br i1 %and, label %bb1, label %exit
+
+bb1:
+ %f.1 = icmp sge i4 %x, 0
+ %f.2 = icmp sge i4 %y, 0
+ %f.3 = icmp sge i4 %z, 0
+ %f.and = and i1 %f.1, %f.2
+ %f.and.2 = and i1 %f.and, %f.3
+ call void @use(i1 %f.and)
+ ret void
+
+exit:
+ %f.4 = icmp slt i4 %x, 0
+ %f.5 = icmp slt i4 %y, 0
+ %f.6 = icmp slt i4 %z, 0
+ %f.and.3 = and i1 %f.4, %f.5
+ %f.and.4 = and i1 %f.and.3, %f.6
+ call void @use(i1 %f.and.4)
+ ret void
+}
diff --git a/llvm/test/Transforms/ConstraintElimination/or.ll b/llvm/test/Transforms/ConstraintElimination/or.ll
index b401d6f18136958..37fecb0348b3b1c 100644
--- a/llvm/test/Transforms/ConstraintElimination/or.ll
+++ b/llvm/test/Transforms/ConstraintElimination/or.ll
@@ -808,3 +808,91 @@ 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: [[F_1:%.*]] = icmp slt i4 [[X]], 0
+; CHECK-NEXT: [[F_2:%.*]] = icmp slt i4 [[Y]], 0
+; CHECK-NEXT: [[F_OR:%.*]] = or i1 true, [[F_2]]
+; CHECK-NEXT: call void @use(i1 [[F_OR]])
+; 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: [[F_OR_2:%.*]] = or i1 true, [[F_4]]
+; CHECK-NEXT: call void @use(i1 [[F_OR_2]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %1 = or i4 %y, %x
+ %or = icmp slt i4 %1, 0
+ br i1 %or, label %bb1, label %exit
+
+bb1:
+ %f.1 = icmp slt i4 %x, 0
+ %f.2 = icmp slt i4 %y, 0
+ %f.or = or i1 %f.1, %f.2
+ call void @use(i1 %f.or)
+ ret void
+
+exit:
+ %f.3 = icmp sge i4 %x, 0
+ %f.4 = icmp sge i4 %y, 0
+ %f.or.2 = or i1 %f.3, %f.4
+ call void @use(i1 %f.or.2)
+ ret void
+}
+
+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: [[TMP1:%.*]] = or i4 [[TMP0]], [[Z:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = icmp slt i4 [[TMP1]], 0
+; CHECK-NEXT: br i1 [[OR]], 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: [[F_3:%.*]] = icmp slt i4 [[Z]], 0
+; CHECK-NEXT: [[F_OR:%.*]] = or i1 [[F_1]], [[F_2]]
+; CHECK-NEXT: [[F_OR_2:%.*]] = or i1 [[F_OR]], true
+; CHECK-NEXT: call void @use(i1 [[F_OR_2]])
+; 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_OR_3:%.*]] = or i1 [[F_4]], [[F_5]]
+; CHECK-NEXT: [[F_OR_4:%.*]] = or i1 [[F_OR_3]], true
+; CHECK-NEXT: call void @use(i1 [[F_OR_4]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %1 = or i4 %y, %x
+ %2 = or i4 %1, %z
+ %or = icmp slt i4 %2, 0
+ br i1 %or, 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.or = or i1 %f.1, %f.2
+ %f.or.2 = or i1 %f.or, %f.3
+ call void @use(i1 %f.or.2)
+ 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.or.3 = or i1 %f.4, %f.5
+ %f.or.4 = or i1 %f.or.3, %f.6
+ call void @use(i1 %f.or.4)
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/126158
More information about the llvm-commits
mailing list