From d5b0e54b492f2433d8ea099f5a25254465585a37 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 29 Apr 2016 16:22:25 +0000 Subject: [PATCH] [InstCombine] add helper function for ICmp with constant canonicalization; NFCI As suggested in http://reviews.llvm.org/D17859 , we should enhance this to support vectors. llvm-svn: 268059 --- .../Transforms/InstCombine/InstCombineCompares.cpp | 62 +++++++++++++--------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 52e2229..3bfe49b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3070,6 +3070,41 @@ bool InstCombiner::replacedSelectWithOperand(SelectInst *SI, return false; } +/// If we have an icmp le or icmp ge instruction with a constant operand, turn +/// it into the appropriate icmp lt or icmp gt instruction. This transform +/// allows them to be folded in visitICmpInst. +static ICmpInst *canonicalizeCmpWithConstant(ICmpInst &I, + InstCombiner::BuilderTy &Builder) { + Value *Op0 = I.getOperand(0); + Value *Op1 = I.getOperand(1); + + if (auto *Op1C = dyn_cast(Op1)) { + // For scalars, SimplifyICmpInst has already handled the edge cases for us, + // so we just assert on them. + APInt Op1Val = Op1C->getValue(); + switch (I.getPredicate()) { + case ICmpInst::ICMP_ULE: + assert(!Op1C->isMaxValue(false)); // A <=u MAX -> TRUE + return new ICmpInst(ICmpInst::ICMP_ULT, Op0, Builder.getInt(Op1Val + 1)); + case ICmpInst::ICMP_SLE: + assert(!Op1C->isMaxValue(true)); // A <=s MAX -> TRUE + return new ICmpInst(ICmpInst::ICMP_SLT, Op0, Builder.getInt(Op1Val + 1)); + case ICmpInst::ICMP_UGE: + assert(!Op1C->isMinValue(false)); // A >=u MIN -> TRUE + return new ICmpInst(ICmpInst::ICMP_UGT, Op0, Builder.getInt(Op1Val - 1)); + case ICmpInst::ICMP_SGE: + assert(!Op1C->isMinValue(true)); // A >=s MIN -> TRUE + return new ICmpInst(ICmpInst::ICMP_SGT, Op0, Builder.getInt(Op1Val - 1)); + default: + break; + } + } + + // TODO: Handle vectors. + + return nullptr; +} + Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { bool Changed = false; Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -3153,6 +3188,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } } + if (ICmpInst *NewICmp = canonicalizeCmpWithConstant(I, *Builder)) + return NewICmp; + unsigned BitWidth = 0; if (Ty->isIntOrIntVectorTy()) BitWidth = Ty->getScalarSizeInBits(); @@ -3227,30 +3265,6 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { return new ICmpInst(ICmpInst::ICMP_SLE, A, B); } - // If we have an icmp le or icmp ge instruction, turn it into the - // appropriate icmp lt or icmp gt instruction. This allows us to rely on - // them being folded in the code below. The SimplifyICmpInst code has - // already handled the edge cases for us, so we just assert on them. - switch (I.getPredicate()) { - default: break; - case ICmpInst::ICMP_ULE: - assert(!CI->isMaxValue(false)); // A <=u MAX -> TRUE - return new ICmpInst(ICmpInst::ICMP_ULT, Op0, - Builder->getInt(CI->getValue()+1)); - case ICmpInst::ICMP_SLE: - assert(!CI->isMaxValue(true)); // A <=s MAX -> TRUE - return new ICmpInst(ICmpInst::ICMP_SLT, Op0, - Builder->getInt(CI->getValue()+1)); - case ICmpInst::ICMP_UGE: - assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE - return new ICmpInst(ICmpInst::ICMP_UGT, Op0, - Builder->getInt(CI->getValue()-1)); - case ICmpInst::ICMP_SGE: - assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE - return new ICmpInst(ICmpInst::ICMP_SGT, Op0, - Builder->getInt(CI->getValue()-1)); - } - if (I.isEquality()) { ConstantInt *CI2; if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) || -- 2.7.4