[llvm-mca] Simplify (and better standardize) the Instruction interface.

llvm-svn: 328190
This commit is contained in:
Andrea Di Biagio 2018-03-22 11:39:34 +00:00
parent ee0510fa94
commit 660fc0f64f
6 changed files with 29 additions and 31 deletions

View File

@ -42,7 +42,7 @@ void Backend::runCycle(unsigned Cycle) {
Instruction *IS = NewIS.get();
Instructions[IR.first] = std::move(NewIS);
IS->setRCUTokenID(DU->dispatch(IR.first, IS, STI));
DU->dispatch(IR.first, IS, STI);
SM.updateNext();
}

View File

@ -348,8 +348,8 @@ void DispatchUnit::updateRAWDependencies(ReadState &RS,
DependentWrites.clear();
}
unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
const MCSubtargetInfo &STI) {
void DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
const MCSubtargetInfo &STI) {
assert(!CarryOver && "Cannot dispatch another instruction!");
unsigned NumMicroOps = NewInst->getDesc().NumMicroOps;
if (NumMicroOps > DispatchWidth) {
@ -370,17 +370,17 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
for (std::unique_ptr<WriteState> &WS : NewInst->getDefs())
RAT->addRegisterMapping(*WS, RegisterFiles);
// Set the cycles left before the write-back stage.
const InstrDesc &D = NewInst->getDesc();
NewInst->setCyclesLeft(D.MaxLatency);
// Reserve slots in the RCU, and notify the instruction that it has been
// dispatched to the schedulers for execution.
NewInst->dispatch(RCU->reserveSlot(IID, NumMicroOps));
// Reserve slots in the RCU.
unsigned RCUTokenID = RCU->reserveSlot(IID, NumMicroOps);
NewInst->setRCUTokenID(RCUTokenID);
// Notify listeners of the "instruction dispatched" event.
notifyInstructionDispatched(IID, RegisterFiles);
// Now move the instruction into the scheduler's queue.
// The scheduler is responsible for checking if this is a zero-latency
// instruction that doesn't consume pipeline/scheduler resources.
SC->scheduleInstruction(IID, *NewInst);
return RCUTokenID;
}
#ifndef NDEBUG

View File

@ -250,7 +250,8 @@ class DispatchUnit {
bool checkScheduler(unsigned Index, const InstrDesc &Desc);
void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
void notifyInstructionDispatched(unsigned IID, llvm::ArrayRef<unsigned> UsedPhysRegs);
void notifyInstructionDispatched(unsigned IID,
llvm::ArrayRef<unsigned> UsedPhysRegs);
public:
DispatchUnit(Backend *B, const llvm::MCRegisterInfo &MRI,
@ -279,8 +280,7 @@ public:
checkScheduler(Index, Desc);
}
unsigned dispatch(unsigned IID, Instruction *NewInst,
const llvm::MCSubtargetInfo &STI);
void dispatch(unsigned IID, Instruction *I, const llvm::MCSubtargetInfo &STI);
void collectWrites(llvm::SmallVectorImpl<WriteState *> &Vec,
unsigned RegID) const {
@ -306,7 +306,6 @@ public:
void dump() const;
#endif
};
} // namespace mca
#endif

View File

@ -92,10 +92,12 @@ void WriteState::dump() const {
}
#endif
void Instruction::dispatch() {
void Instruction::dispatch(unsigned RCUToken) {
assert(Stage == IS_INVALID);
Stage = IS_AVAILABLE;
RCUTokenID = RCUToken;
// Check if input operands are already available.
if (std::all_of(Uses.begin(), Uses.end(),
[](const UniqueUse &Use) { return Use->isReady(); }))
Stage = IS_READY;
@ -104,8 +106,14 @@ void Instruction::dispatch() {
void Instruction::execute() {
assert(Stage == IS_READY);
Stage = IS_EXECUTING;
// Set the cycles left before the write-back stage.
setCyclesLeft(Desc.MaxLatency);
for (UniqueDef &Def : Defs)
Def->onInstructionIssued();
// Transition to the "executed" stage if this is a zero-latency instruction.
if (!CyclesLeft)
Stage = IS_EXECUTED;
}

View File

@ -110,11 +110,9 @@ public:
int getCyclesLeft() const { return CyclesLeft; }
unsigned getWriteResourceID() const { return WD.SClassOrWriteResourceID; }
unsigned getRegisterID() const { return RegisterID; }
void setRegisterID(unsigned ID) { RegisterID = ID; }
void addUser(ReadState *Use, int ReadAdvance);
bool fullyUpdatesSuperRegs() const { return WD.FullyUpdatesSuperRegs; }
bool isWrittenBack() const { return CyclesLeft == 0; }
// On every cycle, update CyclesLeft and notify dependent users.
void cycleEvent();
@ -291,22 +289,16 @@ public:
unsigned getRCUTokenID() const { return RCUTokenID; }
int getCyclesLeft() const { return CyclesLeft; }
void setCyclesLeft(int Cycles) { CyclesLeft = Cycles; }
void setRCUTokenID(unsigned TokenID) { RCUTokenID = TokenID; }
// Transition to the dispatch stage.
// No definition is updated because the instruction is not "executing".
void dispatch();
// Transition to the dispatch stage, and assign a RCUToken to this
// instruction. The RCUToken is used to track the completion of every
// register write performed by this instruction.
void dispatch(unsigned RCUTokenID);
// Instruction issued. Transition to the IS_EXECUTING state, and update
// all the definitions.
void execute();
void forceExecuted() {
assert((Stage == IS_INVALID && isZeroLatency()) ||
(Stage == IS_READY && Desc.MaxLatency == 0));
Stage = IS_EXECUTED;
}
bool isDispatched() const { return Stage == IS_AVAILABLE; }
bool isReady() const { return Stage == IS_READY; }
bool isExecuting() const { return Stage == IS_EXECUTING; }

View File

@ -241,16 +241,16 @@ void Scheduler::scheduleInstruction(unsigned Idx, Instruction &MCIS) {
// eliminated at register renaming stage, since we know in advance that those
// clear their output register.
if (MCIS.isZeroLatency()) {
assert(MCIS.isReady() && "data dependent zero-latency instruction?");
notifyInstructionReady(Idx);
MCIS.forceExecuted();
MCIS.execute();
notifyInstructionIssued(Idx, {});
assert(MCIS.isExecuted() && "Unexpected non-zero latency!");
notifyInstructionExecuted(Idx);
return;
}
// Consume entries in the reservation stations.
const InstrDesc &Desc = MCIS.getDesc();
if (!Desc.Buffers.empty()) {
// Reserve a slot in each buffered resource. Also, mark units with
// BufferSize=0 as reserved. Resources with a buffer size of zero will only
@ -265,7 +265,6 @@ void Scheduler::scheduleInstruction(unsigned Idx, Instruction &MCIS) {
if (MayLoad || MayStore)
LSU->reserve(Idx, MayLoad, MayStore, Desc.HasSideEffects);
MCIS.dispatch();
bool IsReady = MCIS.isReady();
if (IsReady && (MayLoad || MayStore))
IsReady &= LSU->isReady(Idx);