[llvm] da210f5 - [InstCombine] canonicalize "(C2 - Y) > C" as (Y + ~C2) < ~C
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 10 08:08:08 PDT 2021
Author: Sanjay Patel
Date: 2021-10-10T11:06:49-04:00
New Revision: da210f5d3425e8877ceabaf6ed3483d52cbd7448
URL: https://github.com/llvm/llvm-project/commit/da210f5d3425e8877ceabaf6ed3483d52cbd7448
DIFF: https://github.com/llvm/llvm-project/commit/da210f5d3425e8877ceabaf6ed3483d52cbd7448.diff
LOG: [InstCombine] canonicalize "(C2 - Y) > C" as (Y + ~C2) < ~C
The test diffs show that we have better analysis/folds for 'add'
(although we should at least have the simplifications
independently, so we don't have the one-use restriction).
This is related to solving regressions that would appear in
transforms related to D111410, and that is part of a series
of enhancements that may eventually helpi solve PR34047.
https://alive2.llvm.org/ce/z/3tB9KG
define i1 @src(i8 %x, i8 %C, i8 %C2) {
%sub = sub nuw i8 %C2, %x
%r = icmp slt i8 %sub, %C
ret i1 %r
}
define i1 @tgt(i8 %x, i8 %C, i8 %C2) {
%Cnot = xor i8 %C, -1
%C2not = xor i8 %C2, -1
%add = add nuw i8 %x, %C2not
%r = icmp sgt i8 %add, %Cnot
ret i1 %r
}
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
llvm/test/Transforms/InstCombine/icmp-sub.ll
llvm/test/Transforms/InstCombine/or.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index e080e7f95168e..63be48fe352f4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2592,12 +2592,13 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp,
// (icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C)
const APInt *C2;
APInt SubResult;
+ ICmpInst::Predicate SwappedPred = Cmp.getSwappedPredicate();
+ bool HasNSW = Sub->hasNoSignedWrap();
+ bool HasNUW = Sub->hasNoUnsignedWrap();
if (match(X, m_APInt(C2)) &&
- ((Cmp.isUnsigned() && Sub->hasNoUnsignedWrap()) ||
- (Cmp.isSigned() && Sub->hasNoSignedWrap())) &&
+ ((Cmp.isUnsigned() && HasNUW) || (Cmp.isSigned() && HasNSW)) &&
!subWithOverflow(SubResult, *C2, C, Cmp.isSigned()))
- return new ICmpInst(Cmp.getSwappedPredicate(), Y,
- ConstantInt::get(Ty, SubResult));
+ return new ICmpInst(SwappedPred, Y, ConstantInt::get(Ty, SubResult));
// The following transforms are only worth it if the only user of the subtract
// is the icmp.
@@ -2636,7 +2637,12 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp,
if (Pred == ICmpInst::ICMP_UGT && (C + 1).isPowerOf2() && (*C2 & C) == C)
return new ICmpInst(ICmpInst::ICMP_NE, Builder.CreateOr(Y, C), X);
- return nullptr;
+ // We have handled special cases that reduce.
+ // Canonicalize any remaining sub to add as:
+ // (C2 - Y) > C --> (Y + ~C2) < ~C
+ Value *Add = Builder.CreateAdd(Y, ConstantInt::get(Ty, ~(*C2)), "notsub",
+ HasNUW, HasNSW);
+ return new ICmpInst(SwappedPred, Add, ConstantInt::get(Ty, ~C));
}
/// Fold icmp (add X, Y), C.
diff --git a/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll b/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
index 62fb4132d5de6..38721f3079a66 100644
--- a/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
+++ b/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
@@ -3,10 +3,10 @@
define i32 @foo(i32 %a) {
; CHECK-LABEL: @foo(
-; CHECK-NEXT: [[T15:%.*]] = sub i32 99, [[A:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[T15]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1
; CHECK-NEXT: [[A_OP:%.*]] = add i32 [[A]], 1
-; CHECK-NEXT: [[T13:%.*]] = select i1 [[TMP1]], i32 100, i32 [[A_OP]]
+; CHECK-NEXT: [[T13:%.*]] = select i1 [[TMP2]], i32 100, i32 [[A_OP]]
; CHECK-NEXT: ret i32 [[T13]]
;
%t15 = sub i32 99, %a
@@ -19,9 +19,9 @@ define i32 @foo(i32 %a) {
define i32 @bar(i32 %a) {
; CHECK-LABEL: @bar(
-; CHECK-NEXT: [[T15:%.*]] = sub i32 99, [[A:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[T15]], 0
-; CHECK-NEXT: [[T12:%.*]] = select i1 [[TMP1]], i32 99, i32 [[A]]
+; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1
+; CHECK-NEXT: [[T12:%.*]] = select i1 [[TMP2]], i32 99, i32 [[A]]
; CHECK-NEXT: ret i32 [[T12]]
;
%t15 = sub i32 99, %a
diff --git a/llvm/test/Transforms/InstCombine/icmp-sub.ll b/llvm/test/Transforms/InstCombine/icmp-sub.ll
index 0b62df6042585..03488a2f469a3 100644
--- a/llvm/test/Transforms/InstCombine/icmp-sub.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-sub.ll
@@ -46,8 +46,8 @@ define i1 @test_nuw_nsw_and_signed_pred(i64 %x) {
define i1 @test_negative_nuw_and_signed_pred(i64 %x) {
; CHECK-LABEL: @test_negative_nuw_and_signed_pred(
-; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]]
-; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[Y]], 3
+; CHECK-NEXT: [[NOTSUB:%.*]] = add nuw i64 [[X:%.*]], -11
+; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[NOTSUB]], -4
; CHECK-NEXT: ret i1 [[Z]]
;
%y = sub nuw i64 10, %x
@@ -57,8 +57,8 @@ define i1 @test_negative_nuw_and_signed_pred(i64 %x) {
define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) {
; CHECK-LABEL: @test_negative_nsw_and_unsigned_pred(
-; CHECK-NEXT: [[Y:%.*]] = sub nsw i64 10, [[X:%.*]]
-; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 3
+; CHECK-NEXT: [[NOTSUB:%.*]] = add nsw i64 [[X:%.*]], -11
+; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[NOTSUB]], -4
; CHECK-NEXT: ret i1 [[Z]]
;
%y = sub nsw i64 10, %x
@@ -68,9 +68,7 @@ define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) {
define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) {
; CHECK-LABEL: @test_negative_combined_sub_unsigned_overflow(
-; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]]
-; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 11
-; CHECK-NEXT: ret i1 [[Z]]
+; CHECK-NEXT: ret i1 true
;
%y = sub nuw i64 10, %x
%z = icmp ult i64 %y, 11
@@ -79,9 +77,7 @@ define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) {
define i1 @test_negative_combined_sub_signed_overflow(i8 %x) {
; CHECK-LABEL: @test_negative_combined_sub_signed_overflow(
-; CHECK-NEXT: [[Y:%.*]] = sub nsw i8 127, [[X:%.*]]
-; CHECK-NEXT: [[Z:%.*]] = icmp slt i8 [[Y]], -1
-; CHECK-NEXT: ret i1 [[Z]]
+; CHECK-NEXT: ret i1 false
;
%y = sub nsw i8 127, %x
%z = icmp slt i8 %y, -1
@@ -191,8 +187,8 @@ define <2 x i1> @icmp_eq_sub_non_splat2(<2 x i32> %a) {
define i1 @neg_sgt_42(i32 %x) {
; CHECK-LABEL: @neg_sgt_42(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[NEGX]], 42
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[NOTSUB]], -43
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i32 0, %x
@@ -306,8 +302,8 @@ define i1 @subC_nsw_ne(i32 %x) {
define i1 @neg_slt_42(i128 %x) {
; CHECK-LABEL: @neg_slt_42(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i128 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp slt i128 [[NEGX]], 42
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i128 [[X:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i128 [[NOTSUB]], -43
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i128 0, %x
@@ -317,8 +313,8 @@ define i1 @neg_slt_42(i128 %x) {
define <2 x i1> @neg_ugt_42_splat(<2 x i7> %x) {
; CHECK-LABEL: @neg_ugt_42_splat(
-; CHECK-NEXT: [[NEGX:%.*]] = sub <2 x i7> zeroinitializer, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i7> [[NEGX]], <i7 42, i7 42>
+; CHECK-NEXT: [[NOTSUB:%.*]] = add <2 x i7> [[X:%.*]], <i7 -1, i7 -1>
+; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i7> [[NOTSUB]], <i7 -43, i7 -43>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%negx = sub <2 x i7> zeroinitializer, %x
@@ -343,8 +339,8 @@ define i1 @neg_sgt_42_use(i32 %x) {
define i1 @neg_slt_n1(i8 %x) {
; CHECK-LABEL: @neg_slt_n1(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NEGX]], -1
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NOTSUB]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i8 0, %x
@@ -354,8 +350,8 @@ define i1 @neg_slt_n1(i8 %x) {
define i1 @neg_slt_0(i8 %x) {
; CHECK-LABEL: @neg_slt_0(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp slt i8 [[NEGX]], 0
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp sgt i8 [[NOTSUB]], -1
; CHECK-NEXT: ret i1 [[ISNEGNEG]]
;
%negx = sub i8 0, %x
@@ -365,8 +361,7 @@ define i1 @neg_slt_0(i8 %x) {
define i1 @neg_slt_1(i8 %x) {
; CHECK-LABEL: @neg_slt_1(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NEGX]], 1
+; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X:%.*]], -127
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i8 0, %x
@@ -376,8 +371,8 @@ define i1 @neg_slt_1(i8 %x) {
define i1 @neg_sgt_n1(i8 %x) {
; CHECK-LABEL: @neg_sgt_n1(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NEGX]], -1
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i8 0, %x
@@ -387,8 +382,7 @@ define i1 @neg_sgt_n1(i8 %x) {
define i1 @neg_sgt_0(i8 %x) {
; CHECK-LABEL: @neg_sgt_0(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NEGX]], 0
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X:%.*]], -128
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i8 0, %x
@@ -398,8 +392,8 @@ define i1 @neg_sgt_0(i8 %x) {
define i1 @neg_sgt_1(i8 %x) {
; CHECK-LABEL: @neg_sgt_1(
-; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NEGX]], 1
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], -2
; CHECK-NEXT: ret i1 [[R]]
;
%negx = sub i8 0, %x
diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 90f4f45935353..5b4bff6f0c291 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -1447,11 +1447,10 @@ define i8 @lshr_bitwidth_mask(i8 %x, i8 %y) {
define i1 @cmp_overlap(i32 %x) {
; CHECK-LABEL: @cmp_overlap(
-; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0
-; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
-; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i32 [[NEGX]], -1
-; CHECK-NEXT: [[R:%.*]] = or i1 [[ISNEG]], [[ISNOTNEG]]
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[NOTSUB]], [[X]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
+; CHECK-NEXT: ret i1 [[TMP2]]
;
%isneg = icmp slt i32 %x, 0
%negx = sub i32 0, %x
More information about the llvm-commits
mailing list