SimplifyIndVar: make foldIVUser iterative to fold a chain of operands.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137199 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick
2011-08-10 04:01:31 +00:00
parent 4a1a5eb95b
commit ea23daa446

View File

@@ -73,7 +73,7 @@ namespace {
/// all simplicitions to users of an IV. /// all simplicitions to users of an IV.
void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL); void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
bool foldIVUser(Instruction *UseInst, Instruction *IVOperand); Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand); bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand); void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
@@ -84,26 +84,30 @@ namespace {
/// foldIVUser - Fold an IV operand into its use. This removes increments of an /// foldIVUser - Fold an IV operand into its use. This removes increments of an
/// aligned IV when used by a instruction that ignores the low bits. /// aligned IV when used by a instruction that ignores the low bits.
bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) { ///
/// Return the operand of IVOperand for this induction variable if IVOperand can
/// be folded (in case more folding opportunity has been exposed).
/// Otherwise return null.
Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
Value *IVSrc = 0; Value *IVSrc = 0;
unsigned OperIdx = 0; unsigned OperIdx = 0;
const SCEV *FoldedExpr = 0; const SCEV *FoldedExpr = 0;
switch (UseInst->getOpcode()) { switch (UseInst->getOpcode()) {
default: default:
return false; return 0;
case Instruction::UDiv: case Instruction::UDiv:
case Instruction::LShr: case Instruction::LShr:
// We're only interested in the case where we know something about // We're only interested in the case where we know something about
// the numerator and have a constant denominator. // the numerator and have a constant denominator.
if (IVOperand != UseInst->getOperand(OperIdx) || if (IVOperand != UseInst->getOperand(OperIdx) ||
!isa<ConstantInt>(UseInst->getOperand(1))) !isa<ConstantInt>(UseInst->getOperand(1)))
return false; return 0;
// Attempt to fold a binary operator with constant operand. // Attempt to fold a binary operator with constant operand.
// e.g. ((I + 1) >> 2) => I >> 2 // e.g. ((I + 1) >> 2) => I >> 2
if (IVOperand->getNumOperands() != 2 || if (IVOperand->getNumOperands() != 2 ||
!isa<ConstantInt>(IVOperand->getOperand(1))) !isa<ConstantInt>(IVOperand->getOperand(1)))
return false; return 0;
IVSrc = IVOperand->getOperand(0); IVSrc = IVOperand->getOperand(0);
// IVSrc must be the (SCEVable) IV, since the other operand is const. // IVSrc must be the (SCEVable) IV, since the other operand is const.
@@ -114,7 +118,7 @@ bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
// Get a constant for the divisor. See createSCEV. // Get a constant for the divisor. See createSCEV.
uint32_t BitWidth = cast<IntegerType>(UseInst->getType())->getBitWidth(); uint32_t BitWidth = cast<IntegerType>(UseInst->getType())->getBitWidth();
if (D->getValue().uge(BitWidth)) if (D->getValue().uge(BitWidth))
return false; return 0;
D = ConstantInt::get(UseInst->getContext(), D = ConstantInt::get(UseInst->getContext(),
APInt(BitWidth, 1).shl(D->getZExtValue())); APInt(BitWidth, 1).shl(D->getZExtValue()));
@@ -123,11 +127,11 @@ bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
} }
// We have something that might fold it's operand. Compare SCEVs. // We have something that might fold it's operand. Compare SCEVs.
if (!SE->isSCEVable(UseInst->getType())) if (!SE->isSCEVable(UseInst->getType()))
return false; return 0;
// Bypass the operand if SCEV can prove it has no effect. // Bypass the operand if SCEV can prove it has no effect.
if (SE->getSCEV(UseInst) != FoldedExpr) if (SE->getSCEV(UseInst) != FoldedExpr)
return false; return 0;
DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand
<< " -> " << *UseInst << '\n'); << " -> " << *UseInst << '\n');
@@ -139,7 +143,7 @@ bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
Changed = true; Changed = true;
if (IVOperand->use_empty()) if (IVOperand->use_empty())
DeadInsts.push_back(IVOperand); DeadInsts.push_back(IVOperand);
return true; return IVSrc;
} }
/// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless /// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
@@ -337,10 +341,20 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
// Bypass back edges to avoid extra work. // Bypass back edges to avoid extra work.
if (UseOper.first == CurrIV) continue; if (UseOper.first == CurrIV) continue;
foldIVUser(UseOper.first, UseOper.second); Instruction *IVOperand = UseOper.second;
for (unsigned N = 0; IVOperand; ++N) {
assert(N <= Simplified.size() && "runaway iteration");
if (eliminateIVUser(UseOper.first, UseOper.second)) { Value *NewOper = foldIVUser(UseOper.first, IVOperand);
pushIVUsers(UseOper.second, Simplified, SimpleIVUsers); if (!NewOper)
break; // done folding
IVOperand = dyn_cast<Instruction>(NewOper);
}
if (!IVOperand)
continue;
if (eliminateIVUser(UseOper.first, IVOperand)) {
pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
continue; continue;
} }
CastInst *Cast = dyn_cast<CastInst>(UseOper.first); CastInst *Cast = dyn_cast<CastInst>(UseOper.first);