-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[ConstraintElim] Decompose sub nsw
#118219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ConstraintElim] Decompose sub nsw
#118219
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesCloses #118211. Full diff: https://github.com/llvm/llvm-project/pull/118219.diff 2 Files Affected:
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
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. As the constraint system works in terms of abstract (non-wrapping) arithmetic here, the fact that a -nsw b
is not the same as a +nsw (-1 * b)
shouldn't matter.
I strongly suspect that it's possible to construct cases where our current decomposition implementation incorrectly handles the case where constant coefficients overflow, though this is not specific to this case.
Regression (reduced from dtcxzyw/llvm-opt-benchmark#1781 (comment)):
Before (22417ec)
After:
#115893 may fix this problem. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/195/builds/2425 Here is the relevant piece of the build log for the reference
|
This patch seems to cause a miscompilation :( |
See #120076. |
Closes #118211.