mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +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.
|
||||
struct IVChain {
|
||||
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;
|
||||
|
||||
@ -1461,6 +1467,12 @@ struct IVChain {
|
||||
|
||||
// tailUserInst - Returns the last UserInst in the chain.
|
||||
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.
|
||||
@ -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
|
||||
/// to potentially be used as chain increment as long as it's not obviously
|
||||
/// expensive to expand using real instructions.
|
||||
static const SCEV *
|
||||
getProfitableChainIncrement(Value *NextIV, Value *PrevIV,
|
||||
const IVChain &Chain, Loop *L,
|
||||
ScalarEvolution &SE, const TargetLowering *TLI) {
|
||||
// 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.
|
||||
bool IVChain::isProfitableIncrement(const SCEV *OperExpr,
|
||||
const SCEV *IncExpr,
|
||||
ScalarEvolution &SE) {
|
||||
// Aggressively form chains when -stress-ivchain.
|
||||
if (StressIVChain)
|
||||
return IncExpr;
|
||||
return true;
|
||||
|
||||
// Do not replace a constant offset from IV head with a nonconstant IV
|
||||
// increment.
|
||||
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)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
SmallPtrSet<const SCEV*, 8> Processed;
|
||||
if (isHighCostExpansion(IncExpr, Processed, SE))
|
||||
return 0;
|
||||
|
||||
return IncExpr;
|
||||
return !isHighCostExpansion(IncExpr, Processed, SE);
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
// 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.
|
||||
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
|
||||
// profitable loop invariant increment from the last link in the Chain.
|
||||
unsigned ChainIdx = 0, NChains = IVChainVec.size();
|
||||
const SCEV *LastIncExpr = 0;
|
||||
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))
|
||||
continue;
|
||||
|
||||
// A phi node terminates a chain.
|
||||
if (isa<PHINode>(UserInst)
|
||||
&& isa<PHINode>(IVChainVec[ChainIdx].tailUserInst()))
|
||||
if (isa<PHINode>(UserInst) && isa<PHINode>(Chain.tailUserInst()))
|
||||
continue;
|
||||
|
||||
if (const SCEV *IncExpr =
|
||||
getProfitableChainIncrement(NextIV, PrevIV, IVChainVec[ChainIdx],
|
||||
L, SE, TLI)) {
|
||||
// The increment must be loop-invariant so it can be kept in a register.
|
||||
const SCEV *PrevExpr = SE.getSCEV(PrevIV);
|
||||
const SCEV *IncExpr = SE.getMinusSCEV(OperExpr, PrevExpr);
|
||||
if (!SE.isLoopInvariant(IncExpr, L))
|
||||
continue;
|
||||
|
||||
if (Chain.isProfitableIncrement(OperExpr, IncExpr, SE)) {
|
||||
LastIncExpr = IncExpr;
|
||||
break;
|
||||
}
|
||||
@ -2501,24 +2509,24 @@ void LSRInstance::ChainInstruction(Instruction *UserInst, Instruction *IVOper,
|
||||
DEBUG(dbgs() << "IV Chain Limit\n");
|
||||
return;
|
||||
}
|
||||
LastIncExpr = SE.getSCEV(NextIV);
|
||||
LastIncExpr = OperExpr;
|
||||
// IVUsers may have skipped over sign/zero extensions. We don't currently
|
||||
// attempt to form chains involving extensions unless they can be hoisted
|
||||
// into this loop's AddRec.
|
||||
if (!isa<SCEVAddRecExpr>(LastIncExpr))
|
||||
return;
|
||||
++NChains;
|
||||
IVChainVec.resize(NChains);
|
||||
IVChainVec.push_back(IVChain(IVInc(UserInst, IVOper, LastIncExpr),
|
||||
OperExprBase));
|
||||
ChainUsersVec.resize(NChains);
|
||||
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Head: (" << *UserInst
|
||||
<< ") IV=" << *LastIncExpr << "\n");
|
||||
}
|
||||
else
|
||||
} else {
|
||||
DEBUG(dbgs() << "IV Chain#" << ChainIdx << " Inc: (" << *UserInst
|
||||
<< ") IV+" << *LastIncExpr << "\n");
|
||||
|
||||
// Add this IV user to the end of the chain.
|
||||
IVChainVec[ChainIdx].add(IVInc(UserInst, IVOper, LastIncExpr));
|
||||
// Add this IV user to the end of the chain.
|
||||
IVChainVec[ChainIdx].add(IVInc(UserInst, IVOper, LastIncExpr));
|
||||
}
|
||||
|
||||
SmallPtrSet<Instruction*,4> &NearUsers = ChainUsersVec[ChainIdx].NearUsers;
|
||||
// This chain's NearUsers become FarUsers.
|
||||
|
Loading…
Reference in New Issue
Block a user