forked from OSchip/llvm-project
[InstCombine] reduce code duplication in foldICmpMulConstant(); NFC
This commit is contained in:
parent
67e2298311
commit
6174da2299
|
@ -2053,31 +2053,32 @@ Instruction *InstCombinerImpl::foldICmpOrConstant(ICmpInst &Cmp,
|
||||||
Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
|
Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
|
||||||
BinaryOperator *Mul,
|
BinaryOperator *Mul,
|
||||||
const APInt &C) {
|
const APInt &C) {
|
||||||
|
ICmpInst::Predicate Pred = Cmp.getPredicate();
|
||||||
|
Type *MulTy = Mul->getType();
|
||||||
|
Value *X = Mul->getOperand(0);
|
||||||
|
|
||||||
// If there's no overflow:
|
// If there's no overflow:
|
||||||
// X * X == 0 --> X == 0
|
// X * X == 0 --> X == 0
|
||||||
// X * X != 0 --> X != 0
|
// X * X != 0 --> X != 0
|
||||||
Type *MulTy = Mul->getType();
|
if (Cmp.isEquality() && C.isZero() && X == Mul->getOperand(1) &&
|
||||||
if (Cmp.isEquality() && C.isZero() &&
|
|
||||||
Mul->getOperand(0) == Mul->getOperand(1) &&
|
|
||||||
(Mul->hasNoUnsignedWrap() || Mul->hasNoSignedWrap()))
|
(Mul->hasNoUnsignedWrap() || Mul->hasNoSignedWrap()))
|
||||||
return new ICmpInst(Cmp.getPredicate(), Mul->getOperand(0),
|
return new ICmpInst(Pred, X, ConstantInt::getNullValue(MulTy));
|
||||||
ConstantInt::getNullValue(MulTy));
|
|
||||||
|
|
||||||
const APInt *MulC;
|
const APInt *MulC;
|
||||||
if (!match(Mul->getOperand(1), m_APInt(MulC)))
|
if (!match(Mul->getOperand(1), m_APInt(MulC)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// If this is a test of the sign bit and the multiply is sign-preserving with
|
// If this is a test of the sign bit and the multiply is sign-preserving with
|
||||||
// a constant operand, use the multiply LHS operand instead.
|
// a constant operand, use the multiply LHS operand instead:
|
||||||
ICmpInst::Predicate Pred = Cmp.getPredicate();
|
// (X * +MulC) < 0 --> X < 0
|
||||||
|
// (X * -MulC) < 0 --> X > 0
|
||||||
if (isSignTest(Pred, C) && Mul->hasNoSignedWrap()) {
|
if (isSignTest(Pred, C) && Mul->hasNoSignedWrap()) {
|
||||||
if (MulC->isNegative())
|
if (MulC->isNegative())
|
||||||
Pred = ICmpInst::getSwappedPredicate(Pred);
|
Pred = ICmpInst::getSwappedPredicate(Pred);
|
||||||
return new ICmpInst(Pred, Mul->getOperand(0),
|
return new ICmpInst(Pred, X, ConstantInt::getNullValue(MulTy));
|
||||||
Constant::getNullValue(Mul->getType()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MulC->isZero() || !(Mul->hasNoSignedWrap() || Mul->hasNoUnsignedWrap()))
|
if (MulC->isZero() || (!Mul->hasNoSignedWrap() && !Mul->hasNoUnsignedWrap()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// If the multiply does not wrap, try to divide the compare constant by the
|
// If the multiply does not wrap, try to divide the compare constant by the
|
||||||
|
@ -2085,48 +2086,45 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
|
||||||
if (Cmp.isEquality()) {
|
if (Cmp.isEquality()) {
|
||||||
// (mul nsw X, MulC) == C --> X == C /s MulC
|
// (mul nsw X, MulC) == C --> X == C /s MulC
|
||||||
if (Mul->hasNoSignedWrap() && C.srem(*MulC).isZero()) {
|
if (Mul->hasNoSignedWrap() && C.srem(*MulC).isZero()) {
|
||||||
Constant *NewC = ConstantInt::get(Mul->getType(), C.sdiv(*MulC));
|
Constant *NewC = ConstantInt::get(MulTy, C.sdiv(*MulC));
|
||||||
return new ICmpInst(Pred, Mul->getOperand(0), NewC);
|
return new ICmpInst(Pred, X, NewC);
|
||||||
}
|
}
|
||||||
// (mul nuw X, MulC) == C --> X == C /u MulC
|
// (mul nuw X, MulC) == C --> X == C /u MulC
|
||||||
if (Mul->hasNoUnsignedWrap() && C.urem(*MulC).isZero()) {
|
if (Mul->hasNoUnsignedWrap() && C.urem(*MulC).isZero()) {
|
||||||
Constant *NewC = ConstantInt::get(Mul->getType(), C.udiv(*MulC));
|
Constant *NewC = ConstantInt::get(MulTy, C.udiv(*MulC));
|
||||||
return new ICmpInst(Pred, Mul->getOperand(0), NewC);
|
return new ICmpInst(Pred, X, NewC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With a matching no-overflow guarantee, fold the constants:
|
||||||
|
// (X * MulC) < C --> X < (C / MulC)
|
||||||
|
// (X * MulC) > C --> X > (C / MulC)
|
||||||
|
// TODO: Assert that Pred is not equal to SGE, SLE, UGE, ULE?
|
||||||
Constant *NewC = nullptr;
|
Constant *NewC = nullptr;
|
||||||
|
|
||||||
// FIXME: Add assert that Pred is not equal to ICMP_SGE, ICMP_SLE,
|
|
||||||
// ICMP_UGE, ICMP_ULE.
|
|
||||||
|
|
||||||
if (Mul->hasNoSignedWrap()) {
|
if (Mul->hasNoSignedWrap()) {
|
||||||
if (MulC->isNegative()) {
|
// MININT / -1 --> overflow.
|
||||||
// MININT / -1 --> overflow.
|
if (C.isMinSignedValue() && MulC->isAllOnes())
|
||||||
if (C.isMinSignedValue() && MulC->isAllOnes())
|
return nullptr;
|
||||||
return nullptr;
|
if (MulC->isNegative())
|
||||||
Pred = ICmpInst::getSwappedPredicate(Pred);
|
Pred = ICmpInst::getSwappedPredicate(Pred);
|
||||||
}
|
|
||||||
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE)
|
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE)
|
||||||
NewC = ConstantInt::get(
|
NewC = ConstantInt::get(
|
||||||
Mul->getType(),
|
MulTy, APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::UP));
|
||||||
APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::UP));
|
|
||||||
if (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_SGT)
|
if (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_SGT)
|
||||||
NewC = ConstantInt::get(
|
NewC = ConstantInt::get(
|
||||||
Mul->getType(),
|
MulTy, APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::DOWN));
|
||||||
APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::DOWN));
|
} else {
|
||||||
} else if (Mul->hasNoUnsignedWrap()) {
|
assert(Mul->hasNoUnsignedWrap() && "Expected mul nuw");
|
||||||
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)
|
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)
|
||||||
NewC = ConstantInt::get(
|
NewC = ConstantInt::get(
|
||||||
Mul->getType(),
|
MulTy, APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::UP));
|
||||||
APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::UP));
|
|
||||||
if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT)
|
if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT)
|
||||||
NewC = ConstantInt::get(
|
NewC = ConstantInt::get(
|
||||||
Mul->getType(),
|
MulTy, APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::DOWN));
|
||||||
APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::DOWN));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewC ? new ICmpInst(Pred, Mul->getOperand(0), NewC) : nullptr;
|
return NewC ? new ICmpInst(Pred, X, NewC) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fold icmp (shl 1, Y), C.
|
/// Fold icmp (shl 1, Y), C.
|
||||||
|
|
Loading…
Reference in New Issue