forked from OSchip/llvm-project
[InstCombine] Invert `add A, sext(B) --> sub A, zext(B)` canonicalization (to `sub A, zext B -> add A, sext B`)
Summary: D68408 proposes to greatly improve our negation sinking abilities. But in current canonicalization, we produce `sub A, zext(B)`, which we will consider non-canonical and try to sink that negation, undoing the existing canonicalization. So unless we explicitly stop producing previous canonicalization, we will have two conflicting folds, and will end up endlessly looping. This inverts canonicalization, and adds back the obvious fold that we'd miss: * `sub [nsw] Op0, sext/zext (bool Y) -> add [nsw] Op0, zext/sext (bool Y)` https://rise4fun.com/Alive/xx4 * `sext(bool) + C -> bool ? C - 1 : C` https://rise4fun.com/Alive/fBl It is obvious that `@ossfuzz_9880()` / `@lshr_out_of_range()`/`@ashr_out_of_range()` (oss-fuzz 4871) are no longer folded as much, though those aren't really worrying. Reviewers: spatel, efriedma, t.p.northover, hfinkel Reviewed By: spatel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D71064
This commit is contained in:
parent
c8f0d3e130
commit
796fa662f1
|
@ -890,6 +890,10 @@ Instruction *InstCombiner::foldAddWithConstant(BinaryOperator &Add) {
|
|||
if (match(Op0, m_ZExt(m_Value(X))) &&
|
||||
X->getType()->getScalarSizeInBits() == 1)
|
||||
return SelectInst::Create(X, AddOne(Op1C), Op1);
|
||||
// sext(bool) + C -> bool ? C - 1 : C
|
||||
if (match(Op0, m_SExt(m_Value(X))) &&
|
||||
X->getType()->getScalarSizeInBits() == 1)
|
||||
return SelectInst::Create(X, SubOne(Op1C), Op1);
|
||||
|
||||
// ~X + C --> (C-1) - X
|
||||
if (match(Op0, m_Not(m_Value(X))))
|
||||
|
@ -1288,12 +1292,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
|||
return BinaryOperator::CreateSub(RHS, A);
|
||||
}
|
||||
|
||||
// Canonicalize sext to zext for better value tracking potential.
|
||||
// add A, sext(B) --> sub A, zext(B)
|
||||
if (match(&I, m_c_Add(m_Value(A), m_OneUse(m_SExt(m_Value(B))))) &&
|
||||
B->getType()->isIntOrIntVectorTy(1))
|
||||
return BinaryOperator::CreateSub(A, Builder.CreateZExt(B, Ty));
|
||||
|
||||
// A + -B --> A - B
|
||||
if (match(RHS, m_Neg(m_Value(B))))
|
||||
return BinaryOperator::CreateSub(LHS, B);
|
||||
|
@ -1923,6 +1921,14 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
|||
Add->setHasNoSignedWrap(I.hasNoSignedWrap());
|
||||
return Add;
|
||||
}
|
||||
// sub [nsw] X, zext(bool Y) -> add [nsw] X, sext(bool Y)
|
||||
// 'nuw' is dropped in favor of the canonical form.
|
||||
if (match(Op1, m_ZExt(m_Value(Y))) && Y->getType()->isIntOrIntVectorTy(1)) {
|
||||
Value *Sext = Builder.CreateSExt(Y, I.getType());
|
||||
BinaryOperator *Add = BinaryOperator::CreateAdd(Op0, Sext);
|
||||
Add->setHasNoSignedWrap(I.hasNoSignedWrap());
|
||||
return Add;
|
||||
}
|
||||
|
||||
// X - A*-B -> X + A*B
|
||||
// X - -A*B -> X + A*B
|
||||
|
|
|
@ -533,8 +533,11 @@ define i177 @ossfuzz_9880(i177 %X) {
|
|||
; CHECK-LABEL: @ossfuzz_9880(
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i177, align 8
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i177, i177* [[A]], align 8
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i177 [[L1]], 0
|
||||
; CHECK-NEXT: [[B1:%.*]] = zext i1 [[TMP1]] to i177
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i177 [[L1]], -1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = sext i1 [[TMP1]] to i177
|
||||
; CHECK-NEXT: [[B14:%.*]] = add i177 [[L1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i177 [[B14]], -1
|
||||
; CHECK-NEXT: [[B1:%.*]] = zext i1 [[TMP3]] to i177
|
||||
; CHECK-NEXT: ret i177 [[B1]]
|
||||
;
|
||||
%A = alloca i177
|
||||
|
|
|
@ -515,10 +515,10 @@ define <4 x i32> @vec_sel_xor(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c) {
|
|||
define <4 x i32> @vec_sel_xor_multi_use(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c) {
|
||||
; CHECK-LABEL: @vec_sel_xor_multi_use(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> [[C:%.*]], <i1 true, i1 false, i1 false, i1 false>
|
||||
; CHECK-NEXT: [[MASK_FLIP1:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i1> [[C]], <i1 false, i1 true, i1 true, i1 true>
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i1> [[TMP1]] to <4 x i32>
|
||||
; CHECK-NEXT: [[ADD:%.*]] = sub <4 x i32> [[TMP3]], [[TMP4]]
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[TMP3]], [[MASK_FLIP1]]
|
||||
; CHECK-NEXT: ret <4 x i32> [[ADD]]
|
||||
;
|
||||
%mask = sext <4 x i1> %c to <4 x i32>
|
||||
|
|
|
@ -694,8 +694,8 @@ define i32 @test41(i1 %cond, i32 %x, i32 %y) {
|
|||
define i32 @test42(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: @test42(
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[COND]] to i32
|
||||
; CHECK-NEXT: [[C:%.*]] = sub i32 [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B:%.*]] = sext i1 [[COND]] to i32
|
||||
; CHECK-NEXT: [[C:%.*]] = add i32 [[B]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i32 [[C]]
|
||||
;
|
||||
%b = add i32 %y, -1
|
||||
|
@ -707,8 +707,8 @@ define i32 @test42(i32 %x, i32 %y) {
|
|||
define <2 x i32> @test42vec(<2 x i32> %x, <2 x i32> %y) {
|
||||
; CHECK-LABEL: @test42vec(
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> [[COND]] to <2 x i32>
|
||||
; CHECK-NEXT: [[C:%.*]] = sub <2 x i32> [[Y:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B:%.*]] = sext <2 x i1> [[COND]] to <2 x i32>
|
||||
; CHECK-NEXT: [[C:%.*]] = add <2 x i32> [[B]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret <2 x i32> [[C]]
|
||||
;
|
||||
%b = add <2 x i32> %y, <i32 -1, i32 -1>
|
||||
|
|
|
@ -1628,7 +1628,12 @@ define i32 @ashr_select_xor_false(i32 %x, i1 %cond) {
|
|||
; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4871
|
||||
define i177 @lshr_out_of_range(i177 %Y, i177** %A2) {
|
||||
; CHECK-LABEL: @lshr_out_of_range(
|
||||
; CHECK-NEXT: store i177** [[A2:%.*]], i177*** undef, align 8
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i177 [[Y:%.*]], -1
|
||||
; CHECK-NEXT: [[B4:%.*]] = sext i1 [[TMP1]] to i177
|
||||
; CHECK-NEXT: [[C8:%.*]] = icmp ult i177 [[B4]], [[Y]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = sext i1 [[C8]] to i64
|
||||
; CHECK-NEXT: [[G18:%.*]] = getelementptr i177*, i177** [[A2:%.*]], i64 [[TMP2]]
|
||||
; CHECK-NEXT: store i177** [[G18]], i177*** undef, align 8
|
||||
; CHECK-NEXT: ret i177 0
|
||||
;
|
||||
%B5 = udiv i177 %Y, -1
|
||||
|
@ -1649,6 +1654,18 @@ define i177 @lshr_out_of_range(i177 %Y, i177** %A2) {
|
|||
; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=5032
|
||||
define void @ashr_out_of_range(i177* %A) {
|
||||
; CHECK-LABEL: @ashr_out_of_range(
|
||||
; CHECK-NEXT: [[L:%.*]] = load i177, i177* [[A:%.*]], align 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i177 [[L]], -1
|
||||
; CHECK-NEXT: [[B2:%.*]] = select i1 [[TMP1]], i64 -1, i64 -2
|
||||
; CHECK-NEXT: [[G11:%.*]] = getelementptr i177, i177* [[A]], i64 [[B2]]
|
||||
; CHECK-NEXT: [[L7:%.*]] = load i177, i177* [[G11]], align 4
|
||||
; CHECK-NEXT: [[B36:%.*]] = select i1 [[TMP1]], i177 0, i177 [[L7]]
|
||||
; CHECK-NEXT: [[C17:%.*]] = icmp sgt i177 [[B36]], [[L7]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = sext i1 [[C17]] to i64
|
||||
; CHECK-NEXT: [[G62:%.*]] = getelementptr i177, i177* [[G11]], i64 [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i177 [[L7]], -1
|
||||
; CHECK-NEXT: [[B28:%.*]] = select i1 [[TMP3]], i177 0, i177 [[L7]]
|
||||
; CHECK-NEXT: store i177 [[B28]], i177* [[G62]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%L = load i177, i177* %A
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
define i32 @a(i1 zeroext %x, i1 zeroext %y) {
|
||||
; CHECK-LABEL: @a(
|
||||
; CHECK-NEXT: [[CONV3_NEG:%.*]] = sext i1 [[Y:%.*]] to i32
|
||||
; CHECK-NEXT: [[SUB:%.*]] = select i1 [[X:%.*]], i32 2, i32 1
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[Y:%.*]] to i32
|
||||
; CHECK-NEXT: [[ADD:%.*]] = sub nsw i32 [[SUB]], [[TMP1]]
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SUB]], [[CONV3_NEG]]
|
||||
; CHECK-NEXT: ret i32 [[ADD]]
|
||||
;
|
||||
%conv = zext i1 %x to i32
|
||||
|
@ -317,8 +317,8 @@ define i8 @sext_sub_nuw(i8 %x, i1 %y) {
|
|||
|
||||
define i32 @sextbool_add(i1 %c, i32 %x) {
|
||||
; CHECK-LABEL: @sextbool_add(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[C:%.*]] to i32
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i32 [[X:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B:%.*]] = sext i1 [[C:%.*]] to i32
|
||||
; CHECK-NEXT: [[S:%.*]] = add i32 [[B]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret i32 [[S]]
|
||||
;
|
||||
%b = sext i1 %c to i32
|
||||
|
@ -329,8 +329,8 @@ define i32 @sextbool_add(i1 %c, i32 %x) {
|
|||
define i32 @sextbool_add_commute(i1 %c, i32 %px) {
|
||||
; CHECK-LABEL: @sextbool_add_commute(
|
||||
; CHECK-NEXT: [[X:%.*]] = urem i32 [[PX:%.*]], 42
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[C:%.*]] to i32
|
||||
; CHECK-NEXT: [[S:%.*]] = sub nsw i32 [[X]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B:%.*]] = sext i1 [[C:%.*]] to i32
|
||||
; CHECK-NEXT: [[S:%.*]] = add nsw i32 [[X]], [[B]]
|
||||
; CHECK-NEXT: ret i32 [[S]]
|
||||
;
|
||||
%x = urem i32 %px, 42 ; thwart complexity-based canonicalization
|
||||
|
@ -358,8 +358,8 @@ define i32 @sextbool_add_uses(i1 %c, i32 %x) {
|
|||
|
||||
define <4 x i32> @sextbool_add_vector(<4 x i1> %c, <4 x i32> %x) {
|
||||
; CHECK-LABEL: @sextbool_add_vector(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i1> [[C:%.*]] to <4 x i32>
|
||||
; CHECK-NEXT: [[S:%.*]] = sub <4 x i32> [[X:%.*]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B:%.*]] = sext <4 x i1> [[C:%.*]] to <4 x i32>
|
||||
; CHECK-NEXT: [[S:%.*]] = add <4 x i32> [[B]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret <4 x i32> [[S]]
|
||||
;
|
||||
%b = sext <4 x i1> %c to <4 x i32>
|
||||
|
@ -393,8 +393,8 @@ define i32 @zextbool_sub_uses(i1 %c, i32 %x) {
|
|||
|
||||
define <4 x i32> @zextbool_sub_vector(<4 x i1> %c, <4 x i32> %x) {
|
||||
; CHECK-LABEL: @zextbool_sub_vector(
|
||||
; CHECK-NEXT: [[B:%.*]] = zext <4 x i1> [[C:%.*]] to <4 x i32>
|
||||
; CHECK-NEXT: [[S:%.*]] = sub <4 x i32> [[X:%.*]], [[B]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i1> [[C:%.*]] to <4 x i32>
|
||||
; CHECK-NEXT: [[S:%.*]] = add <4 x i32> [[TMP1]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret <4 x i32> [[S]]
|
||||
;
|
||||
%b = zext <4 x i1> %c to <4 x i32>
|
||||
|
|
Loading…
Reference in New Issue