Add an m_Div pattern for matching either a udiv or an sdiv and use it

to simplify the "(X/Y)*Y->X when the division is exact" transform.

llvm-svn: 125004
This commit is contained in:
Duncan Sands 2011-02-07 09:36:32 +00:00
parent 648f55b2b4
commit 867cb633b4
2 changed files with 36 additions and 4 deletions

View File

@ -346,6 +346,40 @@ inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) {
return Shr_match<LHS, RHS>(L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for either SDiv or UDiv .. for convenience
//
template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator>
struct Div_match {
LHS_t L;
RHS_t R;
Div_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
template<typename OpTy>
bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Instruction::SDiv ||
V->getValueID() == Value::InstructionVal + Instruction::UDiv) {
ConcreteTy *I = cast<ConcreteTy>(V);
return (I->getOpcode() == Instruction::UDiv ||
I->getOpcode() == Instruction::SDiv) &&
L.match(I->getOperand(0)) &&
R.match(I->getOperand(1));
}
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
return (CE->getOpcode() == Instruction::SDiv ||
CE->getOpcode() == Instruction::UDiv) &&
L.match(CE->getOperand(0)) &&
R.match(CE->getOperand(1));
return false;
}
};
template<typename LHS, typename RHS>
inline Div_match<LHS, RHS> m_Div(const LHS &L, const RHS &R) {
return Div_match<LHS, RHS>(L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for binary classes
//

View File

@ -734,10 +734,8 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD,
// (X / Y) * Y -> X if the division is exact.
Value *X = 0, *Y = 0;
if ((match(Op0, m_SDiv(m_Value(X), m_Value(Y))) && Y == Op1) || // (X / Y) * Y
(match(Op0, m_UDiv(m_Value(X), m_Value(Y))) && Y == Op1) ||
(match(Op1, m_SDiv(m_Value(X), m_Value(Y))) && Y == Op0) || // Y * (X / Y)
(match(Op1, m_UDiv(m_Value(X), m_Value(Y))) && Y == Op0)) {
if ((match(Op0, m_Div(m_Value(X), m_Value(Y))) && Y == Op1) || // (X / Y) * Y
(match(Op1, m_Div(m_Value(X), m_Value(Y))) && Y == Op0)) { // Y * (X / Y)
BinaryOperator *Div = cast<BinaryOperator>(Y == Op1 ? Op0 : Op1);
if (Div->isExact())
return X;