Re-enable register pressure aware machine licm with fixes. Hoist() may have

erased the instruction during LICM so UpdateRegPressureAfter() should not
reference it afterwards.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116845 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2010-10-19 18:58:51 +00:00
parent 9cb4c7f878
commit 2312842de0
10 changed files with 148 additions and 146 deletions
+58 -77
View File
@@ -43,11 +43,6 @@
using namespace llvm;
static cl::opt<bool>
TrackRegPressure("rp-aware-machine-licm",
cl::desc("Register pressure aware machine LICM"),
cl::init(false), cl::Hidden);
STATISTIC(NumHoisted,
"Number of machine instructions hoisted out of loops");
STATISTIC(NumLowRP,
@@ -128,6 +123,7 @@ namespace {
RegSeen.clear();
RegPressure.clear();
RegLimit.clear();
BackTrace.clear();
for (DenseMap<unsigned,std::vector<const MachineInstr*> >::iterator
CI = CSEMap.begin(), CE = CSEMap.end(); CI != CE; ++CI)
CI->second.clear();
@@ -175,9 +171,10 @@ namespace {
///
bool IsLoopInvariantInst(MachineInstr &I);
/// ComputeOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop.
int ComputeOperandLatency(MachineInstr &MI, unsigned DefIdx, unsigned Reg);
/// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop, return true if the target considered
/// it 'high'.
bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, unsigned Reg);
/// IncreaseHighRegPressure - Visit BBs from preheader to current BB, check
/// if hoisting an instruction of the given cost matrix can cause high
@@ -203,8 +200,9 @@ namespace {
/// UpdateRegPressureBefore / UpdateRegPressureAfter - Update estimate of
/// register pressure before and after executing a specifi instruction.
void UpdateRegPressureBefore(const MachineInstr *MI);
void UpdateRegPressureAfter(const MachineInstr *MI);
void UpdateRegPressureBefore(const MachineInstr *MI,
SmallVector<unsigned, 4> &Defs);
void UpdateRegPressureAfter(SmallVector<unsigned, 4> &Defs);
/// isLoadFromConstantMemory - Return true if the given instruction is a
/// load from constant memory.
@@ -560,28 +558,26 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) {
if (!Preheader)
return;
if (TrackRegPressure) {
if (IsHeader) {
// Compute registers which are liveout of preheader.
RegSeen.clear();
BackTrace.clear();
InitRegPressure(Preheader);
}
// Remember livein register pressure.
BackTrace.push_back(RegPressure);
if (IsHeader) {
// Compute registers which are liveout of preheader.
RegSeen.clear();
BackTrace.clear();
InitRegPressure(Preheader);
}
// Remember livein register pressure.
BackTrace.push_back(RegPressure);
SmallVector<unsigned, 4> Defs;
for (MachineBasicBlock::iterator
MII = BB->begin(), E = BB->end(); MII != E; ) {
MachineBasicBlock::iterator NextMII = MII; ++NextMII;
MachineInstr *MI = &*MII;
if (TrackRegPressure)
UpdateRegPressureBefore(MI);
assert(Defs.empty());
UpdateRegPressureBefore(MI, Defs);
Hoist(MI, Preheader);
if (TrackRegPressure)
UpdateRegPressureAfter(MI);
UpdateRegPressureAfter(Defs);
MII = NextMII;
}
@@ -595,8 +591,7 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) {
HoistRegion(Children[I]);
}
if (TrackRegPressure)
BackTrace.pop_back();
BackTrace.pop_back();
}
/// InitRegPressure - Find all virtual register references that are liveout of
@@ -635,12 +630,13 @@ void MachineLICM::InitRegPressure(MachineBasicBlock *BB) {
/// UpdateRegPressureBefore / UpdateRegPressureAfter - Update estimate of
/// register pressure before and after executing a specifi instruction.
void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI) {
void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI,
SmallVector<unsigned, 4> &Defs) {
bool NoImpact = MI->isImplicitDef() || MI->isPHI();
for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg() || MO.isImplicit() || !MO.isUse())
if (!MO.isReg() || MO.isImplicit())
continue;
unsigned Reg = MO.getReg();
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
@@ -650,33 +646,26 @@ void MachineLICM::UpdateRegPressureBefore(const MachineInstr *MI) {
if (NoImpact)
continue;
if (!isNew && MO.isKill()) {
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
EVT VT = *RC->vt_begin();
unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
unsigned RCCost = TLI->getRepRegClassCostFor(VT);
if (MO.isDef())
Defs.push_back(Reg);
else {
if (!isNew && MO.isKill()) {
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
EVT VT = *RC->vt_begin();
unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
unsigned RCCost = TLI->getRepRegClassCostFor(VT);
assert(RCCost <= RegPressure[RCId]);
RegPressure[RCId] -= RCCost;
assert(RCCost <= RegPressure[RCId]);
RegPressure[RCId] -= RCCost;
}
}
}
}
void MachineLICM::UpdateRegPressureAfter(const MachineInstr *MI) {
bool NoImpact = MI->isImplicitDef() || MI->isPHI();
for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
continue;
unsigned Reg = MO.getReg();
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
void MachineLICM::UpdateRegPressureAfter(SmallVector<unsigned, 4> &Defs) {
while (!Defs.empty()) {
unsigned Reg = Defs.pop_back_val();
RegSeen.insert(Reg);
if (NoImpact)
continue;
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
EVT VT = *RC->vt_begin();
unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
@@ -792,15 +781,14 @@ bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) {
}
}
/// ComputeOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop.
int MachineLICM::ComputeOperandLatency(MachineInstr &MI,
unsigned DefIdx, unsigned Reg) {
/// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop, return true if the target considered
/// it 'high'.
bool MachineLICM::HasHighOperandLatency(MachineInstr &MI,
unsigned DefIdx, unsigned Reg) {
if (MRI->use_nodbg_empty(Reg))
// No use? Return arbitrary large number!
return 300;
return false;
int Latency = -1;
for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg),
E = MRI->use_nodbg_end(); I != E; ++I) {
MachineInstr *UseMI = &*I;
@@ -814,18 +802,15 @@ int MachineLICM::ComputeOperandLatency(MachineInstr &MI,
if (MOReg != Reg)
continue;
int UseCycle = TII->getOperandLatency(InstrItins, &MI, DefIdx, UseMI, i);
Latency = std::max(Latency, UseCycle);
if (TII->hasHighOperandLatency(InstrItins, MRI, &MI, DefIdx, UseMI, i))
return true;
}
if (Latency != -1)
break;
// Only look at the first in loop use.
break;
}
if (Latency == -1)
Latency = InstrItins->getOperandCycle(MI.getDesc().getSchedClass(), DefIdx);
return Latency;
return false;
}
/// IncreaseHighRegPressure - Visit BBs from preheader to current BB, check
@@ -859,19 +844,19 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) {
if (MI.isImplicitDef())
return true;
// FIXME: For now, only hoist re-materilizable instructions. LICM will
// increase register pressure. We want to make sure it doesn't increase
// spilling.
// If the instruction is cheap, only hoist if it is re-materilizable. LICM
// will increase register pressure. It's probably not worth it if the
// instruction is cheap.
// Also hoist loads from constant memory, e.g. load from stubs, GOT. Hoisting
// these tend to help performance in low register pressure situation. The
// trade off is it may cause spill in high pressure situation. It will end up
// adding a store in the loop preheader. But the reload is no more expensive.
// The side benefit is these loads are frequently CSE'ed.
if (!TrackRegPressure || MI.getDesc().isAsCheapAsAMove()) {
if (!TII->isTriviallyReMaterializable(&MI, AA) &&
!isLoadFromConstantMemory(&MI))
if (MI.getDesc().isAsCheapAsAMove()) {
if (!TII->isTriviallyReMaterializable(&MI, AA))
return false;
} else {
// Estimate register pressure to determine whether to LICM the instruction.
// In low register pressure situation, we can be more aggressive about
// hoisting. Also, favors hoisting long latency instructions even in
// moderately high pressure situation.
@@ -884,13 +869,9 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) {
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
if (MO.isDef()) {
if (InstrItins && !InstrItins->isEmpty()) {
int Cycle = ComputeOperandLatency(MI, i, Reg);
if (Cycle > 3) {
// FIXME: Target specific high latency limit?
++NumHighLatency;
return true;
}
if (HasHighOperandLatency(MI, i, Reg)) {
++NumHighLatency;
return true;
}
const TargetRegisterClass *RC = MRI->getRegClass(Reg);