From 2473bf077d3ae81c5977d67c7e5e3b9b31ea2c46 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 15 Sep 2016 18:05:17 +0000 Subject: [PATCH] [InstCombine] allow icmp (sub nsw) folds for vectors Also, clean up the code and comments for the existing folds in foldICmpSubConstant(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281631 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCompares.cpp | 75 +++++++++---------- test/Transforms/InstCombine/icmp.ll | 12 +-- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index f14b818c594..87165424c71 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1420,30 +1420,6 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &Cmp) { if (!CI) return nullptr; - // The following transforms are only worth it if the only user of the subtract - // is the icmp. - if (X->hasOneUse()) { - // (icmp sgt (sub nsw A B), -1) -> (icmp sge A, B) - if (Pred == ICmpInst::ICMP_SGT && CI->isAllOnesValue() && - match(X, m_NSWSub(m_Value(A), m_Value(B)))) - return new ICmpInst(ICmpInst::ICMP_SGE, A, B); - - // (icmp sgt (sub nsw A B), 0) -> (icmp sgt A, B) - if (Pred == ICmpInst::ICMP_SGT && CI->isZero() && - match(X, m_NSWSub(m_Value(A), m_Value(B)))) - return new ICmpInst(ICmpInst::ICMP_SGT, A, B); - - // (icmp slt (sub nsw A B), 0) -> (icmp slt A, B) - if (Pred == ICmpInst::ICMP_SLT && CI->isZero() && - match(X, m_NSWSub(m_Value(A), m_Value(B)))) - return new ICmpInst(ICmpInst::ICMP_SLT, A, B); - - // (icmp slt (sub nsw A B), 1) -> (icmp sle A, B) - if (Pred == ICmpInst::ICMP_SLT && CI->isOne() && - match(X, m_NSWSub(m_Value(A), m_Value(B)))) - return new ICmpInst(ICmpInst::ICMP_SLE, A, B); - } - if (Cmp.isEquality()) { ConstantInt *CI2; if (match(X, m_AShr(m_ConstantInt(CI2), m_Value(A))) || @@ -2306,27 +2282,46 @@ Instruction *InstCombiner::foldICmpDivConstant(ICmpInst &Cmp, Instruction *InstCombiner::foldICmpSubConstant(ICmpInst &Cmp, BinaryOperator *Sub, const APInt *C) { + Value *X = Sub->getOperand(0), *Y = Sub->getOperand(1); + ICmpInst::Predicate Pred = Cmp.getPredicate(); + + // The following transforms are only worth it if the only user of the subtract + // is the icmp. + if (!Sub->hasOneUse()) + return nullptr; + + if (Sub->hasNoSignedWrap()) { + // (icmp sgt (sub nsw X, Y), -1) -> (icmp sge X, Y) + if (Pred == ICmpInst::ICMP_SGT && C->isAllOnesValue()) + return new ICmpInst(ICmpInst::ICMP_SGE, X, Y); + + // (icmp sgt (sub nsw X, Y), 0) -> (icmp sgt X, Y) + if (Pred == ICmpInst::ICMP_SGT && *C == 0) + return new ICmpInst(ICmpInst::ICMP_SGT, X, Y); + + // (icmp slt (sub nsw X, Y), 0) -> (icmp slt X, Y) + if (Pred == ICmpInst::ICMP_SLT && *C == 0) + return new ICmpInst(ICmpInst::ICMP_SLT, X, Y); + + // (icmp slt (sub nsw X, Y), 1) -> (icmp sle X, Y) + if (Pred == ICmpInst::ICMP_SLT && *C == 1) + return new ICmpInst(ICmpInst::ICMP_SLE, X, Y); + } + const APInt *C2; - if (!match(Sub->getOperand(0), m_APInt(C2)) || !Sub->hasOneUse()) + if (!match(X, m_APInt(C2))) return nullptr; - // C-X (X|(C2-1)) == C - // iff C & (C2-1) == C2-1 - // C2 is a power of 2 - if (Cmp.getPredicate() == ICmpInst::ICMP_ULT && C->isPowerOf2() && + // C2 - Y (Y | (C - 1)) == C2 + // iff (C2 & (C - 1)) == C - 1 and C is a power of 2 + if (Pred == ICmpInst::ICMP_ULT && C->isPowerOf2() && (*C2 & (*C - 1)) == (*C - 1)) - return new ICmpInst(ICmpInst::ICMP_EQ, - Builder->CreateOr(Sub->getOperand(1), *C - 1), - Sub->getOperand(0)); + return new ICmpInst(ICmpInst::ICMP_EQ, Builder->CreateOr(Y, *C - 1), X); - // C-X >u C2 -> (X|C2) != C - // iff C & C2 == C2 - // C2+1 is a power of 2 - if (Cmp.getPredicate() == ICmpInst::ICMP_UGT && (*C + 1).isPowerOf2() && - (*C2 & *C) == *C) - return new ICmpInst(ICmpInst::ICMP_NE, - Builder->CreateOr(Sub->getOperand(1), *C), - Sub->getOperand(0)); + // C2 - Y >u C -> (Y | C) != C2 + // iff C2 & C == C and C + 1 is a power of 2 + if (Pred == ICmpInst::ICMP_UGT && (*C + 1).isPowerOf2() && (*C2 & *C) == *C) + return new ICmpInst(ICmpInst::ICMP_NE, Builder->CreateOr(Y, *C), X); return nullptr; } diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index b315c03c1f5..a2b5707ce69 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -2315,8 +2315,7 @@ define i1 @f1(i64 %a, i64 %b) { define <2 x i1> @f1_vec(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @f1_vec( -; CHECK-NEXT: [[T:%.*]] = sub nsw <2 x i64> %a, %b -; CHECK-NEXT: [[V:%.*]] = icmp sgt <2 x i64> [[T]], +; CHECK-NEXT: [[V:%.*]] = icmp sge <2 x i64> %a, %b ; CHECK-NEXT: ret <2 x i1> [[V]] ; %t = sub nsw <2 x i64> %a, %b @@ -2336,8 +2335,7 @@ define i1 @f2(i64 %a, i64 %b) { define <2 x i1> @f2_vec(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @f2_vec( -; CHECK-NEXT: [[T:%.*]] = sub nsw <2 x i64> %a, %b -; CHECK-NEXT: [[V:%.*]] = icmp sgt <2 x i64> [[T]], zeroinitializer +; CHECK-NEXT: [[V:%.*]] = icmp sgt <2 x i64> %a, %b ; CHECK-NEXT: ret <2 x i1> [[V]] ; %t = sub nsw <2 x i64> %a, %b @@ -2357,8 +2355,7 @@ define i1 @f3(i64 %a, i64 %b) { define <2 x i1> @f3_vec(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @f3_vec( -; CHECK-NEXT: [[T:%.*]] = sub nsw <2 x i64> %a, %b -; CHECK-NEXT: [[V:%.*]] = icmp slt <2 x i64> [[T]], zeroinitializer +; CHECK-NEXT: [[V:%.*]] = icmp slt <2 x i64> %a, %b ; CHECK-NEXT: ret <2 x i1> [[V]] ; %t = sub nsw <2 x i64> %a, %b @@ -2378,8 +2375,7 @@ define i1 @f4(i64 %a, i64 %b) { define <2 x i1> @f4_vec(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @f4_vec( -; CHECK-NEXT: [[T:%.*]] = sub nsw <2 x i64> %a, %b -; CHECK-NEXT: [[V:%.*]] = icmp slt <2 x i64> [[T]], +; CHECK-NEXT: [[V:%.*]] = icmp sle <2 x i64> %a, %b ; CHECK-NEXT: ret <2 x i1> [[V]] ; %t = sub nsw <2 x i64> %a, %b -- 2.50.1