RegisterPressure: Expose RegisterOperands API

Previously the RegisterOperands have only been used internally in
RegisterPressure.cpp. However this datastructure can be useful for other
tasks as well and allows refactoring of PDiff initialisation out of
RPTracker::recede().

This patch:
- Exposes RegisterOperands as public API
- Splits RPTracker::recede() into a part that skips DebugValues and
  maintains the region borders, and the core that changes register
  pressure when given a set of RegisterOperands.
- This allows to move the PDiff initialisation out recede() into a
  method of the PressureDiffs class.
- The upcoming subregister scheduling code will also use
  RegisterOperands to avoid pushing more unrelated functionality into
  recede()/advance().

Differential Revision: http://reviews.llvm.org/D15473

llvm-svn: 257535
This commit is contained in:
Matthias Braun 2016-01-12 22:57:35 +00:00
parent 9aae445e09
commit b505c76c9a
3 changed files with 102 additions and 67 deletions

View File

@ -141,6 +141,28 @@ public:
LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const;
};
/// List of registers defined and used by a machine instruction.
class RegisterOperands {
public:
/// List of virtual regiserts and register units read by the instruction.
SmallVector<unsigned, 8> Uses;
/// \brief List of virtual registers and register units defined by the
/// instruction which are not dead.
SmallVector<unsigned, 8> Defs;
/// \brief List of virtual registers and register units defined by the
/// instruction but dead.
SmallVector<unsigned, 8> DeadDefs;
/// Analyze the given instruction \p MI and fill in the Uses, Defs and
/// DeadDefs list based on the MachineOperand flags.
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI,
const MachineRegisterInfo &MRI, bool IgnoreDead = false);
/// Use liveness information to find dead defs not marked with a dead flag
/// and move them to the DeadDefs vector.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS);
};
/// Array of PressureDiffs.
class PressureDiffs {
PressureDiff *PDiffArray;
@ -161,6 +183,10 @@ public:
const PressureDiff &operator[](unsigned Idx) const {
return const_cast<PressureDiffs*>(this)->operator[](Idx);
}
/// \brief Record pressure difference induced by the given operand list to
/// node with index \p Idx.
void addInstruction(unsigned Idx, const RegisterOperands &RegOpers,
const MachineRegisterInfo &MRI);
};
/// Store the effects of a change in pressure on things that MI scheduler cares
@ -329,8 +355,17 @@ public:
void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; }
/// Recede across the previous instruction.
void recede(SmallVectorImpl<unsigned> *LiveUses = nullptr,
PressureDiff *PDiff = nullptr);
void recede(SmallVectorImpl<unsigned> *LiveUses = nullptr);
/// Recede across the previous instruction.
/// This "low-level" variant assumes that recedeSkipDebugValues() was
/// called previously and takes precomputed RegisterOperands for the
/// instruction.
void recede(const RegisterOperands &RegOpers,
SmallVectorImpl<unsigned> *LiveUses = nullptr);
/// Recede until we find an instruction which is not a DebugValue.
void recedeSkipDebugValues();
/// Advance across the current instruction.
void advance();

View File

@ -313,21 +313,6 @@ static bool containsReg(ArrayRef<unsigned> RegUnits, unsigned RegUnit) {
namespace {
/// List of register defined and used by a machine instruction.
class RegisterOperands {
public:
SmallVector<unsigned, 8> Uses;
SmallVector<unsigned, 8> Defs;
SmallVector<unsigned, 8> DeadDefs;
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI,
const MachineRegisterInfo &MRI, bool IgnoreDead = false);
/// Use liveness information to find dead defs not marked with a dead flag
/// and move them to the DeadDefs vector.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS);
};
/// Collect this instruction's unique uses and defs into SmallVectors for
/// processing defs and uses in order.
///
@ -385,9 +370,11 @@ class RegisterOperandsCollector {
}
}
friend class RegisterOperands;
friend class llvm::RegisterOperands;
};
} // namespace
void RegisterOperands::collect(const MachineInstr &MI,
const TargetRegisterInfo &TRI,
const MachineRegisterInfo &MRI,
@ -417,8 +404,6 @@ void RegisterOperands::detectDeadDefs(const MachineInstr &MI,
}
}
} // namespace
/// Initialize an array of N PressureDiffs.
void PressureDiffs::init(unsigned N) {
Size = N;
@ -431,6 +416,18 @@ void PressureDiffs::init(unsigned N) {
PDiffArray = reinterpret_cast<PressureDiff*>(calloc(N, sizeof(PressureDiff)));
}
void PressureDiffs::addInstruction(unsigned Idx,
const RegisterOperands &RegOpers,
const MachineRegisterInfo &MRI) {
PressureDiff &PDiff = (*this)[Idx];
assert(!PDiff.begin()->isValid() && "stale PDiff");
for (unsigned Reg : RegOpers.Defs)
PDiff.addPressureChange(Reg, true, &MRI);
for (unsigned Reg : RegOpers.Uses)
PDiff.addPressureChange(Reg, false, &MRI);
}
/// Add a change in pressure to the pressure diff of a given instruction.
void PressureDiff::addPressureChange(unsigned RegUnit, bool IsDec,
const MachineRegisterInfo *MRI) {
@ -467,18 +464,6 @@ void PressureDiff::addPressureChange(unsigned RegUnit, bool IsDec,
}
}
/// Record the pressure difference induced by the given operand list.
static void collectPDiff(PressureDiff &PDiff, RegisterOperands &RegOpers,
const MachineRegisterInfo *MRI) {
assert(!PDiff.begin()->isValid() && "stale PDiff");
for (unsigned Reg : RegOpers.Defs)
PDiff.addPressureChange(Reg, true, MRI);
for (unsigned Reg : RegOpers.Uses)
PDiff.addPressureChange(Reg, false, MRI);
}
/// Force liveness of registers.
void RegPressureTracker::addLiveRegs(ArrayRef<unsigned> Regs) {
for (unsigned Reg : Regs) {
@ -514,39 +499,10 @@ void RegPressureTracker::discoverLiveOut(unsigned Reg) {
/// registers that are both defined and used by the instruction. If a pressure
/// difference pointer is provided record the changes is pressure caused by this
/// instruction independent of liveness.
void RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses,
PressureDiff *PDiff) {
assert(CurrPos != MBB->begin());
if (!isBottomClosed())
closeBottom();
// Open the top of the region using block iterators.
if (!RequireIntervals && isTopClosed())
static_cast<RegionPressure&>(P).openTop(CurrPos);
// Find the previous instruction.
do
--CurrPos;
while (CurrPos != MBB->begin() && CurrPos->isDebugValue());
void RegPressureTracker::recede(const RegisterOperands &RegOpers,
SmallVectorImpl<unsigned> *LiveUses) {
assert(!CurrPos->isDebugValue());
SlotIndex SlotIdx;
if (RequireIntervals)
SlotIdx = LIS->getInstructionIndex(CurrPos).getRegSlot();
// Open the top of the region using slot indexes.
if (RequireIntervals && isTopClosed())
static_cast<IntervalPressure&>(P).openTop(SlotIdx);
const MachineInstr &MI = *CurrPos;
RegisterOperands RegOpers;
RegOpers.collect(MI, *TRI, *MRI);
if (RequireIntervals)
RegOpers.detectDeadDefs(MI, *LIS);
if (PDiff)
collectPDiff(*PDiff, RegOpers, MRI);
// Boost pressure for all dead defs together.
increaseRegPressure(RegOpers.DeadDefs);
decreaseRegPressure(RegOpers.DeadDefs);
@ -560,6 +516,10 @@ void RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses,
discoverLiveOut(Reg);
}
SlotIndex SlotIdx;
if (RequireIntervals)
SlotIdx = LIS->getInstructionIndex(CurrPos).getRegSlot();
// Generate liveness for uses.
for (unsigned Reg : RegOpers.Uses) {
if (!LiveRegs.contains(Reg)) {
@ -586,6 +546,41 @@ void RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses,
}
}
void RegPressureTracker::recedeSkipDebugValues() {
assert(CurrPos != MBB->begin());
if (!isBottomClosed())
closeBottom();
// Open the top of the region using block iterators.
if (!RequireIntervals && isTopClosed())
static_cast<RegionPressure&>(P).openTop(CurrPos);
// Find the previous instruction.
do
--CurrPos;
while (CurrPos != MBB->begin() && CurrPos->isDebugValue());
SlotIndex SlotIdx;
if (RequireIntervals)
SlotIdx = LIS->getInstructionIndex(CurrPos).getRegSlot();
// Open the top of the region using slot indexes.
if (RequireIntervals && isTopClosed())
static_cast<IntervalPressure&>(P).openTop(SlotIdx);
}
void RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses) {
recedeSkipDebugValues();
const MachineInstr &MI = *CurrPos;
RegisterOperands RegOpers;
RegOpers.collect(MI, *TRI, *MRI);
if (RequireIntervals)
RegOpers.detectDeadDefs(MI, *LIS);
recede(RegOpers, LiveUses);
}
/// Advance across the current instruction.
void RegPressureTracker::advance() {
assert(!TrackUntiedDefs && "unsupported mode");

View File

@ -896,11 +896,16 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
assert(SU && "No SUnit mapped to this MI");
if (RPTracker) {
PressureDiff *PDiff = PDiffs ? &(*PDiffs)[SU->NodeNum] : nullptr;
RPTracker->recede(/*LiveUses=*/nullptr, PDiff);
assert(RPTracker->getPos() == std::prev(MII) &&
"RPTracker can't find MI");
collectVRegUses(SU);
RegisterOperands RegOpers;
RegOpers.collect(*MI, *TRI, MRI);
if (PDiffs != nullptr)
PDiffs->addInstruction(SU->NodeNum, RegOpers, MRI);
RPTracker->recedeSkipDebugValues();
assert(&*RPTracker->getPos() == MI && "RPTracker in sync");
RPTracker->recede(RegOpers);
}
assert(