diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 81dcbb761dba..d3155e13c4da 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1971,55 +1971,59 @@ Instruction *InstCombiner::foldICmpUDivConstant(ICmpInst &Cmp, Instruction *InstCombiner::foldICmpDivConstant(ICmpInst &Cmp, BinaryOperator *Div, const APInt *C) { - // FIXME: This check restricts all folds under here to scalar types. + // FIXME: These checks restrict all folds under here to scalar types. ConstantInt *RHS = dyn_cast(Cmp.getOperand(1)); if (!RHS) return nullptr; - // Fold: icmp pred ([us]div X, C1), C2 -> range test + ConstantInt *DivRHS = dyn_cast(Div->getOperand(1)); + if (!DivRHS) + return nullptr; + + // Fold: icmp pred ([us]div X, C2), C -> range test // Fold this div into the comparison, producing a range check. // Determine, based on the divide type, what the range is being // checked. If there is an overflow on the low or high side, remember // it, otherwise compute the range [low, hi) bounding the new value. // See: InsertRangeTest above for the kinds of replacements possible. - ConstantInt *DivRHS = dyn_cast(Div->getOperand(1)); - if (!DivRHS) + const APInt *C2; + if (!match(Div->getOperand(1), m_APInt(C2))) return nullptr; - ConstantInt *CmpRHS = cast(Cmp.getOperand(1)); - // FIXME: If the operand types don't match the type of the divide // then don't attempt this transform. The code below doesn't have the // logic to deal with a signed divide and an unsigned compare (and - // vice versa). This is because (x /s C1) getOpcode() == Instruction::SDiv; if (!Cmp.isEquality() && DivIsSigned != Cmp.isSigned()) return nullptr; - if (DivRHS->isZero()) + + // FIXME: These 3 checks can be asserts. + if (*C2 == 0) return nullptr; // The ProdOV computation fails on divide by zero. - if (DivIsSigned && DivRHS->isAllOnesValue()) + if (DivIsSigned && C2->isAllOnesValue()) return nullptr; // The overflow computation also screws up here - if (DivRHS->isOne()) { + if (*C2 == 1) { // This eliminates some funny cases with INT_MIN. Cmp.setOperand(0, Div->getOperand(0)); // X/1 == X. return &Cmp; } // Compute Prod = CI * DivRHS. We are essentially solving an equation - // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and - // C2 (CI). By solving for X we can turn this into a range check + // of form X/C2=C. We solve for X by multiplying C2 (DivRHS) and + // C (CI). By solving for X we can turn this into a range check // instead of computing a divide. - Constant *Prod = ConstantExpr::getMul(CmpRHS, DivRHS); + Constant *Prod = ConstantExpr::getMul(RHS, DivRHS); // Determine if the product overflows by seeing if the product is // not equal to the divide. Make sure we do the same kind of divide // as in the LHS instruction that we're folding. bool ProdOV = (DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) : - ConstantExpr::getUDiv(Prod, DivRHS)) != CmpRHS; + ConstantExpr::getUDiv(Prod, DivRHS)) != RHS; // Get the ICmp opcode ICmpInst::Predicate Pred = Cmp.getPredicate();