[llvm] [InstCombine] Infer sub nuw from dominating conditions (PR #100164)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 23 10:01:28 PDT 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/100164
Alive2: https://alive2.llvm.org/ce/z/g3xxnM
>From f7cd7bb7e8c2204d815940591e19ec95be48d775 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 24 Jul 2024 00:53:22 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/sub.ll | 144 ++++++++++++++++++++++++
1 file changed, 144 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 49770e8d9e43f..72bcaf6619a26 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2661,3 +2661,147 @@ 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 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: [[EXT0:%.*]] = zext i32 [[Y]] to i64
+; CHECK-NEXT: [[EXT1:%.*]] = zext i32 [[X]] to i64
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
+; CHECK-NEXT: [[EXT2:%.*]] = zext i32 [[SUB]] to i64
+; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[EXT2]], [[EXT0]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[ADD]], [[EXT1]]
+; CHECK-NEXT: ret i1 [[CMP]]
+; 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 nsw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[EXT:%.*]] = zext 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: [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SUB]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+; 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
+}
>From db7728f2acac24a2d919287971b6b91fef93b001 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 24 Jul 2024 00:58:50 +0800
Subject: [PATCH 2/2] [InstCombine] Infer sub nuw from dominating conditions
---
.../InstCombine/InstCombineAddSub.cpp | 5 ++++-
.../Transforms/InstCombine/abs-intrinsic.ll | 2 +-
llvm/test/Transforms/InstCombine/sub.ll | 18 +++++-------------
3 files changed, 10 insertions(+), 15 deletions(-)
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 72bcaf6619a26..cb308ab66b093 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2667,7 +2667,7 @@ define i32 @sub_infer_nuw_from_domcond(i32 %x, i32 %y) {
; 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 i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[X]], [[Y]]
; CHECK-NEXT: ret i32 [[SUB]]
; CHECK: if.else:
; CHECK-NEXT: ret i32 0
@@ -2688,13 +2688,7 @@ define i1 @sub_infer_nuw_from_domcond_fold1(i32 %x, i32 %y) {
; 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: [[EXT0:%.*]] = zext i32 [[Y]] to i64
-; CHECK-NEXT: [[EXT1:%.*]] = zext i32 [[X]] to i64
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
-; CHECK-NEXT: [[EXT2:%.*]] = zext i32 [[SUB]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[EXT2]], [[EXT0]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[ADD]], [[EXT1]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
; CHECK: if.else:
; CHECK-NEXT: ret i1 false
;
@@ -2719,8 +2713,8 @@ define i64 @sub_infer_nuw_from_domcond_fold2(i32 range(i32 0, 2147483648) %x, i3
; 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 nsw i32 [[X]], [[Y]]
-; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SUB]] to i64
+; 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
@@ -2743,9 +2737,7 @@ define i1 @sub_infer_nuw_from_domcond_fold3(i16 %xx, i32 range(i32 0, 12) %y) {
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[Y]], [[X]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SUB]], -1
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
; CHECK: if.else:
; CHECK-NEXT: ret i1 false
;
More information about the llvm-commits
mailing list