-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstCombine] Infer sub nuw from dominating conditions #100164
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
Conversation
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesAlive2: https://alive2.llvm.org/ce/z/g3xxnM Full diff: https://github.com/llvm/llvm-project/pull/100164.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 0a55f4762fdf0..6285091a33d46 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2175,7 +2175,10 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
Changed = true;
I.setHasNoSignedWrap(true);
}
- if (!I.hasNoUnsignedWrap() && willNotOverflowUnsignedSub(Op0, Op1, I)) {
+ if (!I.hasNoUnsignedWrap() &&
+ (willNotOverflowUnsignedSub(Op0, Op1, I) ||
+ isImpliedByDomCondition(ICmpInst::ICMP_UGE, Op0, Op1, &I, DL)
+ .value_or(false))) {
Changed = true;
I.setHasNoUnsignedWrap(true);
}
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index b6740374c0791..f7c639f1d8e6b 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -800,7 +800,7 @@ define i32 @sub_abs_wrong_pred(i32 %x, i32 %y) {
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
; CHECK: cond.true:
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[X]], [[Y]]
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 true)
; CHECK-NEXT: br label [[COND_END]]
; CHECK: cond.end:
diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 49770e8d9e43f..cb308ab66b093 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2661,3 +2661,139 @@ define i8 @sub_of_adds_2xc(i8 %x, i8 %y) {
%r = sub i8 %xc, %yc
ret i8 %r
}
+
+define i32 @sub_infer_nuw_from_domcond(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond(
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[X]], [[Y]]
+; CHECK-NEXT: ret i32 [[SUB]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i32 0
+;
+ %cond = icmp uge i32 %x, %y
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ %sub = sub i32 %x, %y
+ ret i32 %sub
+
+if.else:
+ ret i32 0
+}
+
+define i1 @sub_infer_nuw_from_domcond_fold1(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold1(
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 false
+; CHECK: if.else:
+; CHECK-NEXT: ret i1 false
+;
+ %cond = icmp uge i32 %x, %y
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ %ext0 = zext i32 %y to i64
+ %ext1 = zext i32 %x to i64
+ %sub = sub i32 %x, %y
+ %ext2 = zext i32 %sub to i64
+ %add = add nuw nsw i64 %ext2, %ext0
+ %cmp = icmp ugt i64 %add, %ext1
+ ret i1 %cmp
+
+if.else:
+ ret i1 false
+}
+
+define i64 @sub_infer_nuw_from_domcond_fold2(i32 range(i32 0, 2147483648) %x, i32 range(i32 0, 2147483648) %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold2(
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[EXT:%.*]] = zext nneg i32 [[SUB]] to i64
+; CHECK-NEXT: ret i64 [[EXT]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 0
+;
+ %cond = icmp uge i32 %x, %y
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ %sub = sub i32 %x, %y
+ %ext = zext i32 %sub to i64
+ ret i64 %ext
+
+if.else:
+ ret i64 0
+}
+
+define i1 @sub_infer_nuw_from_domcond_fold3(i16 %xx, i32 range(i32 0, 12) %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold3(
+; CHECK-NEXT: [[X:%.*]] = zext i16 [[XX:%.*]] to i32
+; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
+; 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 false
+;
+ %x = zext i16 %xx to i32
+ %cond = icmp ult i32 %x, %y
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ %sub = sub nsw i32 %y, %x
+ %cmp = icmp eq i32 %sub, -1
+ ret i1 %cmp
+
+if.else:
+ ret i1 false
+}
+
+; negative tests
+
+define i32 @sub_infer_nuw_from_domcond_wrong_pred(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond_wrong_pred(
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
+; CHECK-NEXT: ret i32 [[SUB]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i32 0
+;
+ %cond = icmp sge i32 %x, %y
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ %sub = sub i32 %x, %y
+ ret i32 %sub
+
+if.else:
+ ret i32 0
+}
+
+define i32 @sub_infer_nuw_from_domcond_lhs_is_false(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub_infer_nuw_from_domcond_lhs_is_false(
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
+; CHECK-NEXT: ret i32 [[SUB]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i32 0
+;
+ %cond = icmp uge i32 %x, %y
+ br i1 %cond, label %if.else, label %if.then
+
+if.then:
+ %sub = sub i32 %x, %y
+ ret i32 %sub
+
+if.else:
+ ret i32 0
+}
|
LGTM |
The principled way to do this would be to infer sub nuw in ConstraintElimination, but I think using CE for this is probably too expensive. |
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
Summary: Alive2: https://alive2.llvm.org/ce/z/g3xxnM Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250731
Alive2: https://alive2.llvm.org/ce/z/g3xxnM