Canonicalize multiplies by looking at whether the operands have any constants themselves. Patch by Tim Murray!

llvm-svn: 223554
This commit is contained in:
Nick Lewycky 2014-12-06 00:45:50 +00:00
parent 2163b05d8e
commit 05044c248e
1 changed files with 26 additions and 5 deletions

View File

@ -2207,6 +2207,25 @@ static uint64_t Choose(uint64_t n, uint64_t k, bool &Overflow) {
return r;
}
/// Determine if any of the operands in this SCEV are a constant or if
/// any of the add or multiply expressions in this SCEV contain a constant.
static bool containsConstantSomewhere(const SCEV *StartExpr) {
SmallVector<const SCEV *, 4> Ops;
Ops.push_back(StartExpr);
while (!Ops.empty()) {
const SCEV *CurrentExpr = Ops.pop_back_val();
if (isa<SCEVConstant>(*CurrentExpr))
return true;
if (isa<SCEVAddExpr>(*CurrentExpr) || isa<SCEVMulExpr>(*CurrentExpr)) {
const auto *CurrentNAry = cast<SCEVNAryExpr>(CurrentExpr);
for (const SCEV *Operand : CurrentNAry->operands())
Ops.push_back(Operand);
}
}
return false;
}
/// getMulExpr - Get a canonical multiply expression, or something simpler if
/// possible.
const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
@ -2246,11 +2265,13 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// C1*(C2+V) -> C1*C2 + C1*V
if (Ops.size() == 2)
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1]))
if (Add->getNumOperands() == 2 &&
isa<SCEVConstant>(Add->getOperand(0)))
return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)),
getMulExpr(LHSC, Add->getOperand(1)));
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1]))
// If any of Add's ops are Adds or Muls with a constant,
// apply this transformation as well.
if (Add->getNumOperands() == 2)
if (containsConstantSomewhere(Add))
return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)),
getMulExpr(LHSC, Add->getOperand(1)));
++Idx;
while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {