From fd8c14ece26b616538f29ca6417e47f2d71f8150 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 23 Aug 2016 21:25:13 +0000 Subject: [PATCH] [InstCombine] move foldICmpShrConstConst() contents to foldICmpShrConst(); NFCI There will only be 3 lines of code in foldICmpShrConst() when the cleanup is done, so it doesn't make much sense to have a separate function for a single fold. llvm-svn: 279575 --- .../InstCombine/InstCombineCompares.cpp | 140 ++++++++---------- .../InstCombine/InstCombineInternal.h | 2 - 2 files changed, 65 insertions(+), 77 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 4c1d9676d9e..a59c188fc6c 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1336,80 +1336,6 @@ Instruction *InstCombiner::foldICmpDivConstConst(ICmpInst &ICI, } } -/// Handle "icmp(([al]shr X, cst1), cst2)". -Instruction *InstCombiner::foldICmpShrConstConst(ICmpInst &ICI, - BinaryOperator *Shr, - ConstantInt *ShAmt) { - const APInt &CmpRHSV = cast(ICI.getOperand(1))->getValue(); - - // Check that the shift amount is in range. If not, don't perform - // undefined shifts. When the shift is visited it will be - // simplified. - uint32_t TypeBits = CmpRHSV.getBitWidth(); - uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits); - if (ShAmtVal >= TypeBits || ShAmtVal == 0) - return nullptr; - - if (!ICI.isEquality()) { - // If we have an unsigned comparison and an ashr, we can't simplify this. - // Similarly for signed comparisons with lshr. - if (ICI.isSigned() != (Shr->getOpcode() == Instruction::AShr)) - return nullptr; - - // Otherwise, all lshr and most exact ashr's are equivalent to a udiv/sdiv - // by a power of 2. Since we already have logic to simplify these, - // transform to div and then simplify the resultant comparison. - if (Shr->getOpcode() == Instruction::AShr && - (!Shr->isExact() || ShAmtVal == TypeBits - 1)) - return nullptr; - - // Revisit the shift (to delete it). - Worklist.Add(Shr); - - Constant *DivCst = - ConstantInt::get(Shr->getType(), APInt::getOneBitSet(TypeBits, ShAmtVal)); - - Value *Tmp = - Shr->getOpcode() == Instruction::AShr ? - Builder->CreateSDiv(Shr->getOperand(0), DivCst, "", Shr->isExact()) : - Builder->CreateUDiv(Shr->getOperand(0), DivCst, "", Shr->isExact()); - - ICI.setOperand(0, Tmp); - - // If the builder folded the binop, just return it. - BinaryOperator *TheDiv = dyn_cast(Tmp); - if (!TheDiv) - return &ICI; - - // Otherwise, fold this div/compare. - assert(TheDiv->getOpcode() == Instruction::SDiv || - TheDiv->getOpcode() == Instruction::UDiv); - - Instruction *Res = - foldICmpDivConstConst(ICI, TheDiv, cast(DivCst)); - assert(Res && "This div/cst should have folded!"); - return Res; - } - - // Check if the bits shifted out are known to be zero. If so, we can compare - // against the unshifted value: - // (X & 4) >> 1 == 2 --> (X & 4) == 4. - ConstantInt *ShiftedCmpRHS = Builder->getInt(CmpRHSV << ShAmtVal); - if (Shr->hasOneUse() && Shr->isExact()) - return new ICmpInst(ICI.getPredicate(), Shr->getOperand(0), ShiftedCmpRHS); - - if (Shr->hasOneUse()) { - // Otherwise strength reduce the shift into an and. - APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal)); - Constant *Mask = Builder->getInt(Val); - - Value *And = Builder->CreateAnd(Shr->getOperand(0), - Mask, Shr->getName()+".mask"); - return new ICmpInst(ICI.getPredicate(), And, ShiftedCmpRHS); - } - return nullptr; -} - /// Handle "(icmp eq/ne (ashr/lshr const2, A), const1)" -> /// (icmp eq/ne A, Log2(const2/const1)) -> /// (icmp eq/ne A, Log2(const2) - Log2(const1)). @@ -2067,8 +1993,72 @@ Instruction *InstCombiner::foldICmpShrConstant(ICmpInst &Cmp, if (!ShAmt) return nullptr; - if (Instruction *Res = foldICmpShrConstConst(Cmp, Shr, ShAmt)) + // Check that the shift amount is in range. If not, don't perform + // undefined shifts. When the shift is visited it will be + // simplified. + uint32_t TypeBits = C->getBitWidth(); + uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits); + if (ShAmtVal >= TypeBits || ShAmtVal == 0) + return nullptr; + + if (!Cmp.isEquality()) { + // If we have an unsigned comparison and an ashr, we can't simplify this. + // Similarly for signed comparisons with lshr. + if (Cmp.isSigned() != (Shr->getOpcode() == Instruction::AShr)) + return nullptr; + + // Otherwise, all lshr and most exact ashr's are equivalent to a udiv/sdiv + // by a power of 2. Since we already have logic to simplify these, + // transform to div and then simplify the resultant comparison. + if (Shr->getOpcode() == Instruction::AShr && + (!Shr->isExact() || ShAmtVal == TypeBits - 1)) + return nullptr; + + // Revisit the shift (to delete it). + Worklist.Add(Shr); + + Constant *DivCst = ConstantInt::get( + Shr->getType(), APInt::getOneBitSet(TypeBits, ShAmtVal)); + + Value *Tmp = Shr->getOpcode() == Instruction::AShr + ? Builder->CreateSDiv(Shr->getOperand(0), DivCst, "", + Shr->isExact()) + : Builder->CreateUDiv(Shr->getOperand(0), DivCst, "", + Shr->isExact()); + + Cmp.setOperand(0, Tmp); + + // If the builder folded the binop, just return it. + BinaryOperator *TheDiv = dyn_cast(Tmp); + if (!TheDiv) + return &Cmp; + + // Otherwise, fold this div/compare. + assert(TheDiv->getOpcode() == Instruction::SDiv || + TheDiv->getOpcode() == Instruction::UDiv); + + Instruction *Res = + foldICmpDivConstConst(Cmp, TheDiv, cast(DivCst)); + assert(Res && "This div/cst should have folded!"); return Res; + } + + // Check if the bits shifted out are known to be zero. If so, we can compare + // against the unshifted value: + // (X & 4) >> 1 == 2 --> (X & 4) == 4. + ConstantInt *ShiftedCmpRHS = Builder->getInt(*C << ShAmtVal); + if (Shr->hasOneUse() && Shr->isExact()) + return new ICmpInst(Pred, Shr->getOperand(0), ShiftedCmpRHS); + + if (Shr->hasOneUse()) { + // Otherwise strength reduce the shift into an and. + APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal)); + Constant *Mask = Builder->getInt(Val); + + Value *And = + Builder->CreateAnd(Shr->getOperand(0), Mask, Shr->getName() + ".mask"); + return new ICmpInst(Pred, And, ShiftedCmpRHS); + } return nullptr; } diff --git a/lib/Transforms/InstCombine/InstCombineInternal.h b/lib/Transforms/InstCombine/InstCombineInternal.h index f3ee94a9784..8f2a7f45dc8 100644 --- a/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/lib/Transforms/InstCombine/InstCombineInternal.h @@ -550,8 +550,6 @@ private: Constant *RHSC); Instruction *foldICmpDivConstConst(ICmpInst &ICI, BinaryOperator *DivI, ConstantInt *DivRHS); - Instruction *foldICmpShrConstConst(ICmpInst &ICI, BinaryOperator *DivI, - ConstantInt *DivRHS); Instruction *foldICmpCstShrConst(ICmpInst &I, Value *Op, Value *A, ConstantInt *CI1, ConstantInt *CI2); Instruction *foldICmpCstShlConst(ICmpInst &I, Value *Op, Value *A,