mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-30 04:56:49 +00:00
Break up getProfitableChainIncrement().
The required checks are moved to ChainInstruction() itself and the policy decisions are moved to IVChain::isProfitableInc(). Also cache the ExprBase in IVChain to avoid frequent recomputations. No functional change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155676 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
70a1860a46
commit
f9f1c7aa89
@ -1441,6 +1441,12 @@ struct IVInc {
|
|||||||
// We typically add the head of a chain without finding subsequent links.
|
// We typically add the head of a chain without finding subsequent links.
|
||||||
struct IVChain {
|
struct IVChain {
|
||||||
SmallVector<IVInc,1> Incs;
|
SmallVector<IVInc,1> Incs;
|
||||||
|
const SCEV *ExprBase;
|
||||||
|
|
||||||
|
IVChain() : ExprBase(0) {}
|
||||||
|
|
||||||
|
IVChain(const IVInc &Head, const SCEV *Base)
|
||||||
|
: Incs(1, Head), ExprBase(Base) {}
|
||||||
|
|
||||||
typedef SmallVectorImpl<IVInc>::const_iterator const_iterator;
|
typedef SmallVectorImpl<IVInc>::const_iterator const_iterator;
|
||||||
|
|
||||||
@ -1461,6 +1467,12 @@ struct IVChain {
|
|||||||
|
|
||||||
// tailUserInst - Returns the last UserInst in the chain.
|
// tailUserInst - Returns the last UserInst in the chain.
|
||||||
Instruction *tailUserInst() const { return Incs.back().UserInst; }
|
Instruction *tailUserInst() const { return Incs.back().UserInst; }
|
||||||
|
|
||||||
|
// isProfitableIncrement - Returns true if IncExpr can be profitably added to
|
||||||
|
// this chain.
|
||||||
|
bool isProfitableIncrement(const SCEV *OperExpr,
|
||||||
|
const SCEV *IncExpr,
|
||||||
|
ScalarEvolution&);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ChainUsers - Helper for CollectChains to track multiple IV increment uses.
|
/// ChainUsers - Helper for CollectChains to track multiple IV increment uses.
|
||||||
@ -2341,41 +2353,23 @@ static const SCEV *getExprBase(const SCEV *S) {
|
|||||||
/// increment will be an offset relative to the same base. We allow such offsets
|
/// increment will be an offset relative to the same base. We allow such offsets
|
||||||
/// to potentially be used as chain increment as long as it's not obviously
|
/// to potentially be used as chain increment as long as it's not obviously
|
||||||
/// expensive to expand using real instructions.
|
/// expensive to expand using real instructions.
|
||||||
static const SCEV *
|
bool IVChain::isProfitableIncrement(const SCEV *OperExpr,
|
||||||
getProfitableChainIncrement(Value *NextIV, Value *PrevIV,
|
const SCEV *IncExpr,
|
||||||
const IVChain &Chain, Loop *L,
|
ScalarEvolution &SE) {
|
||||||
ScalarEvolution &SE, const TargetLowering *TLI) {
|
// Aggressively form chains when -stress-ivchain.
|
||||||
// Prune the solution space aggressively by checking that both IV operands
|
|
||||||
// are expressions that operate on the same unscaled SCEVUnknown. This
|
|
||||||
// "base" will be canceled by the subsequent getMinusSCEV call. Checking first
|
|
||||||
// avoids creating extra SCEV expressions.
|
|
||||||
const SCEV *OperExpr = SE.getSCEV(NextIV);
|
|
||||||
const SCEV *PrevExpr = SE.getSCEV(PrevIV);
|
|
||||||
if (getExprBase(OperExpr) != getExprBase(PrevExpr) && !StressIVChain)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const SCEV *IncExpr = SE.getMinusSCEV(OperExpr, PrevExpr);
|
|
||||||
if (!SE.isLoopInvariant(IncExpr, L))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// We are not able to expand an increment unless it is loop invariant,
|
|
||||||
// however, the following checks are purely for profitability.
|
|
||||||
if (StressIVChain)
|
if (StressIVChain)
|
||||||
return IncExpr;
|
return true;
|
||||||
|
|
||||||
// Do not replace a constant offset from IV head with a nonconstant IV
|
// Do not replace a constant offset from IV head with a nonconstant IV
|
||||||
// increment.
|
// increment.
|
||||||
if (!isa<SCEVConstant>(IncExpr)) {
|
if (!isa<SCEVConstant>(IncExpr)) {
|
||||||
const SCEV *HeadExpr = SE.getSCEV(getWideOperand(Chain.Incs[0].IVOperand));
|
const SCEV *HeadExpr = SE.getSCEV(getWideOperand(Incs[0].IVOperand));
|
||||||
if (isa<SCEVConstant>(SE.getMinusSCEV(OperExpr, HeadExpr)))
|
if (isa<SCEVConstant>(SE.getMinusSCEV(OperExpr, HeadExpr)))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallPtrSet<const SCEV*, 8> Processed;
|
SmallPtrSet<const SCEV*, 8> Processed;
|
||||||
if (isHighCostExpansion(IncExpr, Processed, SE))
|
return !isHighCostExpansion(IncExpr, Processed, SE);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return IncExpr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the number of registers needed for the chain is estimated to
|
/// Return true if the number of registers needed for the chain is estimated to
|
||||||
@ -2469,25 +2463,39 @@ void LSRInstance::ChainInstruction(Instruction *UserInst, Instruction *IVOper,
|
|||||||
SmallVectorImpl<ChainUsers> &ChainUsersVec) {
|
SmallVectorImpl<ChainUsers> &ChainUsersVec) {
|
||||||
// When IVs are used as types of varying widths, they are generally converted
|
// When IVs are used as types of varying widths, they are generally converted
|
||||||
// to a wider type with some uses remaining narrow under a (free) trunc.
|
// to a wider type with some uses remaining narrow under a (free) trunc.
|
||||||
Value *NextIV = getWideOperand(IVOper);
|
Value *const NextIV = getWideOperand(IVOper);
|
||||||
|
const SCEV *const OperExpr = SE.getSCEV(NextIV);
|
||||||
|
const SCEV *const OperExprBase = getExprBase(OperExpr);
|
||||||
|
|
||||||
// Visit all existing chains. Check if its IVOper can be computed as a
|
// Visit all existing chains. Check if its IVOper can be computed as a
|
||||||
// profitable loop invariant increment from the last link in the Chain.
|
// profitable loop invariant increment from the last link in the Chain.
|
||||||
unsigned ChainIdx = 0, NChains = IVChainVec.size();
|
unsigned ChainIdx = 0, NChains = IVChainVec.size();
|
||||||
const SCEV *LastIncExpr = 0;
|
const SCEV *LastIncExpr = 0;
|
||||||
for (; ChainIdx < NChains; ++ChainIdx) {
|
for (; ChainIdx < NChains; ++ChainIdx) {
|
||||||
Value *PrevIV = getWideOperand(IVChainVec[ChainIdx].Incs.back().IVOperand);
|
IVChain &Chain = IVChainVec[ChainIdx];
|
||||||
|
|
||||||
|
// Prune the solution space aggressively by checking that both IV operands
|
||||||
|
// are expressions that operate on the same unscaled SCEVUnknown. This
|
||||||
|
// "base" will be canceled by the subsequent getMinusSCEV call. Checking
|
||||||
|
// first avoids creating extra SCEV expressions.
|
||||||
|
if (!StressIVChain && Chain.ExprBase != OperExprBase)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Value *PrevIV = getWideOperand(Chain.Incs.back().IVOperand);
|
||||||
if (!isCompatibleIVType(PrevIV, NextIV))
|
if (!isCompatibleIVType(PrevIV, NextIV))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// A phi node terminates a chain.
|
// A phi node terminates a chain.
|
||||||
if (isa<PHINode>(UserInst)
|
if (isa<PHINode>(UserInst) && isa<PHINode>(Chain.tailUserInst()))
|
||||||
&& isa<PHINode>(IVChainVec[ChainIdx].tailUserInst()))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (const SCEV *IncExpr =
|
// The increment must be loop-invariant so it can be kept in a register.
|
||||||
getProfitableChainIncrement(NextIV, PrevIV, IVChainVec[ChainIdx],
|
const SCEV *PrevExpr = SE.getSCEV(PrevIV);
|
||||||
L, SE, TLI)) {
|
const SCEV *IncExpr = SE.getMinusSCEV(OperExpr, PrevExpr);
|
||||||
|
if (!SE.isLoopInvariant(IncExpr, L))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Chain.isProfitableIncrement(OperExpr, IncExpr, SE)) {
|
||||||
LastIncExpr = IncExpr;
|
LastIncExpr = IncExpr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2501,24 +2509,24 @@ void LSRInstance::ChainInstruction(Instruction *UserInst, Instruction *IVOper,
|
|||||||
DEBUG(dbgs() << "IV Chain Limit\n");
|
DEBUG(dbgs() << "IV Chain Limit\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LastIncExpr = SE.getSCEV(NextIV);
|
LastIncExpr = OperExpr;
|
||||||
// IVUsers may have skipped over sign/zero extensions. We don't currently
|
// IVUsers may have skipped over sign/zero extensions. We don't currently
|
||||||
// attempt to form chains involving extensions unless they can be hoisted
|
// attempt to form chains involving extensions unless they can be hoisted
|
||||||
// into this loop's AddRec.
|
// into this loop's AddRec.
|
||||||
if (!isa<SCEVAddRecExpr>(LastIncExpr))
|
if (!isa<SCEVAddRecExpr>(LastIncExpr))
|
||||||
return;
|
return;
|
||||||
++NChains;
|
++NChains;
|
||||||
IVChainVec.resize(NChains);
|
IVChainVec.push_back(IVChain(IVInc(UserInst, IVOper, LastIncExpr),
|
||||||
|
OperExprBase));
|
||||||
ChainUsersVec.resize(NChains);
|
ChainUsersVec.resize(NChains);
|
||||||
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Head: (" << *UserInst
|
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Head: (" << *UserInst
|
||||||
<< ") IV=" << *LastIncExpr << "\n");
|
<< ") IV=" << *LastIncExpr << "\n");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Inc: (" << *UserInst
|
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Inc: (" << *UserInst
|
||||||
<< ") IV+" << *LastIncExpr << "\n");
|
<< ") IV+" << *LastIncExpr << "\n");
|
||||||
|
// Add this IV user to the end of the chain.
|
||||||
// Add this IV user to the end of the chain.
|
IVChainVec[ChainIdx].add(IVInc(UserInst, IVOper, LastIncExpr));
|
||||||
IVChainVec[ChainIdx].add(IVInc(UserInst, IVOper, LastIncExpr));
|
}
|
||||||
|
|
||||||
SmallPtrSet<Instruction*,4> &NearUsers = ChainUsersVec[ChainIdx].NearUsers;
|
SmallPtrSet<Instruction*,4> &NearUsers = ChainUsersVec[ChainIdx].NearUsers;
|
||||||
// This chain's NearUsers become FarUsers.
|
// This chain's NearUsers become FarUsers.
|
||||||
|
Loading…
Reference in New Issue
Block a user