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:
Jakob Stoklund Olesen 2012-04-26 23:33:11 +00:00
parent 70a1860a46
commit f9f1c7aa89

View File

@ -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.