mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-24 13:18:17 +00:00
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:
+58
-77
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user