diff --git a/llvm/tools/llvm-mca/Backend.cpp b/llvm/tools/llvm-mca/Backend.cpp index c17d48ca1509..966682944988 100644 --- a/llvm/tools/llvm-mca/Backend.cpp +++ b/llvm/tools/llvm-mca/Backend.cpp @@ -31,26 +31,18 @@ void Backend::addEventListener(HWEventListener *Listener) { void Backend::runCycle(unsigned Cycle) { notifyCycleBegin(Cycle); - if (!SM.hasNext()) { - notifyCycleEnd(Cycle); - return; - } - - InstRef IR = SM.peekNext(); - const InstrDesc *Desc = &IB->getOrCreateInstrDesc(STI, *IR.second); - while (DU->isAvailable(Desc->NumMicroOps) && DU->canDispatch(*Desc)) { - Instruction *NewIS = IB->createInstruction(STI, *DU, IR.first, *IR.second); - Instructions[IR.first] = std::unique_ptr(NewIS); - NewIS->setRCUTokenID(DU->dispatch(IR.first, NewIS)); - - // Check if we have dispatched all the instructions. - SM.updateNext(); - if (!SM.hasNext()) + while (SM.hasNext()) { + InstRef IR = SM.peekNext(); + std::unique_ptr NewIS( + IB->createInstruction(STI, IR.first, *IR.second)); + const InstrDesc &Desc = NewIS->getDesc(); + if (!DU->isAvailable(Desc.NumMicroOps) || !DU->canDispatch(Desc)) break; - // Prepare for the next round. - IR = SM.peekNext(); - Desc = &IB->getOrCreateInstrDesc(STI, *IR.second); + Instruction *IS = NewIS.get(); + Instructions[IR.first] = std::move(NewIS); + IS->setRCUTokenID(DU->dispatch(IR.first, IS, STI)); + SM.updateNext(); } notifyCycleEnd(Cycle); diff --git a/llvm/tools/llvm-mca/Dispatch.cpp b/llvm/tools/llvm-mca/Dispatch.cpp index a3aad1889450..33b5f4926c9f 100644 --- a/llvm/tools/llvm-mca/Dispatch.cpp +++ b/llvm/tools/llvm-mca/Dispatch.cpp @@ -237,7 +237,36 @@ bool DispatchUnit::checkScheduler(const InstrDesc &Desc) { return false; } -unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst) { +void DispatchUnit::updateRAWDependencies(ReadState &RS, + const MCSubtargetInfo &STI) { + SmallVector DependentWrites; + + collectWrites(DependentWrites, RS.getRegisterID()); + RS.setDependentWrites(DependentWrites.size()); + DEBUG(dbgs() << "Found " << DependentWrites.size() << " dependent writes\n"); + // 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(); + if (!RD.HasReadAdvanceEntries) { + for (WriteState *WS : DependentWrites) + WS->addUser(&RS, /* ReadAdvance */ 0); + return; + } + + const MCSchedModel &SM = STI.getSchedModel(); + const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID); + for (WriteState *WS : DependentWrites) { + unsigned WriteResID = WS->getWriteResourceID(); + int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.OpIndex, WriteResID); + WS->addUser(&RS, ReadAdvance); + } + // Prepare the set for another round. + DependentWrites.clear(); +} + +unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst, + const MCSubtargetInfo &STI) { assert(!CarryOver && "Cannot dispatch another instruction!"); unsigned NumMicroOps = NewInst->getDesc().NumMicroOps; if (NumMicroOps > DispatchWidth) { @@ -249,6 +278,18 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst) { AvailableEntries -= NumMicroOps; } + // Update RAW dependencies. + for (std::unique_ptr &RS : NewInst->getUses()) + updateRAWDependencies(*RS, STI); + + // Allocate temporary registers in the register file. + for (std::unique_ptr &WS : NewInst->getDefs()) + addNewRegisterMapping(*WS); + + // Set the cycles left before the write-back stage. + const InstrDesc &D = NewInst->getDesc(); + NewInst->setCyclesLeft(D.MaxLatency); + // Reserve slots in the RCU. unsigned RCUTokenID = RCU->reserveSlot(IID, NumMicroOps); NewInst->setRCUTokenID(RCUTokenID); diff --git a/llvm/tools/llvm-mca/Dispatch.h b/llvm/tools/llvm-mca/Dispatch.h index e810ddaf77b3..66ac2f7e64af 100644 --- a/llvm/tools/llvm-mca/Dispatch.h +++ b/llvm/tools/llvm-mca/Dispatch.h @@ -18,6 +18,7 @@ #include "Instruction.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include namespace mca { @@ -236,6 +237,7 @@ class DispatchUnit { bool checkRCU(const InstrDesc &Desc); bool checkScheduler(const InstrDesc &Desc); + void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI); void notifyInstructionDispatched(unsigned IID); public: @@ -263,7 +265,8 @@ public: return checkRCU(Desc) && checkRAT(Desc) && checkScheduler(Desc); } - unsigned dispatch(unsigned IID, Instruction *NewInst); + unsigned dispatch(unsigned IID, Instruction *NewInst, + const llvm::MCSubtargetInfo &STI); void collectWrites(llvm::SmallVectorImpl &Vec, unsigned RegID) const { diff --git a/llvm/tools/llvm-mca/InstrBuilder.cpp b/llvm/tools/llvm-mca/InstrBuilder.cpp index 35b3a3592fef..7c9ffdc7ed79 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.cpp +++ b/llvm/tools/llvm-mca/InstrBuilder.cpp @@ -419,14 +419,12 @@ const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCSubtargetInfo &STI, } Instruction *InstrBuilder::createInstruction(const MCSubtargetInfo &STI, - DispatchUnit &DU, unsigned Idx, - const MCInst &MCI) { + unsigned Idx, const MCInst &MCI) { const InstrDesc &D = getOrCreateInstrDesc(STI, MCI); Instruction *NewIS = new Instruction(D); // Populate Reads first. const MCSchedModel &SM = STI.getSchedModel(); - SmallVector DependentWrites; for (const ReadDescriptor &RD : D.Reads) { int RegID = -1; if (RD.OpIndex != -1) { @@ -447,34 +445,9 @@ Instruction *InstrBuilder::createInstruction(const MCSubtargetInfo &STI, // Okay, this is a register operand. Create a ReadState for it. assert(RegID > 0 && "Invalid register ID found!"); - ReadState *NewRDS = new ReadState(RD); + ReadState *NewRDS = new ReadState(RD, RegID); NewIS->getUses().emplace_back(std::unique_ptr(NewRDS)); - DU.collectWrites(DependentWrites, RegID); - NewRDS->setDependentWrites(DependentWrites.size()); - DEBUG(dbgs() << "Found " << DependentWrites.size() - << " dependent writes\n"); - - // 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 after how many cycles this read becomes available. - if (!RD.HasReadAdvanceEntries) { - for (WriteState *WS : DependentWrites) - WS->addUser(NewRDS, /* ReadAdvance */ 0); - // Prepare the set for another round. - DependentWrites.clear(); - continue; - } - - const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID); - for (WriteState *WS : DependentWrites) { - unsigned WriteResID = WS->getWriteResourceID(); - int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.OpIndex, WriteResID); - WS->addUser(NewRDS, ReadAdvance); - } - - // Prepare the set for another round. - DependentWrites.clear(); - } + } // Now populate writes. for (const WriteDescriptor &WD : D.Writes) { @@ -489,11 +462,8 @@ Instruction *InstrBuilder::createInstruction(const MCSubtargetInfo &STI, WriteState *NewWS = new WriteState(WD); NewIS->getDefs().emplace_back(std::unique_ptr(NewWS)); NewWS->setRegisterID(RegID); - DU.addNewRegisterMapping(*NewWS); } - // Update Latency. - NewIS->setCyclesLeft(D.MaxLatency); return NewIS; } diff --git a/llvm/tools/llvm-mca/InstrBuilder.h b/llvm/tools/llvm-mca/InstrBuilder.h index ddbd2835b9da..252b68ca5b0a 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.h +++ b/llvm/tools/llvm-mca/InstrBuilder.h @@ -15,7 +15,6 @@ #ifndef LLVM_TOOLS_LLVM_MCA_INSTRBUILDER_H #define LLVM_TOOLS_LLVM_MCA_INSTRBUILDER_H -#include "Dispatch.h" #include "Instruction.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -53,7 +52,7 @@ public: const llvm::MCInst &MCI); Instruction *createInstruction(const llvm::MCSubtargetInfo &STI, - DispatchUnit &DU, unsigned Idx, + unsigned Idx, const llvm::MCInst &MCI); }; diff --git a/llvm/tools/llvm-mca/Instruction.h b/llvm/tools/llvm-mca/Instruction.h index 8d0bb0f529d1..a7601931c616 100644 --- a/llvm/tools/llvm-mca/Instruction.h +++ b/llvm/tools/llvm-mca/Instruction.h @@ -131,6 +131,7 @@ public: /// writes only partially update the register associated to this read. class ReadState { const ReadDescriptor &RD; + unsigned RegisterID; unsigned DependentWrites; int CyclesLeft; unsigned TotalCycles; @@ -142,14 +143,15 @@ public: return (CyclesLeft == UNKNOWN_CYCLES || CyclesLeft == 0); } - ReadState(const ReadDescriptor &Desc) - : RD(Desc), DependentWrites(0), CyclesLeft(UNKNOWN_CYCLES), - TotalCycles(0) {} + ReadState(const ReadDescriptor &Desc, unsigned RegID) + : RD(Desc), RegisterID(RegID), DependentWrites(0), + CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0) {} ReadState(const ReadState &Other) = delete; ReadState &operator=(const ReadState &Other) = delete; const ReadDescriptor &getDescriptor() const { return RD; } unsigned getSchedClass() const { return RD.SchedClassID; } + unsigned getRegisterID() const { return RegisterID; } void cycleEvent(); void writeStartEvent(unsigned Cycles); void setDependentWrites(unsigned Writes) { DependentWrites = Writes; }