From: Andrea Di Biagio Date: Wed, 21 Mar 2018 18:11:05 +0000 (+0000) Subject: [llvm-mca] Move the logic that computes the register file usage to the BackendStatist... X-Git-Tag: llvmorg-7.0.0-rc1~10018 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=12ef5260ea2fada35c830266e926441c671cf5a5;p=platform%2Fupstream%2Fllvm.git [llvm-mca] Move the logic that computes the register file usage to the BackendStatistics view. With this patch, the "instruction dispatched" event now provides information related to the number of microarchitectural registers used in each register file. Similarly, the "instruction retired" event is now able to tell how may registers are freed in each register file. Currently, the BackendStatistics view is the only consumer of register usage/pressure information. BackendStatistics uses that info to print out a few general statistics (i.e. max number of mappings used; total mapping created). Before this patch, the BackendStatistics was forced to query the Backend to obtain the register pressure information. This helps removes that dependency. Now views are completely independent from the Backend. As a consequence, it should be easier to address PR36663 and further modularize the pipeline. Added a couple of test cases in the BtVer2 specific directory. llvm-svn: 328129 --- 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 000000000000..390201ec2fdc --- /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 000000000000..d5c3fd747c25 --- /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 513904bf6c64..027850ecba54 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 64b8be11e4d6..c5425509064e 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(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(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 77bd089196c1..aff3bdeb736b 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; @@ -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 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 3614d4d0972f..36f1bc3b716d 100644 --- a/llvm/tools/llvm-mca/Dispatch.cpp +++ b/llvm/tools/llvm-mca/Dispatch.cpp @@ -45,7 +45,8 @@ void RegisterFile::addRegisterFile(ArrayRef RegisterClasses, } } -void RegisterFile::createNewMappings(unsigned RegisterFileMask) { +void RegisterFile::createNewMappings(unsigned RegisterFileMask, + MutableArrayRef 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 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 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 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 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 FreedRegs(RAT->getNumRegisterFiles()); for (const std::unique_ptr &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 RegisterFiles(RAT->getNumRegisterFiles()); for (std::unique_ptr &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 ceb361381143..c1093fa73ba9 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 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 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 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 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 &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 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 220c3ffed75d..2c3f7f31c7a7 100644 --- a/llvm/tools/llvm-mca/HWEventListener.h +++ b/llvm/tools/llvm-mca/HWEventListener.h @@ -68,6 +68,26 @@ public: llvm::ArrayRef> UsedResources; }; +class HWInstructionDispatchedEvent : public HWInstructionEvent { +public: + HWInstructionDispatchedEvent(unsigned Index, llvm::ArrayRef Regs) + : HWInstructionEvent(HWInstructionEvent::Dispatched, Index), + UsedPhysRegs(Regs) {} + // Number of physical register allocated for this instruction. There is one + // entry per register file. + llvm::ArrayRef UsedPhysRegs; +}; + +class HWInstructionRetiredEvent : public HWInstructionEvent { +public: + HWInstructionRetiredEvent(unsigned Index, llvm::ArrayRef 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 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 baba4056061f..88d33facd2b8 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 BS = - llvm::make_unique(*B, *STI); + llvm::make_unique(*STI); Printer->addView(std::move(BS)); }