[MCA] Moved the logic that updates register dependencies from DispatchStage to RegisterFile. NFC
DispatchStage should always delegate to an object of class RegisterFile the task of updating data dependencies. ReadState and WriteState objects should not be modified directly by DispatchStage. This patch also renames stage IS_AVAILABLE to IS_DISPATCHED. llvm-svn: 353170
This commit is contained in:
parent
cad6336675
commit
4bce783ee3
|
@ -20,6 +20,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSchedule.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MCA/HardwareUnits/HardwareUnit.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
|
@ -195,7 +196,7 @@ public:
|
|||
|
||||
// Collect writes that are in a data dependency with RS, and update RS
|
||||
// internal state.
|
||||
void addRegisterRead(ReadState &RS, SmallVectorImpl<WriteRef> &Writes) const;
|
||||
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const;
|
||||
|
||||
// Removes write \param WS from the register mappings.
|
||||
// Physical registers may be released to reflect this update.
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
/// An instruction is moved from the WaitSet to the ReadySet when register
|
||||
/// operands become available, and all memory dependencies are met.
|
||||
/// Instructions that are moved from the WaitSet to the ReadySet transition
|
||||
/// in state from 'IS_AVAILABLE' to 'IS_READY'.
|
||||
/// in state from 'IS_DISPATCHED' to 'IS_READY'.
|
||||
///
|
||||
/// On every cycle, the Scheduler checks if it can promote instructions from the
|
||||
/// WaitSet to the ReadySet.
|
||||
|
|
|
@ -409,12 +409,12 @@ public:
|
|||
/// that are sent to the various components of the simulated hardware pipeline.
|
||||
class Instruction : public InstructionBase {
|
||||
enum InstrStage {
|
||||
IS_INVALID, // Instruction in an invalid state.
|
||||
IS_AVAILABLE, // Instruction dispatched but operands are not ready.
|
||||
IS_READY, // Instruction dispatched and operands ready.
|
||||
IS_EXECUTING, // Instruction issued.
|
||||
IS_EXECUTED, // Instruction executed. Values are written back.
|
||||
IS_RETIRED // Instruction retired.
|
||||
IS_INVALID, // Instruction in an invalid state.
|
||||
IS_DISPATCHED, // Instruction dispatched but operands are not ready.
|
||||
IS_READY, // Instruction dispatched and operands ready.
|
||||
IS_EXECUTING, // Instruction issued.
|
||||
IS_EXECUTED, // Instruction executed. Values are written back.
|
||||
IS_RETIRED // Instruction retired.
|
||||
};
|
||||
|
||||
// The current instruction stage.
|
||||
|
@ -444,7 +444,7 @@ public:
|
|||
// all the definitions.
|
||||
void execute();
|
||||
|
||||
// Force a transition from the IS_AVAILABLE state to the IS_READY state if
|
||||
// Force a transition from the IS_DISPATCHED state to the IS_READY state if
|
||||
// input operands are all ready. State transitions normally occur at the
|
||||
// beginning of a new cycle (see method cycleEvent()). However, the scheduler
|
||||
// may decide to promote instructions from the wait queue to the ready queue
|
||||
|
@ -452,7 +452,7 @@ public:
|
|||
// instruction might have changed in state.
|
||||
void update();
|
||||
|
||||
bool isDispatched() const { return Stage == IS_AVAILABLE; }
|
||||
bool isDispatched() const { return Stage == IS_DISPATCHED; }
|
||||
bool isReady() const { return Stage == IS_READY; }
|
||||
bool isExecuting() const { return Stage == IS_EXECUTING; }
|
||||
bool isExecuted() const { return Stage == IS_EXECUTED; }
|
||||
|
@ -464,7 +464,7 @@ public:
|
|||
[](const WriteState &W) { return W.isEliminated(); });
|
||||
}
|
||||
|
||||
// Forces a transition from state IS_AVAILABLE to state IS_EXECUTED.
|
||||
// Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
|
||||
void forceExecuted();
|
||||
|
||||
void retire() {
|
||||
|
|
|
@ -61,8 +61,6 @@ class DispatchStage final : public Stage {
|
|||
bool canDispatch(const InstRef &IR) const;
|
||||
Error dispatch(InstRef IR);
|
||||
|
||||
void updateRAWDependencies(ReadState &RS, const MCSubtargetInfo &STI);
|
||||
|
||||
void notifyInstructionDispatched(const InstRef &IR,
|
||||
ArrayRef<unsigned> UsedPhysRegs,
|
||||
unsigned uOps) const;
|
||||
|
|
|
@ -401,7 +401,7 @@ void RegisterFile::collectWrites(const ReadState &RS,
|
|||
}
|
||||
|
||||
void RegisterFile::addRegisterRead(ReadState &RS,
|
||||
SmallVectorImpl<WriteRef> &Defs) const {
|
||||
const MCSubtargetInfo &STI) const {
|
||||
unsigned RegID = RS.getRegisterID();
|
||||
const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
|
||||
RS.setPRF(RRI.IndexPlusCost.first);
|
||||
|
@ -410,8 +410,23 @@ void RegisterFile::addRegisterRead(ReadState &RS,
|
|||
|
||||
if (ZeroRegisters[RS.getRegisterID()])
|
||||
RS.setReadZero();
|
||||
collectWrites(RS, Defs);
|
||||
RS.setDependentWrites(Defs.size());
|
||||
|
||||
SmallVector<WriteRef, 4> DependentWrites;
|
||||
collectWrites(RS, DependentWrites);
|
||||
RS.setDependentWrites(DependentWrites.size());
|
||||
|
||||
// We know that this read depends on all the writes in DependentWrites.
|
||||
// For each write, check if we have ReadAdvance information, and use it
|
||||
// to figure out in how many cycles this read becomes available.
|
||||
const ReadDescriptor &RD = RS.getDescriptor();
|
||||
const MCSchedModel &SM = STI.getSchedModel();
|
||||
const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
|
||||
for (WriteRef &WR : DependentWrites) {
|
||||
WriteState &WS = *WR.getWriteState();
|
||||
unsigned WriteResID = WS.getWriteResourceID();
|
||||
int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
|
||||
WS.addUser(&RS, ReadAdvance);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RegisterFile::isAvailable(ArrayRef<unsigned> Regs) const {
|
||||
|
|
|
@ -123,7 +123,7 @@ void WriteRef::dump() const {
|
|||
|
||||
void Instruction::dispatch(unsigned RCUToken) {
|
||||
assert(Stage == IS_INVALID);
|
||||
Stage = IS_AVAILABLE;
|
||||
Stage = IS_DISPATCHED;
|
||||
RCUTokenID = RCUToken;
|
||||
|
||||
// Check if input operands are already available.
|
||||
|
|
|
@ -62,27 +62,6 @@ bool DispatchStage::canDispatch(const InstRef &IR) const {
|
|||
return checkRCU(IR) && checkPRF(IR) && checkNextStage(IR);
|
||||
}
|
||||
|
||||
void DispatchStage::updateRAWDependencies(ReadState &RS,
|
||||
const MCSubtargetInfo &STI) {
|
||||
SmallVector<WriteRef, 4> DependentWrites;
|
||||
|
||||
// Collect all the dependent writes, and update RS internal state.
|
||||
PRF.addRegisterRead(RS, DependentWrites);
|
||||
|
||||
// We know that this read depends on all the writes in DependentWrites.
|
||||
// For each write, check if we have ReadAdvance information, and use it
|
||||
// to figure out in how many cycles this read becomes available.
|
||||
const ReadDescriptor &RD = RS.getDescriptor();
|
||||
const MCSchedModel &SM = STI.getSchedModel();
|
||||
const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
|
||||
for (WriteRef &WR : DependentWrites) {
|
||||
WriteState &WS = *WR.getWriteState();
|
||||
unsigned WriteResID = WS.getWriteResourceID();
|
||||
int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
|
||||
WS.addUser(&RS, ReadAdvance);
|
||||
}
|
||||
}
|
||||
|
||||
Error DispatchStage::dispatch(InstRef IR) {
|
||||
assert(!CarryOver && "Cannot dispatch another instruction!");
|
||||
Instruction &IS = *IR.getInstruction();
|
||||
|
@ -121,7 +100,7 @@ Error DispatchStage::dispatch(InstRef IR) {
|
|||
// eliminated at register renaming stage.
|
||||
if (!IsEliminated) {
|
||||
for (ReadState &RS : IS.getUses())
|
||||
updateRAWDependencies(RS, STI);
|
||||
PRF.addRegisterRead(RS, STI);
|
||||
}
|
||||
|
||||
// By default, a dependency-breaking zero-idiom is expected to be optimized
|
||||
|
|
Loading…
Reference in New Issue