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
diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp
index 3e25e91..1f04124 100644
--- a/lib/CodeGen/MachineLICM.cpp
+++ b/lib/CodeGen/MachineLICM.cpp
@@ -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 @@
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 @@
///
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 @@
/// 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 @@
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 @@
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 @@
/// 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 @@
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 @@
}
}
-/// 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 @@
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 @@
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 @@
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);