From e2bef9a9026a5f62c8ec478031e4d3cbb170fb9e Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Tue, 3 Apr 2018 16:46:23 +0000 Subject: [PATCH] [llvm-mca] Move the logic that prints register file statistics to its own view. NFCI Before this patch, the "BackendStatistics" view was responsible for printing the register file usage (as well as many other statistics). Now users can enable register file usage statistics using the command line flag `-register-file-stats`. By default, the tool doesn't print register file statistics. llvm-svn: 329083 --- docs/CommandGuide/llvm-mca.rst | 4 + .../llvm-mca/X86/BtVer2/register-files-1.s | 2 +- .../llvm-mca/X86/BtVer2/register-files-2.s | 2 +- .../llvm-mca/X86/BtVer2/register-files-3.s | 2 +- .../llvm-mca/X86/BtVer2/register-files-4.s | 2 +- .../llvm-mca/X86/BtVer2/register-files-5.s | 2 +- tools/llvm-mca/BackendStatistics.cpp | 74 ------------ tools/llvm-mca/BackendStatistics.h | 24 +--- tools/llvm-mca/CMakeLists.txt | 1 + tools/llvm-mca/RegisterFileStatistics.cpp | 108 ++++++++++++++++++ tools/llvm-mca/RegisterFileStatistics.h | 67 +++++++++++ tools/llvm-mca/llvm-mca.cpp | 9 ++ 12 files changed, 195 insertions(+), 102 deletions(-) create mode 100644 tools/llvm-mca/RegisterFileStatistics.cpp create mode 100644 tools/llvm-mca/RegisterFileStatistics.h diff --git a/docs/CommandGuide/llvm-mca.rst b/docs/CommandGuide/llvm-mca.rst index 97a27f043c6..bcb03bdc58e 100644 --- a/docs/CommandGuide/llvm-mca.rst +++ b/docs/CommandGuide/llvm-mca.rst @@ -128,6 +128,10 @@ option specifies "``-``", then the output will also be sent to standard output. Enable the resource pressure view. This is enabled by default. +.. option:: -register-file-stats + + Enable register file usage statistics. + .. option:: -instruction-info Enable the instruction info view. This is enabled by default. diff --git a/test/tools/llvm-mca/X86/BtVer2/register-files-1.s b/test/tools/llvm-mca/X86/BtVer2/register-files-1.s index 5fe5e5b6389..d7fd25fbe46 100644 --- a/test/tools/llvm-mca/X86/BtVer2/register-files-1.s +++ b/test/tools/llvm-mca/X86/BtVer2/register-files-1.s @@ -1,4 +1,4 @@ -# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=5 -verbose -timeline < %s | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=5 -verbose -register-file-stats -timeline < %s | FileCheck %s vaddps %xmm0, %xmm0, %xmm0 vmulps %xmm0, %xmm0, %xmm0 diff --git a/test/tools/llvm-mca/X86/BtVer2/register-files-2.s b/test/tools/llvm-mca/X86/BtVer2/register-files-2.s index c077acea582..03785f7d3f9 100644 --- a/test/tools/llvm-mca/X86/BtVer2/register-files-2.s +++ b/test/tools/llvm-mca/X86/BtVer2/register-files-2.s @@ -1,4 +1,4 @@ -# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=5 -verbose -timeline < %s | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=5 -verbose -register-file-stats -timeline < %s | FileCheck %s vaddps %xmm0, %xmm0, %xmm0 vmulps %xmm0, %xmm0, %xmm0 diff --git a/test/tools/llvm-mca/X86/BtVer2/register-files-3.s b/test/tools/llvm-mca/X86/BtVer2/register-files-3.s index 73215e36a71..447143f8281 100644 --- a/test/tools/llvm-mca/X86/BtVer2/register-files-3.s +++ b/test/tools/llvm-mca/X86/BtVer2/register-files-3.s @@ -1,4 +1,4 @@ -# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=2 -verbose -timeline < %s | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=2 -verbose -register-file-stats -timeline < %s | FileCheck %s idiv %eax diff --git a/test/tools/llvm-mca/X86/BtVer2/register-files-4.s b/test/tools/llvm-mca/X86/BtVer2/register-files-4.s index 25e6deba5f9..86c508af2e4 100644 --- a/test/tools/llvm-mca/X86/BtVer2/register-files-4.s +++ b/test/tools/llvm-mca/X86/BtVer2/register-files-4.s @@ -1,4 +1,4 @@ -# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=22 -verbose -timeline -timeline-max-iterations=3 < %s | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=22 -verbose -register-file-stats -timeline -timeline-max-iterations=3 < %s | FileCheck %s idiv %eax diff --git a/test/tools/llvm-mca/X86/BtVer2/register-files-5.s b/test/tools/llvm-mca/X86/BtVer2/register-files-5.s index 64c489e2b7a..704869fd4fc 100644 --- a/test/tools/llvm-mca/X86/BtVer2/register-files-5.s +++ b/test/tools/llvm-mca/X86/BtVer2/register-files-5.s @@ -1,4 +1,4 @@ -# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -resource-pressure=false -instruction-info=false -verbose -timeline < %s | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -resource-pressure=false -instruction-info=false -verbose -register-file-stats -timeline < %s | FileCheck %s vdivps %ymm0, %ymm0, %ymm1 vaddps %ymm0, %ymm0, %ymm2 diff --git a/tools/llvm-mca/BackendStatistics.cpp b/tools/llvm-mca/BackendStatistics.cpp index d89570b18ff..e40eb73480e 100644 --- a/tools/llvm-mca/BackendStatistics.cpp +++ b/tools/llvm-mca/BackendStatistics.cpp @@ -20,35 +20,11 @@ using namespace llvm; namespace mca { -void BackendStatistics::initializeRegisterFileInfo() { - const MCSchedModel &SM = STI.getSchedModel(); - RegisterFileUsage Empty = {0, 0, 0}; - if (!SM.hasExtraProcessorInfo()) { - // Assume a single register file. - RegisterFiles.emplace_back(Empty); - return; - } - - // Initialize a RegisterFileUsage for every user defined register file, plus - // the default register file which is always at index #0. - const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo(); - // There is always an "InvalidRegisterFile" entry in tablegen. That entry can - // be skipped. If there are no user defined register files, then reserve a - // single entry for the default register file at index #0. - unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U); - RegisterFiles.resize(NumRegFiles); - std::fill(RegisterFiles.begin(), RegisterFiles.end(), Empty); -} - void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) { switch (Event.Type) { 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; } @@ -56,16 +32,6 @@ void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) { ++NumIssued; break; 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; } } @@ -150,46 +116,6 @@ void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const { OS << Buffer; } -void BackendStatistics::printRATStatistics(raw_ostream &OS) const { - std::string Buffer; - raw_string_ostream TempStream(Buffer); - - TempStream << "\n\nRegister File statistics:"; - const RegisterFileUsage &GlobalUsage = RegisterFiles[0]; - TempStream << "\nTotal number of mappings created: " - << GlobalUsage.TotalMappings; - TempStream << "\nMax number of mappings used: " - << GlobalUsage.MaxUsedMappings << '\n'; - - for (unsigned I = 1, E = RegisterFiles.size(); I < E; ++I) { - const RegisterFileUsage &RFU = RegisterFiles[I]; - // Obtain the register file descriptor from the scheduling model. - assert(STI.getSchedModel().hasExtraProcessorInfo() && - "Unable to find register file info!"); - const MCExtraProcessorInfo &PI = - STI.getSchedModel().getExtraProcessorInfo(); - assert(I <= PI.NumRegisterFiles && "Unexpected register file index!"); - const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I]; - // Skip invalid register files. - if (!RFDesc.NumPhysRegs) - continue; - - TempStream << "\n* Register File #" << I; - TempStream << " -- " << StringRef(RFDesc.Name) << ':'; - TempStream << "\n Number of physical registers: "; - if (!RFDesc.NumPhysRegs) - TempStream << "unbounded"; - else - TempStream << RFDesc.NumPhysRegs; - TempStream << "\n Total number of mappings created: " << RFU.TotalMappings; - TempStream << "\n Max number of mappings used: " - << RFU.MaxUsedMappings << '\n'; - } - - TempStream.flush(); - OS << Buffer; -} - void BackendStatistics::printDispatchStalls(raw_ostream &OS) const { std::string Buffer; raw_string_ostream TempStream(Buffer); diff --git a/tools/llvm-mca/BackendStatistics.h b/tools/llvm-mca/BackendStatistics.h index c3cec95f8df..7de38b45a7d 100644 --- a/tools/llvm-mca/BackendStatistics.h +++ b/tools/llvm-mca/BackendStatistics.h @@ -23,11 +23,6 @@ /// GROUP - Static restrictions on the dispatch group: 0 /// /// -/// Register Alias Table: -/// Total number of mappings created: 210 -/// Max number of mappings used: 35 -/// -/// /// Dispatch Logic - number of cycles where we saw N instructions dispatched: /// [# dispatched], [# cycles] /// 0, 15 (11.5%) @@ -61,7 +56,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/raw_ostream.h" namespace mca { @@ -102,24 +96,11 @@ 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 initializeRegisterFileInfo(); - 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) const; void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram, unsigned Cycles) const; void printDispatchUnitUsage(llvm::raw_ostream &OS, const Histogram &Stats, @@ -132,9 +113,7 @@ class BackendStatistics : public View { public: BackendStatistics(const llvm::MCSubtargetInfo &sti) : STI(sti), NumDispatched(0), NumIssued(0), NumRetired(0), NumCycles(0), - HWStalls(HWStallEvent::LastGenericEvent) { - initializeRegisterFileInfo(); - } + HWStalls(HWStallEvent::LastGenericEvent) { } void onInstructionEvent(const HWInstructionEvent &Event) override; @@ -157,7 +136,6 @@ public: void printView(llvm::raw_ostream &OS) const override { printDispatchStalls(OS); - printRATStatistics(OS); printDispatchUnitStatistics(OS); printSchedulerStatistics(OS); printRetireUnitStatistics(OS); diff --git a/tools/llvm-mca/CMakeLists.txt b/tools/llvm-mca/CMakeLists.txt index 36af64c0bd8..2964fde0309 100644 --- a/tools/llvm-mca/CMakeLists.txt +++ b/tools/llvm-mca/CMakeLists.txt @@ -21,6 +21,7 @@ add_llvm_tool(llvm-mca InstructionTables.cpp LSUnit.cpp llvm-mca.cpp + RegisterFileStatistics.cpp ResourcePressureView.cpp Scheduler.cpp Support.cpp diff --git a/tools/llvm-mca/RegisterFileStatistics.cpp b/tools/llvm-mca/RegisterFileStatistics.cpp new file mode 100644 index 00000000000..46302bf41b2 --- /dev/null +++ b/tools/llvm-mca/RegisterFileStatistics.cpp @@ -0,0 +1,108 @@ +//===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements the RegisterFileStatistics interface. +/// +//===----------------------------------------------------------------------===// + +#include "RegisterFileStatistics.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +namespace mca { + +void RegisterFileStatistics::initializeRegisterFileInfo() { + const MCSchedModel &SM = STI.getSchedModel(); + RegisterFileUsage Empty = {0, 0, 0}; + if (!SM.hasExtraProcessorInfo()) { + // Assume a single register file. + RegisterFiles.emplace_back(Empty); + return; + } + + // Initialize a RegisterFileUsage for every user defined register file, plus + // the default register file which is always at index #0. + const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo(); + // There is always an "InvalidRegisterFile" entry in tablegen. That entry can + // be skipped. If there are no user defined register files, then reserve a + // single entry for the default register file at index #0. + unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U); + RegisterFiles.resize(NumRegFiles); + std::fill(RegisterFiles.begin(), RegisterFiles.end(), Empty); +} + +void RegisterFileStatistics::onInstructionEvent( + const HWInstructionEvent &Event) { + switch (Event.Type) { + 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]; + break; + } + 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); + } + } + } +} + +void RegisterFileStatistics::printView(raw_ostream &OS) const { + std::string Buffer; + raw_string_ostream TempStream(Buffer); + + TempStream << "\n\nRegister File statistics:"; + const RegisterFileUsage &GlobalUsage = RegisterFiles[0]; + TempStream << "\nTotal number of mappings created: " + << GlobalUsage.TotalMappings; + TempStream << "\nMax number of mappings used: " + << GlobalUsage.MaxUsedMappings << '\n'; + + for (unsigned I = 1, E = RegisterFiles.size(); I < E; ++I) { + const RegisterFileUsage &RFU = RegisterFiles[I]; + // Obtain the register file descriptor from the scheduling model. + assert(STI.getSchedModel().hasExtraProcessorInfo() && + "Unable to find register file info!"); + const MCExtraProcessorInfo &PI = + STI.getSchedModel().getExtraProcessorInfo(); + assert(I <= PI.NumRegisterFiles && "Unexpected register file index!"); + const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I]; + // Skip invalid register files. + if (!RFDesc.NumPhysRegs) + continue; + + TempStream << "\n* Register File #" << I; + TempStream << " -- " << StringRef(RFDesc.Name) << ':'; + TempStream << "\n Number of physical registers: "; + if (!RFDesc.NumPhysRegs) + TempStream << "unbounded"; + else + TempStream << RFDesc.NumPhysRegs; + TempStream << "\n Total number of mappings created: " + << RFU.TotalMappings; + TempStream << "\n Max number of mappings used: " + << RFU.MaxUsedMappings << '\n'; + } + + TempStream.flush(); + OS << Buffer; +} + +} // namespace mca diff --git a/tools/llvm-mca/RegisterFileStatistics.h b/tools/llvm-mca/RegisterFileStatistics.h new file mode 100644 index 00000000000..d36b61ecd2b --- /dev/null +++ b/tools/llvm-mca/RegisterFileStatistics.h @@ -0,0 +1,67 @@ +//===--------------------- RegisterFileStatistics.h -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This view collects and prints register file usage statistics. +/// +/// Example (-mcpu=btver2): +/// ======================== +/// +/// Register File statistics: +/// Total number of mappings created: 6 +/// Max number of mappings used: 3 +/// +/// * Register File #1 -- FpuPRF: +/// Number of physical registers: 72 +/// Total number of mappings created: 0 +/// Max number of mappings used: 0 +/// +/// * Register File #2 -- IntegerPRF: +/// Number of physical registers: 64 +/// Total number of mappings created: 6 +/// Max number of mappings used: 3 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H +#define LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H + +#include "View.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCSubtargetInfo.h" + +namespace mca { + +class RegisterFileStatistics : public View { + const llvm::MCSubtargetInfo &STI; + + // 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 initializeRegisterFileInfo(); + +public: + RegisterFileStatistics(const llvm::MCSubtargetInfo &sti) : STI(sti) { + initializeRegisterFileInfo(); + } + + void onInstructionEvent(const HWInstructionEvent &Event) override; + + void printView(llvm::raw_ostream &OS) const override; +}; +} // namespace mca + +#endif diff --git a/tools/llvm-mca/llvm-mca.cpp b/tools/llvm-mca/llvm-mca.cpp index 49d50476354..7ad31df3ce8 100644 --- a/tools/llvm-mca/llvm-mca.cpp +++ b/tools/llvm-mca/llvm-mca.cpp @@ -25,6 +25,7 @@ #include "BackendStatistics.h" #include "InstructionInfoView.h" #include "InstructionTables.h" +#include "RegisterFileStatistics.h" #include "ResourcePressureView.h" #include "SummaryView.h" #include "TimelineView.h" @@ -91,6 +92,11 @@ static cl::opt "be used for register mappings"), cl::init(0)); +static cl::opt + PrintRegisterFileStats("register-file-stats", + cl::desc("Print register file statistics"), + cl::init(false)); + static cl::opt PrintResourcePressureView("resource-pressure", cl::desc("Print the resource pressure view"), @@ -370,6 +376,9 @@ int main(int argc, char **argv) { if (PrintModeVerbose) Printer->addView(llvm::make_unique(*STI)); + if (PrintRegisterFileStats) + Printer->addView(llvm::make_unique(*STI)); + if (PrintResourcePressureView) Printer->addView( llvm::make_unique(*STI, *IP, *S));