#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"
// 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.
/// 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.
/// 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.
// 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
// 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; }
[](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() {
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;
}
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);
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 {
void Instruction::dispatch(unsigned RCUToken) {
assert(Stage == IS_INVALID);
- Stage = IS_AVAILABLE;
+ Stage = IS_DISPATCHED;
RCUTokenID = RCUToken;
// Check if input operands are already available.
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();
// 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