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.
-# 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
-# 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
-# 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
-# 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
-# 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
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<const HWInstructionRetiredEvent &>(Event);
- for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I)
- RegisterFiles[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
-
++NumRetired;
break;
}
++NumIssued;
break;
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;
}
}
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);
/// 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%)
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/raw_ostream.h"
namespace mca {
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 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,
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;
void printView(llvm::raw_ostream &OS) const override {
printDispatchStalls(OS);
- printRATStatistics(OS);
printDispatchUnitStatistics(OS);
printSchedulerStatistics(OS);
printRetireUnitStatistics(OS);
InstructionTables.cpp
LSUnit.cpp
llvm-mca.cpp
+ RegisterFileStatistics.cpp
ResourcePressureView.cpp
Scheduler.cpp
Support.cpp
--- /dev/null
+//===--------------------- 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<const HWInstructionRetiredEvent &>(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<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);
+ }
+ }
+ }
+}
+
+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
--- /dev/null
+//===--------------------- 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<RegisterFileUsage, 4> 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
#include "BackendStatistics.h"
#include "InstructionInfoView.h"
#include "InstructionTables.h"
+#include "RegisterFileStatistics.h"
#include "ResourcePressureView.h"
#include "SummaryView.h"
#include "TimelineView.h"
cl::init(0));
static cl::opt<bool>
+ PrintRegisterFileStats("register-file-stats",
+ cl::desc("Print register file statistics"),
+ cl::init(false));
+
+static cl::opt<bool>
PrintResourcePressureView("resource-pressure",
cl::desc("Print the resource pressure view"),
cl::init(true));
if (PrintModeVerbose)
Printer->addView(llvm::make_unique<mca::BackendStatistics>(*STI));
+ if (PrintRegisterFileStats)
+ Printer->addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI));
+
if (PrintResourcePressureView)
Printer->addView(
llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, *S));