From: David Majnemer Date: Sun, 12 Oct 2014 08:34:24 +0000 (+0000) Subject: InstCombine: Simplify commonIDivTransforms X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=05f7e38c0bb8ff1cdb6546a4a991b2c8793264cf;p=oota-llvm.git InstCombine: Simplify commonIDivTransforms A helper routine, MultiplyOverflows, was a less efficient reimplementation of APInt's smul_ov and umul_ov. While we are here, clean up the code so it's more uniform. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219583 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index b09198afff2..dad2c2d256d 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -81,25 +81,15 @@ static Value *simplifyValueKnownNonZero(Value *V, InstCombiner &IC, /// MultiplyOverflows - True if the multiply can not be expressed in an int /// this size. -static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) { - uint32_t W = C1->getBitWidth(); - APInt LHSExt = C1->getValue(), RHSExt = C2->getValue(); - if (sign) { - LHSExt = LHSExt.sext(W * 2); - RHSExt = RHSExt.sext(W * 2); - } else { - LHSExt = LHSExt.zext(W * 2); - RHSExt = RHSExt.zext(W * 2); - } - - APInt MulExt = LHSExt * RHSExt; - - if (!sign) - return MulExt.ugt(APInt::getLowBitsSet(W * 2, W)); +static bool MultiplyOverflows(const APInt &C1, const APInt &C2, APInt &Product, + bool IsSigned) { + bool Overflow; + if (IsSigned) + Product = C1.smul_ov(C2, Overflow); + else + Product = C1.umul_ov(C2, Overflow); - APInt Min = APInt::getSignedMinValue(W).sext(W * 2); - APInt Max = APInt::getSignedMaxValue(W).sext(W * 2); - return MulExt.slt(Min) || MulExt.sgt(Max); + return Overflow; } /// \brief True if C2 is a multiple of C1. Quotient contains C2/C1. @@ -722,83 +712,83 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { if (isa(Op1) && SimplifyDivRemOfSelect(I)) return &I; - if (ConstantInt *RHS = dyn_cast(Op1)) { - if (Instruction *LHS = dyn_cast(Op0)) { + if (Instruction *LHS = dyn_cast(Op0)) { + const APInt *C2; + if (match(Op1, m_APInt(C2))) { + Value *X; + const APInt *C1; + bool IsSigned = I.getOpcode() == Instruction::SDiv; + // (X / C1) / C2 -> X / (C1*C2) - if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode()) - if (ConstantInt *LHSRHS = dyn_cast(LHS->getOperand(1))) { - if (!MultiplyOverflows(RHS, LHSRHS, - I.getOpcode() == Instruction::SDiv)) - return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0), - ConstantExpr::getMul(RHS, LHSRHS)); - } + if ((IsSigned && match(LHS, m_SDiv(m_Value(X), m_APInt(C1)))) || + (!IsSigned && match(LHS, m_UDiv(m_Value(X), m_APInt(C1))))) { + APInt Product(C1->getBitWidth(), /*Val=*/0ULL, IsSigned); + if (!MultiplyOverflows(*C1, *C2, Product, IsSigned)) + return BinaryOperator::Create(I.getOpcode(), X, + ConstantInt::get(I.getType(), Product)); + } - Value *X; - const APInt *C1, *C2; - if (match(RHS, m_APInt(C2))) { - bool IsSigned = I.getOpcode() == Instruction::SDiv; - if ((IsSigned && match(LHS, m_NSWMul(m_Value(X), m_APInt(C1)))) || - (!IsSigned && match(LHS, m_NUWMul(m_Value(X), m_APInt(C1))))) { - APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned); - - // (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1. - if (IsMultiple(*C2, *C1, Quotient, IsSigned)) { - BinaryOperator *BO = BinaryOperator::Create( - I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient)); - BO->setIsExact(I.isExact()); - return BO; - } + if ((IsSigned && match(LHS, m_NSWMul(m_Value(X), m_APInt(C1)))) || + (!IsSigned && match(LHS, m_NUWMul(m_Value(X), m_APInt(C1))))) { + APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned); - // (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2. - if (IsMultiple(*C1, *C2, Quotient, IsSigned)) { - BinaryOperator *BO = BinaryOperator::Create( - Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient)); - BO->setHasNoUnsignedWrap( - !IsSigned && - cast(LHS)->hasNoUnsignedWrap()); - BO->setHasNoSignedWrap( - cast(LHS)->hasNoSignedWrap()); - return BO; - } + // (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1. + if (IsMultiple(*C2, *C1, Quotient, IsSigned)) { + BinaryOperator *BO = BinaryOperator::Create( + I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient)); + BO->setIsExact(I.isExact()); + return BO; } - if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1))) && - *C1 != C1->getBitWidth() - 1) || - (!IsSigned && match(LHS, m_NUWShl(m_Value(X), m_APInt(C1))))) { - APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned); - APInt C1Shifted = APInt::getOneBitSet( - C1->getBitWidth(), static_cast(C1->getLimitedValue())); - - // (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of C1. - if (IsMultiple(*C2, C1Shifted, Quotient, IsSigned)) { - BinaryOperator *BO = BinaryOperator::Create( - I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient)); - BO->setIsExact(I.isExact()); - return BO; - } + // (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2. + if (IsMultiple(*C1, *C2, Quotient, IsSigned)) { + BinaryOperator *BO = BinaryOperator::Create( + Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient)); + BO->setHasNoUnsignedWrap( + !IsSigned && + cast(LHS)->hasNoUnsignedWrap()); + BO->setHasNoSignedWrap( + cast(LHS)->hasNoSignedWrap()); + return BO; + } + } - // (X << C1) / C2 -> X * (C2 >> C1) if C1 is a multiple of C2. - if (IsMultiple(C1Shifted, *C2, Quotient, IsSigned)) { - BinaryOperator *BO = BinaryOperator::Create( - Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient)); - BO->setHasNoUnsignedWrap( - !IsSigned && - cast(LHS)->hasNoUnsignedWrap()); - BO->setHasNoSignedWrap( - cast(LHS)->hasNoSignedWrap()); - return BO; - } + if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1))) && + *C1 != C1->getBitWidth() - 1) || + (!IsSigned && match(LHS, m_NUWShl(m_Value(X), m_APInt(C1))))) { + APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned); + APInt C1Shifted = APInt::getOneBitSet( + C1->getBitWidth(), static_cast(C1->getLimitedValue())); + + // (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of C1. + if (IsMultiple(*C2, C1Shifted, Quotient, IsSigned)) { + BinaryOperator *BO = BinaryOperator::Create( + I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient)); + BO->setIsExact(I.isExact()); + return BO; + } + + // (X << C1) / C2 -> X * (C2 >> C1) if C1 is a multiple of C2. + if (IsMultiple(C1Shifted, *C2, Quotient, IsSigned)) { + BinaryOperator *BO = BinaryOperator::Create( + Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient)); + BO->setHasNoUnsignedWrap( + !IsSigned && + cast(LHS)->hasNoUnsignedWrap()); + BO->setHasNoSignedWrap( + cast(LHS)->hasNoSignedWrap()); + return BO; } } - } - if (!RHS->isZero()) { // avoid X udiv 0 - if (SelectInst *SI = dyn_cast(Op0)) - if (Instruction *R = FoldOpIntoSelect(I, SI)) - return R; - if (isa(Op0)) - if (Instruction *NV = FoldOpIntoPhi(I)) - return NV; + if (*C2 != 0) { // avoid X udiv 0 + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldOpIntoSelect(I, SI)) + return R; + if (isa(Op0)) + if (Instruction *NV = FoldOpIntoPhi(I)) + return NV; + } } }