[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