[llvm] [ConstraintElim] Decompose `sub nsw` (PR #118219)

via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 1 08:36:13 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Yingwei Zheng (dtcxzyw)

<details>
<summary>Changes</summary>

Closes https://github.com/llvm/llvm-project/issues/118211.


---
Full diff: https://github.com/llvm/llvm-project/pull/118219.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+7) 
- (added) llvm/test/Transforms/ConstraintElimination/sub-nsw.ll (+129) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 4884c23f16e12a..2f5ea8a2e46813 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -522,6 +522,13 @@ static Decomposition decompose(Value *V,
     if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1))))
       return MergeResults(Op0, Op1, IsSigned);
 
+    if (match(V, m_NSWSub(m_Value(Op0), m_Value(Op1)))) {
+      auto ResA = decompose(Op0, Preconditions, IsSigned, DL);
+      auto ResB = decompose(Op1, Preconditions, IsSigned, DL);
+      ResA.sub(ResB);
+      return ResA;
+    }
+
     ConstantInt *CI;
     if (match(V, m_NSWMul(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI)) {
       auto Result = decompose(Op0, Preconditions, IsSigned, DL);
diff --git a/llvm/test/Transforms/ConstraintElimination/sub-nsw.ll b/llvm/test/Transforms/ConstraintElimination/sub-nsw.ll
new file mode 100644
index 00000000000000..3ea60d267043d9
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/sub-nsw.ll
@@ -0,0 +1,129 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+define i1 @test_decompose_sub_nsw_sgt_nonneg(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @test_decompose_sub_nsw_sgt_nonneg(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[SUB]], 10
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    ret i1 true
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %sub = sub nsw i32 %y, %x
+  %cond = icmp sgt i32 %sub, 10
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %ret = icmp slt i32 %x, %y
+  ret i1 %ret
+
+if.else:
+  ret i1 true
+}
+
+define i1 @test_decompose_sub_nsw_sgt_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @test_decompose_sub_nsw_sgt_zero(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[SUB]], 0
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    ret i1 true
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %sub = sub nsw i32 %y, %x
+  %cond = icmp sgt i32 %sub, 0
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %ret = icmp slt i32 %x, %y
+  ret i1 %ret
+
+if.else:
+  ret i1 true
+}
+
+define i1 @test_decompose_sub_nsw_sgt_zero_inv(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @test_decompose_sub_nsw_sgt_zero_inv(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[SUB]], 10
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %sub = sub nsw i32 %y, %x
+  %cond = icmp sgt i32 %sub, 10
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %ret = icmp sge i32 %x, %y
+  ret i1 %ret
+
+if.else:
+  ret i1 true
+}
+
+define i1 @test_decompose_sub_nonsw_sgt_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @test_decompose_sub_nonsw_sgt_zero(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[SUB]], 10
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[RET:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[RET]]
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %sub = sub i32 %y, %x
+  %cond = icmp sgt i32 %sub, 10
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %ret = icmp slt i32 %x, %y
+  ret i1 %ret
+
+if.else:
+  ret i1 true
+}
+
+define i1 @test_decompose_sub_nsw_sgt_neg(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @test_decompose_sub_nsw_sgt_neg(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[SUB]], -10
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[RET:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[RET]]
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %sub = sub nsw i32 %y, %x
+  %cond = icmp sgt i32 %sub, -10
+  br i1 %cond, label %if.then, label %if.else
+
+if.then:
+  %ret = icmp slt i32 %x, %y
+  ret i1 %ret
+
+if.else:
+  ret i1 true
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/118219


More information about the llvm-commits mailing list