diff options
| -rw-r--r-- | llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s | 29 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s | 29 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/Backend.h | 6 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/BackendStatistics.cpp | 43 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/BackendStatistics.h | 28 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/Dispatch.cpp | 41 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/Dispatch.h | 38 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/HWEventListener.h | 20 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/llvm-mca.cpp | 2 |
9 files changed, 161 insertions, 75 deletions
diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s new file mode 100644 index 00000000000..390201ec2fd --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s @@ -0,0 +1,29 @@ +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=5 -verbose -timeline < %s | FileCheck %s + +vaddps %xmm0, %xmm0, %xmm0 +vmulps %xmm0, %xmm0, %xmm0 + +# CHECK: Iterations: 5 +# CHECK-NEXT: Instructions: 10 + +# CHECK: Dynamic Dispatch Stall Cycles: +# CHECK-NEXT: RAT - Register unavailable: 0 + +# CHECK: Register File statistics. +# CHECK-NEXT: Register File #0 +# CHECK-NEXT: Total number of mappings created: 10 +# CHECK-NEXT: Max number of mappings used: 10 + +# CHECK: Timeline view: +# CHECK-NEXT: 0123456789 +# CHECK-NEXT: Index 0123456789 01234567 +# CHECK: [0,0] DeeeER . . . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [0,1] D===eeER . . . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [1,0] .D====eeeER . . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [1,1] .D=======eeER . . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [2,0] . D========eeeER . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [2,1] . D===========eeER . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [3,0] . D============eeeER . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [3,1] . D===============eeER . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [4,0] . D================eeeER . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [4,1] . D===================eeER vmulps %xmm0, %xmm0, %xmm0 diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s new file mode 100644 index 00000000000..d5c3fd747c2 --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s @@ -0,0 +1,29 @@ +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=5 -verbose -timeline < %s | FileCheck %s + +vaddps %xmm0, %xmm0, %xmm0 +vmulps %xmm0, %xmm0, %xmm0 + +# CHECK: Iterations: 5 +# CHECK-NEXT: Instructions: 10 + +# CHECK: Dynamic Dispatch Stall Cycles: +# CHECK-NEXT: RAT - Register unavailable: 13 + +# CHECK: Register File statistics. +# CHECK-NEXT: Register File #0 +# CHECK-NEXT: Total number of mappings created: 10 +# CHECK-NEXT: Max number of mappings used: 5 + +# CHECK: Timeline view: +# CHECK-NEXT: 0123456789 +# CHECK-NEXT: Index 0123456789 01234567 +# CHECK: [0,0] DeeeER . . . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [0,1] D===eeER . . . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [1,0] .D====eeeER . . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [1,1] .D=======eeER . . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [2,0] . D========eeeER . . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [2,1] . D========eeER . . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [3,0] . . D========eeeER . . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [3,1] . . D========eeER . . vmulps %xmm0, %xmm0, %xmm0 +# CHECK: [4,0] . . . D========eeeER . vaddps %xmm0, %xmm0, %xmm0 +# CHECK-NEXT: [4,1] . . . D========eeER vmulps %xmm0, %xmm0, %xmm0 diff --git a/llvm/tools/llvm-mca/Backend.h b/llvm/tools/llvm-mca/Backend.h index 513904bf6c6..027850ecba5 100644 --- a/llvm/tools/llvm-mca/Backend.h +++ b/llvm/tools/llvm-mca/Backend.h @@ -88,12 +88,6 @@ public: return *It->second; } void eraseInstruction(unsigned Index) { Instructions.erase(Index); } - unsigned getTotalRegisterMappingsCreated() const { - return DU->getTotalRegisterMappingsCreated(); - } - unsigned getMaxUsedRegisterMappings() const { - return DU->getMaxUsedRegisterMappings(); - } void addEventListener(HWEventListener *Listener); void notifyCycleBegin(unsigned Cycle); diff --git a/llvm/tools/llvm-mca/BackendStatistics.cpp b/llvm/tools/llvm-mca/BackendStatistics.cpp index 64b8be11e4d..c5425509064 100644 --- a/llvm/tools/llvm-mca/BackendStatistics.cpp +++ b/llvm/tools/llvm-mca/BackendStatistics.cpp @@ -22,17 +22,32 @@ namespace mca { void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) { switch (Event.Type) { - case HWInstructionEvent::Retired: + default: + break; + case HWInstructionEvent::Retired: { + const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event); + for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) + RegisterFiles[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I]; + ++NumRetired; break; + } case HWInstructionEvent::Issued: ++NumIssued; break; - case HWInstructionEvent::Dispatched: + case HWInstructionEvent::Dispatched: { + const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event); + for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) { + RegisterFileUsage &RFU = RegisterFiles[I]; + unsigned NumUsedPhysRegs = DE.UsedPhysRegs[I]; + RFU.CurrentlyUsedMappings += NumUsedPhysRegs; + RFU.TotalMappings += NumUsedPhysRegs; + RFU.MaxUsedMappings = + std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings); + } + ++NumDispatched; - break; - default: - break; + } } } @@ -115,15 +130,19 @@ void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const { OS << Buffer; } -void BackendStatistics::printRATStatistics(raw_ostream &OS, - unsigned TotalMappings, - unsigned MaxUsedMappings) const { +void BackendStatistics::printRATStatistics(raw_ostream &OS) const { std::string Buffer; raw_string_ostream TempStream(Buffer); - TempStream << "\n\nRegister Alias Table:"; - TempStream << "\nTotal number of mappings created: " << TotalMappings; - TempStream << "\nMax number of mappings used: " << MaxUsedMappings - << '\n'; + + TempStream << "\n\nRegister File statistics."; + for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) { + const RegisterFileUsage &RFU = RegisterFiles[I]; + TempStream << "\nRegister File #" << I; + TempStream << "\n Total number of mappings created: " << RFU.TotalMappings; + TempStream << "\n Max number of mappings used: " + << RFU.MaxUsedMappings; + } + TempStream.flush(); OS << Buffer; } diff --git a/llvm/tools/llvm-mca/BackendStatistics.h b/llvm/tools/llvm-mca/BackendStatistics.h index 77bd089196c..aff3bdeb736 100644 --- a/llvm/tools/llvm-mca/BackendStatistics.h +++ b/llvm/tools/llvm-mca/BackendStatistics.h @@ -67,8 +67,6 @@ namespace mca { class BackendStatistics : public View { - // TODO: remove the dependency from Backend. - const Backend &B; const llvm::MCSubtargetInfo &STI; using Histogram = std::map<unsigned, unsigned>; @@ -105,13 +103,22 @@ class BackendStatistics : public View { NumRetired = 0; } + // Used to track the number of physical registers used in a register file. + struct RegisterFileUsage { + unsigned TotalMappings; + unsigned MaxUsedMappings; + unsigned CurrentlyUsedMappings; + }; + + // There is one entry for each register file implemented by the processor. + llvm::SmallVector<RegisterFileUsage, 4> RegisterFiles; + void printRetireUnitStatistics(llvm::raw_ostream &OS) const; void printDispatchUnitStatistics(llvm::raw_ostream &OS) const; void printSchedulerStatistics(llvm::raw_ostream &OS) const; void printDispatchStalls(llvm::raw_ostream &OS) const; - void printRATStatistics(llvm::raw_ostream &OS, unsigned Mappings, - unsigned MaxUsedMappings) const; + void printRATStatistics(llvm::raw_ostream &OS) const; void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram, unsigned Cycles) const; void printDispatchUnitUsage(llvm::raw_ostream &OS, const Histogram &Stats, @@ -122,9 +129,12 @@ class BackendStatistics : public View { const llvm::MCSchedModel &SM) const; public: - BackendStatistics(const Backend &backend, const llvm::MCSubtargetInfo &sti) - : B(backend), STI(sti), NumDispatched(0), NumIssued(0), NumRetired(0), - NumCycles(0), HWStalls(HWStallEvent::LastGenericEvent) {} + BackendStatistics(const llvm::MCSubtargetInfo &sti) + : STI(sti), NumDispatched(0), NumIssued(0), NumRetired(0), + NumCycles(0), HWStalls(HWStallEvent::LastGenericEvent), + // TODO: The view currently assumes a single register file. This will + // change in future. + RegisterFiles(1) {} void onInstructionEvent(const HWInstructionEvent &Event) override; @@ -147,12 +157,10 @@ public: void printView(llvm::raw_ostream &OS) const override { printDispatchStalls(OS); - printRATStatistics(OS, B.getTotalRegisterMappingsCreated(), - B.getMaxUsedRegisterMappings()); + printRATStatistics(OS); printDispatchUnitStatistics(OS); printSchedulerStatistics(OS); printRetireUnitStatistics(OS); - printSchedulerUsage(OS, STI.getSchedModel()); } }; diff --git a/llvm/tools/llvm-mca/Dispatch.cpp b/llvm/tools/llvm-mca/Dispatch.cpp index 3614d4d0972..36f1bc3b716 100644 --- a/llvm/tools/llvm-mca/Dispatch.cpp +++ b/llvm/tools/llvm-mca/Dispatch.cpp @@ -45,7 +45,8 @@ void RegisterFile::addRegisterFile(ArrayRef<unsigned> RegisterClasses, } } -void RegisterFile::createNewMappings(unsigned RegisterFileMask) { +void RegisterFile::createNewMappings(unsigned RegisterFileMask, + MutableArrayRef<unsigned> UsedPhysRegs) { assert(RegisterFileMask && "RegisterFileMask cannot be zero!"); // Notify each register file that contains RegID. do { @@ -53,13 +54,13 @@ void RegisterFile::createNewMappings(unsigned RegisterFileMask) { unsigned RegisterFileIndex = llvm::countTrailingZeros(NextRegisterFile); RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; RMT.NumUsedMappings++; - RMT.MaxUsedMappings = std::max(RMT.MaxUsedMappings, RMT.NumUsedMappings); - RMT.TotalMappingsCreated++; + UsedPhysRegs[RegisterFileIndex]++; RegisterFileMask ^= NextRegisterFile; } while (RegisterFileMask); } -void RegisterFile::removeMappings(unsigned RegisterFileMask) { +void RegisterFile::removeMappings(unsigned RegisterFileMask, + MutableArrayRef<unsigned> FreedPhysRegs) { assert(RegisterFileMask && "RegisterFileMask cannot be zero!"); // Notify each register file that contains RegID. do { @@ -68,11 +69,13 @@ void RegisterFile::removeMappings(unsigned RegisterFileMask) { RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; assert(RMT.NumUsedMappings); RMT.NumUsedMappings--; + FreedPhysRegs[RegisterFileIndex]++; RegisterFileMask ^= NextRegisterFile; } while (RegisterFileMask); } -void RegisterFile::addRegisterMapping(WriteState &WS) { +void RegisterFile::addRegisterMapping(WriteState &WS, + MutableArrayRef<unsigned> UsedPhysRegs) { unsigned RegID = WS.getRegisterID(); assert(RegID && "Adding an invalid register definition?"); @@ -81,7 +84,8 @@ void RegisterFile::addRegisterMapping(WriteState &WS) { for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) RegisterMappings[*I].first = &WS; - createNewMappings(Mapping.second); + createNewMappings(Mapping.second, UsedPhysRegs); + // If this is a partial update, then we are done. if (!WS.fullyUpdatesSuperRegs()) return; @@ -90,7 +94,8 @@ void RegisterFile::addRegisterMapping(WriteState &WS) { RegisterMappings[*I].first = &WS; } -void RegisterFile::invalidateRegisterMapping(const WriteState &WS) { +void RegisterFile::invalidateRegisterMapping( + const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) { unsigned RegID = WS.getRegisterID(); bool ShouldInvalidateSuperRegs = WS.fullyUpdatesSuperRegs(); @@ -102,7 +107,7 @@ void RegisterFile::invalidateRegisterMapping(const WriteState &WS) { if (!Mapping.first) return; - removeMappings(Mapping.second); + removeMappings(Mapping.second, FreedPhysRegs); if (Mapping.first == &WS) Mapping.first = nullptr; @@ -196,8 +201,6 @@ void RegisterFile::dump() const { dbgs() << "Register File #" << I; const RegisterMappingTracker &RMT = RegisterFiles[I]; dbgs() << "\n TotalMappings: " << RMT.TotalMappings - << "\n TotalMappingsCreated: " << RMT.TotalMappingsCreated - << "\n MaxUsedMappings: " << RMT.MaxUsedMappings << "\n NumUsedMappings: " << RMT.NumUsedMappings << '\n'; } } @@ -220,21 +223,20 @@ unsigned RetireControlUnit::reserveSlot(unsigned Index, unsigned NumMicroOps) { return TokenID; } -void DispatchUnit::notifyInstructionDispatched(unsigned Index) { +void DispatchUnit::notifyInstructionDispatched( + unsigned Index, ArrayRef<unsigned> UsedRegs) { DEBUG(dbgs() << "[E] Instruction Dispatched: " << Index << '\n'); - Owner->notifyInstructionEvent( - HWInstructionEvent(HWInstructionEvent::Dispatched, Index)); + Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(Index, UsedRegs)); } void DispatchUnit::notifyInstructionRetired(unsigned Index) { DEBUG(dbgs() << "[E] Instruction Retired: " << Index << '\n'); - Owner->notifyInstructionEvent( - HWInstructionEvent(HWInstructionEvent::Retired, Index)); - const Instruction &IS = Owner->getInstruction(Index); + SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles()); for (const std::unique_ptr<WriteState> &WS : IS.getDefs()) - RAT->invalidateRegisterMapping(*WS.get()); + RAT->invalidateRegisterMapping(*WS.get(), FreedRegs); + Owner->notifyInstructionEvent(HWInstructionRetiredEvent(Index, FreedRegs)); Owner->eraseInstruction(Index); } @@ -364,8 +366,9 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst, updateRAWDependencies(*RS, STI); // Allocate new mappings. + SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles()); for (std::unique_ptr<WriteState> &WS : NewInst->getDefs()) - RAT->addRegisterMapping(*WS); + RAT->addRegisterMapping(*WS, RegisterFiles); // Set the cycles left before the write-back stage. const InstrDesc &D = NewInst->getDesc(); @@ -374,7 +377,7 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst, // Reserve slots in the RCU. unsigned RCUTokenID = RCU->reserveSlot(IID, NumMicroOps); NewInst->setRCUTokenID(RCUTokenID); - notifyInstructionDispatched(IID); + notifyInstructionDispatched(IID, RegisterFiles); SC->scheduleInstruction(IID, *NewInst); return RCUTokenID; diff --git a/llvm/tools/llvm-mca/Dispatch.h b/llvm/tools/llvm-mca/Dispatch.h index ceb36138114..c1093fa73ba 100644 --- a/llvm/tools/llvm-mca/Dispatch.h +++ b/llvm/tools/llvm-mca/Dispatch.h @@ -43,14 +43,9 @@ class RegisterFile { const unsigned TotalMappings; // Number of mappings that are currently in use. unsigned NumUsedMappings; - // Maximum number of register mappings used. - unsigned MaxUsedMappings; - // Total number of mappings allocated during the entire execution. - unsigned TotalMappingsCreated; RegisterMappingTracker(unsigned NumMappings) - : TotalMappings(NumMappings), NumUsedMappings(0), MaxUsedMappings(0), - TotalMappingsCreated(0) {} + : TotalMappings(NumMappings), NumUsedMappings(0) {} }; // This is where information related to the various register files is kept. @@ -105,11 +100,13 @@ class RegisterFile { // Allocates a new register mapping in every register file specified by the // register file mask. This method is called from addRegisterMapping. - void createNewMappings(unsigned RegisterFileMask); + void createNewMappings(unsigned RegisterFileMask, + llvm::MutableArrayRef<unsigned> UsedPhysRegs); // Removes a previously allocated mapping from each register file in the // RegisterFileMask set. This method is called from invalidateRegisterMapping. - void removeMappings(unsigned RegisterFileMask); + void removeMappings(unsigned RegisterFileMask, + llvm::MutableArrayRef<unsigned> FreedPhysRegs); public: RegisterFile(const llvm::MCRegisterInfo &mri, unsigned TempRegs = 0) @@ -121,12 +118,14 @@ public: // Creates a new register mapping for RegID. // This reserves a microarchitectural register in every register file that // contains RegID. - void addRegisterMapping(WriteState &WS); + void addRegisterMapping(WriteState &WS, + llvm::MutableArrayRef<unsigned> UsedPhysRegs); // Invalidates register mappings associated to the input WriteState object. // This releases previously allocated mappings for the physical register // associated to the WriteState. - void invalidateRegisterMapping(const WriteState &WS); + void invalidateRegisterMapping(const WriteState &WS, + llvm::MutableArrayRef<unsigned> FreedPhysRegs); // Checks if there are enough microarchitectural registers in the register // files. Returns a "response mask" where each bit is the response from a @@ -138,16 +137,7 @@ public: void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes, unsigned RegID) const; void updateOnRead(ReadState &RS, unsigned RegID); - unsigned getMaxUsedRegisterMappings(unsigned RegisterFileIndex) const { - assert(RegisterFileIndex < getNumRegisterFiles() && - "Invalid register file index!"); - return RegisterFiles[RegisterFileIndex].MaxUsedMappings; - } - unsigned getTotalRegisterMappingsCreated(unsigned RegisterFileIndex) const { - assert(RegisterFileIndex < getNumRegisterFiles() && - "Invalid register file index!"); - return RegisterFiles[RegisterFileIndex].TotalMappingsCreated; - } + unsigned getNumRegisterFiles() const { return RegisterFiles.size(); } #ifndef NDEBUG @@ -260,7 +250,7 @@ class DispatchUnit { bool checkScheduler(unsigned Index, const InstrDesc &Desc); void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI); - void notifyInstructionDispatched(unsigned IID); + void notifyInstructionDispatched(unsigned IID, llvm::ArrayRef<unsigned> UsedPhysRegs); public: DispatchUnit(Backend *B, const llvm::MCRegisterInfo &MRI, @@ -296,12 +286,6 @@ public: unsigned RegID) const { return RAT->collectWrites(Vec, RegID); } - unsigned getMaxUsedRegisterMappings(unsigned RegFileIndex = 0) const { - return RAT->getMaxUsedRegisterMappings(RegFileIndex); - } - unsigned getTotalRegisterMappingsCreated(unsigned RegFileIndex = 0) const { - return RAT->getTotalRegisterMappingsCreated(RegFileIndex); - } void cycleEvent(unsigned Cycle) { RCU->cycleEvent(); diff --git a/llvm/tools/llvm-mca/HWEventListener.h b/llvm/tools/llvm-mca/HWEventListener.h index 220c3ffed75..2c3f7f31c7a 100644 --- a/llvm/tools/llvm-mca/HWEventListener.h +++ b/llvm/tools/llvm-mca/HWEventListener.h @@ -68,6 +68,26 @@ public: llvm::ArrayRef<std::pair<ResourceRef, unsigned>> UsedResources; }; +class HWInstructionDispatchedEvent : public HWInstructionEvent { +public: + HWInstructionDispatchedEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs) + : HWInstructionEvent(HWInstructionEvent::Dispatched, Index), + UsedPhysRegs(Regs) {} + // Number of physical register allocated for this instruction. There is one + // entry per register file. + llvm::ArrayRef<unsigned> UsedPhysRegs; +}; + +class HWInstructionRetiredEvent : public HWInstructionEvent { +public: + HWInstructionRetiredEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs) + : HWInstructionEvent(HWInstructionEvent::Retired, Index), + FreedPhysRegs(Regs) {} + // Number of register writes that have been architecturally committed. There + // is one entry per register file. + llvm::ArrayRef<unsigned> FreedPhysRegs; +}; + // A HWStallEvent represents a pipeline stall caused by the lack of hardware // resources. class HWStallEvent { diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index baba4056061..88d33facd2b 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -330,7 +330,7 @@ int main(int argc, char **argv) { if (PrintModeVerbose) { std::unique_ptr<mca::BackendStatistics> BS = - llvm::make_unique<mca::BackendStatistics>(*B, *STI); + llvm::make_unique<mca::BackendStatistics>(*STI); Printer->addView(std::move(BS)); } |

