From: Simon Pilgrim Date: Thu, 10 Mar 2022 13:30:42 +0000 (+0000) Subject: [InstCombine] Add vector support to icmp(add(X,C1),add(Y,C2)) -> icmp(add(X,C1-C2... X-Git-Tag: upstream/15.0.7~14041 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=808d9d260bdfbd485082d71f120661dfa7a8405e;p=platform%2Fupstream%2Fllvm.git [InstCombine] Add vector support to icmp(add(X,C1),add(Y,C2)) -> icmp(add(X,C1-C2),Y) fold As discussed on Issue #32161 this fold can be generalized a lot more than it currently is, but this patch at least adds vector support. Differential Revision: https://reviews.llvm.org/D121358 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7d4e9b5..e405dc7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4110,29 +4110,31 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, // icmp (A + C1), (C + C2) -> icmp A, (C + C3) // s.t. C3 = C2 - C1 if (A && C && NoOp0WrapProblem && NoOp1WrapProblem && - (BO0->hasOneUse() || BO1->hasOneUse()) && !I.isUnsigned()) - if (ConstantInt *C1 = dyn_cast(B)) - if (ConstantInt *C2 = dyn_cast(D)) { - const APInt &AP1 = C1->getValue(); - const APInt &AP2 = C2->getValue(); - if (AP1.isNegative() == AP2.isNegative()) { - APInt AP1Abs = C1->getValue().abs(); - APInt AP2Abs = C2->getValue().abs(); - if (AP1Abs.uge(AP2Abs)) { - ConstantInt *C3 = Builder.getInt(AP1 - AP2); - bool HasNUW = BO0->hasNoUnsignedWrap() && C3->getValue().ule(AP1); - bool HasNSW = BO0->hasNoSignedWrap(); - Value *NewAdd = Builder.CreateAdd(A, C3, "", HasNUW, HasNSW); - return new ICmpInst(Pred, NewAdd, C); - } else { - ConstantInt *C3 = Builder.getInt(AP2 - AP1); - bool HasNUW = BO1->hasNoUnsignedWrap() && C3->getValue().ule(AP2); - bool HasNSW = BO1->hasNoSignedWrap(); - Value *NewAdd = Builder.CreateAdd(C, C3, "", HasNUW, HasNSW); - return new ICmpInst(Pred, A, NewAdd); - } - } + (BO0->hasOneUse() || BO1->hasOneUse()) && !I.isUnsigned()) { + const APInt *AP1, *AP2; + // TODO: Support non-uniform vectors. + // TODO: Allow undef passthrough if B AND D's element is undef. + if (match(B, m_APIntAllowUndef(AP1)) && match(D, m_APIntAllowUndef(AP2)) && + AP1->isNegative() == AP2->isNegative()) { + APInt AP1Abs = AP1->abs(); + APInt AP2Abs = AP2->abs(); + if (AP1Abs.uge(AP2Abs)) { + APInt Diff = *AP1 - *AP2; + bool HasNUW = BO0->hasNoUnsignedWrap() && Diff.ule(*AP1); + bool HasNSW = BO0->hasNoSignedWrap(); + Constant *C3 = Constant::getIntegerValue(BO0->getType(), Diff); + Value *NewAdd = Builder.CreateAdd(A, C3, "", HasNUW, HasNSW); + return new ICmpInst(Pred, NewAdd, C); + } else { + APInt Diff = *AP2 - *AP1; + bool HasNUW = BO1->hasNoUnsignedWrap() && Diff.ule(*AP2); + bool HasNSW = BO1->hasNoSignedWrap(); + Constant *C3 = Constant::getIntegerValue(BO0->getType(), Diff); + Value *NewAdd = Builder.CreateAdd(C, C3, "", HasNUW, HasNSW); + return new ICmpInst(Pred, A, NewAdd); } + } + } // Analyze the case when either Op0 or Op1 is a sub instruction. // Op0 = A - B (or A and B are null); Op1 = C - D (or C and D are null). diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 8da2ed3..3c8f86c 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -1581,9 +1581,8 @@ define i1 @icmp_add20_sge_add57(i32 %x, i32 %y) { define <2 x i1> @icmp_add20_sge_add57_splat(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @icmp_add20_sge_add57_splat( -; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[Y:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i32> [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %1 = add nsw <2 x i32> %x, @@ -1594,9 +1593,8 @@ define <2 x i1> @icmp_add20_sge_add57_splat(<2 x i32> %x, <2 x i32> %y) { define <2 x i1> @icmp_add20_sge_add57_undef(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @icmp_add20_sge_add57_undef( -; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[Y:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i32> [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %1 = add nsw <2 x i32> %x, @@ -1632,9 +1630,8 @@ define i1 @icmp_sub57_sge_sub20(i32 %x, i32 %y) { define <2 x i1> @icmp_sub57_sge_sub20_splat(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @icmp_sub57_sge_sub20_splat( -; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[Y:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %1 = add nsw <2 x i32> %x, @@ -1645,9 +1642,8 @@ define <2 x i1> @icmp_sub57_sge_sub20_splat(<2 x i32> %x, <2 x i32> %y) { define <2 x i1> @icmp_sub57_sge_sub20_vec_undef(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @icmp_sub57_sge_sub20_vec_undef( -; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[Y:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sge <2 x i32> [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %1 = add nsw <2 x i32> %x,