mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-09 16:45:03 +00:00
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
This commit is contained in:
parent
e9bc1e8263
commit
05f7e38c0b
@ -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);
|
||||
}
|
||||
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 MulExt = LHSExt * RHSExt;
|
||||
|
||||
if (!sign)
|
||||
return MulExt.ugt(APInt::getLowBitsSet(W * 2, W));
|
||||
|
||||
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<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
|
||||
return &I;
|
||||
|
||||
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
|
||||
if (Instruction *LHS = dyn_cast<Instruction>(Op0)) {
|
||||
// (X / C1) / C2 -> X / (C1*C2)
|
||||
if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
|
||||
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
|
||||
if (!MultiplyOverflows(RHS, LHSRHS,
|
||||
I.getOpcode() == Instruction::SDiv))
|
||||
return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
|
||||
ConstantExpr::getMul(RHS, LHSRHS));
|
||||
}
|
||||
|
||||
if (Instruction *LHS = dyn_cast<Instruction>(Op0)) {
|
||||
const APInt *C2;
|
||||
if (match(Op1, m_APInt(C2))) {
|
||||
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);
|
||||
const APInt *C1;
|
||||
bool IsSigned = I.getOpcode() == Instruction::SDiv;
|
||||
|
||||
// (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;
|
||||
}
|
||||
// (X / C1) / C2 -> X / (C1*C2)
|
||||
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));
|
||||
}
|
||||
|
||||
// (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<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
|
||||
BO->setHasNoSignedWrap(
|
||||
cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
|
||||
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 / (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<unsigned>(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<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
|
||||
BO->setHasNoSignedWrap(
|
||||
cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
|
||||
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<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
|
||||
BO->setHasNoSignedWrap(
|
||||
cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
|
||||
return BO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!RHS->isZero()) { // avoid X udiv 0
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
||||
return R;
|
||||
if (isa<PHINode>(Op0))
|
||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||
return NV;
|
||||
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<unsigned>(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<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
|
||||
BO->setHasNoSignedWrap(
|
||||
cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
|
||||
return BO;
|
||||
}
|
||||
}
|
||||
|
||||
if (*C2 != 0) { // avoid X udiv 0
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
||||
return R;
|
||||
if (isa<PHINode>(Op0))
|
||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||
return NV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user