mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
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:
@@ -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);
|
||||||
|
Reference in New Issue
Block a user