diff options
| -rw-r--r-- | llvm/include/llvm/MCA/Instruction.h | 43 | ||||
| -rw-r--r-- | llvm/lib/MCA/Instruction.cpp | 34 |
2 files changed, 63 insertions, 14 deletions
diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h index a7a47fd3645..c4d0f6aace3 100644 --- a/llvm/include/llvm/MCA/Instruction.h +++ b/llvm/include/llvm/MCA/Instruction.h @@ -80,6 +80,16 @@ struct ReadDescriptor { class ReadState; +/// Longest register dependency. +/// +/// Used internally by WriteState/ReadState/InstructionBase to help with the +/// computation of the longest register dependency for an instruction. +struct CriticalRegDep { + unsigned IID; + unsigned RegID; + unsigned Cycles; +}; + /// Tracks uses of a register definition (e.g. register write). /// /// Each implicit/explicit register write is associated with an instance of @@ -123,9 +133,11 @@ class WriteState { // A partial write that is in a false dependency with this write. WriteState *PartialWrite; - unsigned DependentWriteCyclesLeft; + // Critical register dependency for this write. + CriticalRegDep CRD; + // A list of dependent reads. Users is a set of dependent // reads. A dependent read is added to the set only if CyclesLeft // is "unknown". As soon as CyclesLeft is 'known', each user in the set @@ -140,7 +152,7 @@ public: : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), - DependentWriteCyclesLeft(0) {} + DependentWriteCyclesLeft(0), CRD() {} WriteState(const WriteState &Other) = default; WriteState &operator=(const WriteState &Other) = default; @@ -150,7 +162,11 @@ public: unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } unsigned getLatency() const { return WD->Latency; } + unsigned getDependentWriteCyclesLeft() const { + return DependentWriteCyclesLeft; + } const WriteState *getDependentWrite() const { return DependentWrite; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } // This method adds Use to the set of data dependent reads. IID is the // instruction identifier associated with this write. ReadAdvance is the @@ -162,10 +178,6 @@ public: // write. IID is the instruction identifier associated with this write. void addUser(unsigned IID, WriteState *Use); - unsigned getDependentWriteCyclesLeft() const { - return DependentWriteCyclesLeft; - } - unsigned getNumUsers() const { unsigned NumUsers = Users.size(); if (PartialWrite) @@ -189,11 +201,7 @@ public: } void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } - void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { - DependentWriteCyclesLeft = Cycles; - DependentWrite = nullptr; - } - + void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles); void setWriteZero() { WritesZero = true; } void setEliminated() { assert(Users.empty() && "Write is in an inconsistent state."); @@ -235,6 +243,8 @@ class ReadState { // dependent writes (i.e. field DependentWrite) is zero, this value is // propagated to field CyclesLeft. unsigned TotalCycles; + // Longest register dependency. + CriticalRegDep CRD; // This field is set to true only if there are no dependent writes, and // there are no `CyclesLeft' to wait. bool IsReady; @@ -246,13 +256,14 @@ class ReadState { public: ReadState(const ReadDescriptor &Desc, unsigned RegID) : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), - CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true), - IsZero(false), IndependentFromDef(false) {} + CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), + IsReady(true), IsZero(false), IndependentFromDef(false) {} const ReadDescriptor &getDescriptor() const { return *RD; } unsigned getSchedClass() const { return RD->SchedClassID; } unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } bool isReady() const { return IsReady; } @@ -394,6 +405,9 @@ class InstructionBase { // One entry per each implicit and explicit register use. SmallVector<ReadState, 4> Uses; + // Critical register dependency. + CriticalRegDep CRD; + public: InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {} @@ -405,6 +419,9 @@ public: unsigned getLatency() const { return Desc.MaxLatency; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } + const CriticalRegDep &computeCriticalRegDep(); + bool hasDependentUsers() const { return any_of(Defs, [](const WriteState &Def) { return Def.getNumUsers() > 0; }); diff --git a/llvm/lib/MCA/Instruction.cpp b/llvm/lib/MCA/Instruction.cpp index 58f02503137..5e2fb771e4f 100644 --- a/llvm/lib/MCA/Instruction.cpp +++ b/llvm/lib/MCA/Instruction.cpp @@ -18,6 +18,14 @@ namespace llvm { namespace mca { +void WriteState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { + CRD.IID = IID; + CRD.RegID = RegID; + CRD.Cycles = Cycles; + DependentWriteCyclesLeft = Cycles; + DependentWrite = nullptr; +} + void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { assert(DependentWrites); assert(CyclesLeft == UNKNOWN_CYCLES); @@ -28,7 +36,12 @@ void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { // The HW is forced to do some extra bookkeeping to track of all the // dependent writes, and implement a merging scheme for the partial writes. --DependentWrites; - TotalCycles = std::max(TotalCycles, Cycles); + if (TotalCycles < Cycles) { + CRD.IID = IID; + CRD.RegID = RegID; + CRD.Cycles = Cycles; + TotalCycles = Cycles; + } if (!DependentWrites) { CyclesLeft = TotalCycles; @@ -121,6 +134,25 @@ void WriteRef::dump() const { } #endif +const CriticalRegDep &InstructionBase::computeCriticalRegDep() { + if (CRD.Cycles || (Defs.empty() && Uses.empty())) + return CRD; + unsigned MaxLatency = 0; + for (const WriteState &WS : Defs) { + const CriticalRegDep &WriteCRD = WS.getCriticalRegDep(); + if (WriteCRD.Cycles > MaxLatency) + CRD = WriteCRD; + } + + for (const ReadState &RS : Uses) { + const CriticalRegDep &ReadCRD = RS.getCriticalRegDep(); + if (ReadCRD.Cycles > MaxLatency) + CRD = ReadCRD; + } + + return CRD; +} + void Instruction::dispatch(unsigned RCUToken) { assert(Stage == IS_INVALID); Stage = IS_DISPATCHED; |

