[InstCombine] clean up foldICmpDivConstant; NFCI

1. Fix comments to match variable names
2. Remove redundant CmpRHS variable
3. Add FIXME to replace some checks with asserts

llvm-svn: 280112
This commit is contained in:
Sanjay Patel 2016-08-30 17:10:49 +00:00
parent fddfdca030
commit a7cb477277
1 changed files with 20 additions and 16 deletions

View File

@ -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<ConstantInt>(Cmp.getOperand(1));
if (!RHS)
return nullptr;
// Fold: icmp pred ([us]div X, C1), C2 -> range test
ConstantInt *DivRHS = dyn_cast<ConstantInt>(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<ConstantInt>(Div->getOperand(1));
if (!DivRHS)
const APInt *C2;
if (!match(Div->getOperand(1), m_APInt(C2)))
return nullptr;
ConstantInt *CmpRHS = cast<ConstantInt>(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) <s C2 produces different
// results than (x /s C1) <u C2 or (x /u C1) <s C2 or even
// (x /u C1) <u C2. Simply casting the operands and result won't
// vice versa). This is because (x /s C2) <s C produces different
// results than (x /s C2) <u C or (x /u C2) <s C or even
// (x /u C2) <u C. Simply casting the operands and result won't
// work. :( The if statement below tests that condition and bails
// if it finds it.
bool DivIsSigned = Div->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();