From: Sanjay Patel Date: Sun, 10 Oct 2021 14:58:58 +0000 (-0400) Subject: [InstCombine] canonicalize "(C2 - Y) > C" as (Y + ~C2) < ~C X-Git-Tag: upstream/15.0.7~29055 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=da210f5d3425e8877ceabaf6ed3483d52cbd7448;p=platform%2Fupstream%2Fllvm.git [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 } --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index e080e7f..63be48f 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 62fb413..38721f3 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 0b62df6..03488a2 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]], +; CHECK-NEXT: [[NOTSUB:%.*]] = add <2 x i7> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i7> [[NOTSUB]], ; 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 90f4f45..5b4bff6 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