[llvm-mca] Move the logic that prints scheduler statistics from BackendStatistics to its own view.

Added flag -scheduler-stats to print scheduler related statistics.

llvm-svn: 329792
This commit is contained in:
Andrea Di Biagio 2018-04-11 11:37:46 +00:00
parent d928201ac5
commit 1cc29c045e
9 changed files with 244 additions and 131 deletions

View File

@ -139,8 +139,7 @@ option specifies "``-``", then the output will also be sent to standard output.
.. option:: -verbose .. option:: -verbose
Enable verbose output. In particular, this flag enables a number of extra Enable verbose output. In particular, this flag enables a number of extra
statistics and performance counters for the dispatch logic, the reorder statistics and performance counters for the retire control unit.
buffer, the retire control unit and the register file.
.. option:: -timeline .. option:: -timeline
@ -170,6 +169,11 @@ option specifies "``-``", then the output will also be sent to standard output.
dispatch events, as well as static/dynamic dispatch stall events. This view dispatch events, as well as static/dynamic dispatch stall events. This view
is disabled by default. is disabled by default.
.. option:: -scheduler-stats
Enable extra scheduler statistics. This view collects and analyzes instruction
issue events. This view is disabled by default.
.. option:: -instruction-info .. option:: -instruction-info
Enable the instruction info view. This is enabled by default. Enable the instruction info view. This is enabled by default.

View File

@ -1,7 +1,13 @@
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m3 -iterations=1 -verbose -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL # RUN: llvm-mca -march=aarch64 -mcpu=exynos-m3 -iterations=1 -scheduler-stats -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m1 -iterations=1 -verbose -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL # RUN: llvm-mca -march=aarch64 -mcpu=exynos-m1 -iterations=1 -scheduler-stats -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
b t b t
# ALL: Schedulers - number of cycles where we saw N instructions issued:
# ALL-NEXT: [# issued], [# cycles]
# ALL-NEXT: 0, 1 (50.0%)
# ALL-NEXT: 1, 1 (50.0%)
# ALL: Scheduler's queue usage: # ALL: Scheduler's queue usage:
# ALL-NEXT: No scheduler resources used. # ALL-NEXT: No scheduler resources used.

View File

@ -1,8 +1,31 @@
# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -verbose < %s | FileCheck %s # RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -scheduler-stats < %s | FileCheck %s
vmulps (%rsi), %xmm0, %xmm0 vmulps (%rsi), %xmm0, %xmm0
add %rsi, %rsi add %rsi, %rsi
# CHECK: Iterations: 1
# CHECK-NEXT: Instructions: 2
# CHECK-NEXT: Total Cycles: 10
# CHECK-NEXT: Dispatch Width: 2
# CHECK-NEXT: IPC: 0.20
# CHECK: Instruction Info:
# CHECK-NEXT: [1]: #uOps
# CHECK-NEXT: [2]: Latency
# CHECK-NEXT: [3]: RThroughput
# CHECK-NEXT: [4]: MayLoad
# CHECK-NEXT: [5]: MayStore
# CHECK-NEXT: [6]: HasSideEffects
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
# CHECK-NEXT: 1 7 1.00 * vmulps (%rsi), %xmm0, %xmm0
# CHECK-NEXT: 1 1 0.50 addq %rsi, %rsi
# CHECK: Schedulers - number of cycles where we saw N instructions issued:
# CHECK-NEXT: [# issued], [# cycles]
# CHECK-NEXT: 0, 9 (90.0%)
# CHECK-NEXT: 2, 1 (10.0%)
# CHECK: Scheduler's queue usage: # CHECK: Scheduler's queue usage:
# CHECK-NEXT: JALU01, 1/20 # CHECK-NEXT: JALU01, 1/20
# CHECK-NEXT: JFPU01, 1/18 # CHECK-NEXT: JFPU01, 1/18
@ -26,9 +49,10 @@ add %rsi, %rsi
# CHECK: Resource pressure per iteration: # CHECK: Resource pressure per iteration:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
# CHECK-NEXT: - 1.00 - - 1.00 - 1.00 1.00 - - - - - - # CHECK-NEXT: - 1.00 - - 1.00 - 1.00 1.00 - - - - - -
# CHECK: Resource pressure by instruction: # CHECK: Resource pressure by instruction:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions:
# CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - vmulps (%rsi), %xmm0, %xmm0 # CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - vmulps (%rsi), %xmm0, %xmm0
# CHECK-NEXT: - 1.00 - - - - - - - - - - - - addq %rsi, %rsi # CHECK-NEXT: - 1.00 - - - - - - - - - - - - addq %rsi, %rsi

View File

@ -21,42 +21,11 @@ using namespace llvm;
namespace mca { namespace mca {
void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) { void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) {
switch (Event.Type) { if (Event.Type == HWInstructionEvent::Retired)
default:
break;
case HWInstructionEvent::Retired: {
++NumRetired; ++NumRetired;
break;
}
case HWInstructionEvent::Issued:
++NumIssued;
}
} }
void BackendStatistics::onReservedBuffers(ArrayRef<unsigned> Buffers) { void BackendStatistics::printView(llvm::raw_ostream &OS) const {
for (const unsigned Buffer : Buffers) {
if (BufferedResources.find(Buffer) != BufferedResources.end()) {
BufferUsage &BU = BufferedResources[Buffer];
BU.SlotsInUse++;
BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);
continue;
}
BufferedResources.insert(
std::pair<unsigned, BufferUsage>(Buffer, {1U, 1U}));
}
}
void BackendStatistics::onReleasedBuffers(ArrayRef<unsigned> Buffers) {
for (const unsigned Buffer : Buffers) {
assert(BufferedResources.find(Buffer) != BufferedResources.end() &&
"Buffered resource not in map?");
BufferUsage &BU = BufferedResources[Buffer];
BU.SlotsInUse--;
}
}
void BackendStatistics::printRetireUnitStatistics(llvm::raw_ostream &OS) const {
std::string Buffer; std::string Buffer;
raw_string_ostream TempStream(Buffer); raw_string_ostream TempStream(Buffer);
TempStream << "\n\nRetire Control Unit - " TempStream << "\n\nRetire Control Unit - "
@ -78,46 +47,4 @@ void BackendStatistics::printRetireUnitStatistics(llvm::raw_ostream &OS) const {
OS << Buffer; OS << Buffer;
} }
void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const {
std::string Buffer;
raw_string_ostream TempStream(Buffer);
TempStream << "\n\nSchedulers - number of cycles where we saw N instructions "
"issued:\n";
TempStream << "[# issued], [# cycles]\n";
for (const std::pair<unsigned, unsigned> &Entry : IssuedPerCycle) {
TempStream << " " << Entry.first << ", " << Entry.second << " ("
<< format("%.1f", ((double)Entry.second / NumCycles) * 100)
<< "%)\n";
}
TempStream.flush();
OS << Buffer;
}
void BackendStatistics::printSchedulerUsage(raw_ostream &OS,
const MCSchedModel &SM) const {
std::string Buffer;
raw_string_ostream TempStream(Buffer);
TempStream << "\n\nScheduler's queue usage:\n";
// Early exit if no buffered resources were consumed.
if (BufferedResources.empty()) {
TempStream << "No scheduler resources used.\n";
TempStream.flush();
OS << Buffer;
return;
}
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
if (ProcResource.BufferSize <= 0)
continue;
const BufferUsage &BU = BufferedResources.lookup(I);
TempStream << ProcResource.Name << ", " << BU.MaxUsedSlots << '/'
<< ProcResource.BufferSize << '\n';
}
TempStream.flush();
OS << Buffer;
}
} // namespace mca } // namespace mca

View File

@ -8,18 +8,12 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// \file /// \file
/// ///
/// This file implements a printer class for printing generic Backend /// This file implements a View named BackendStatistics that knows how to
/// statistics related to the scheduler and retire unit. /// collect and print a few statistics related to the retire unit.
/// ///
/// Example: /// Example:
/// ======== /// ========
/// ///
/// Schedulers - number of cycles where we saw N instructions issued:
/// [# issued], [# cycles]
/// 0, 7 (5.4%)
/// 1, 4 (3.1%)
/// 2, 8 (6.2%)
///
/// Retire Control Unit - number of cycles where we saw N instructions retired: /// Retire Control Unit - number of cycles where we saw N instructions retired:
/// [# retired], [# cycles] /// [# retired], [# cycles]
/// 0, 9 (6.9%) /// 0, 9 (6.9%)
@ -27,11 +21,6 @@
/// 2, 1 (0.8%) /// 2, 1 (0.8%)
/// 4, 3 (2.3%) /// 4, 3 (2.3%)
/// ///
/// Scheduler's queue usage:
/// JALU01, 0/20
/// JFPU01, 18/18
/// JLSAGU, 0/12
///
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_BACKENDSTATISTICS_H #ifndef LLVM_TOOLS_LLVM_MCA_BACKENDSTATISTICS_H
@ -49,43 +38,21 @@ class BackendStatistics : public View {
using Histogram = llvm::DenseMap<unsigned, unsigned>; using Histogram = llvm::DenseMap<unsigned, unsigned>;
Histogram RetiredPerCycle; Histogram RetiredPerCycle;
Histogram IssuedPerCycle;
unsigned NumIssued;
unsigned NumRetired; unsigned NumRetired;
unsigned NumCycles; unsigned NumCycles;
// Tracks the usage of a scheduler's queue.
struct BufferUsage {
unsigned SlotsInUse;
unsigned MaxUsedSlots;
};
// There is a map entry for each buffered resource in the scheduling model.
// Every time a buffer is consumed/freed, this view updates the corresponding
// entry.
llvm::DenseMap<unsigned, BufferUsage> BufferedResources;
void updateHistograms() { void updateHistograms() {
IssuedPerCycle[NumIssued]++;
RetiredPerCycle[NumRetired]++; RetiredPerCycle[NumRetired]++;
NumIssued = 0;
NumRetired = 0; NumRetired = 0;
} }
void printRetireUnitStatistics(llvm::raw_ostream &OS) const;
void printSchedulerStatistics(llvm::raw_ostream &OS) const;
void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram, void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram,
unsigned Cycles) const; unsigned Cycles) const;
void printIssuePerCycle(const Histogram &IssuePerCycle,
unsigned TotalCycles) const;
void printSchedulerUsage(llvm::raw_ostream &OS,
const llvm::MCSchedModel &SM) const;
public: public:
BackendStatistics(const llvm::MCSubtargetInfo &sti) BackendStatistics(const llvm::MCSubtargetInfo &sti)
: STI(sti), NumIssued(0), NumRetired(0), NumCycles(0) { } : STI(sti), NumRetired(0), NumCycles(0) {}
void onInstructionEvent(const HWInstructionEvent &Event) override; void onInstructionEvent(const HWInstructionEvent &Event) override;
@ -93,19 +60,7 @@ public:
void onCycleEnd(unsigned Cycle) override { updateHistograms(); } void onCycleEnd(unsigned Cycle) override { updateHistograms(); }
// Increases the number of used scheduler queue slots of every buffered void printView(llvm::raw_ostream &OS) const override;
// resource in the Buffers set.
void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
// Decreases by one the number of used scheduler queue slots of every
// buffered resource in the Buffers set.
void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
void printView(llvm::raw_ostream &OS) const override {
printSchedulerStatistics(OS);
printRetireUnitStatistics(OS);
printSchedulerUsage(OS, STI.getSchedModel());
}
}; };
} // namespace mca } // namespace mca

View File

@ -26,6 +26,7 @@ add_llvm_tool(llvm-mca
RegisterFileStatistics.cpp RegisterFileStatistics.cpp
ResourcePressureView.cpp ResourcePressureView.cpp
Scheduler.cpp Scheduler.cpp
SchedulerStatistics.cpp
Support.cpp Support.cpp
SummaryView.cpp SummaryView.cpp
TimelineView.cpp TimelineView.cpp

View File

@ -0,0 +1,92 @@
//===--------------------- SchedulerStatistics.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 SchedulerStatistics interface.
///
//===----------------------------------------------------------------------===//
#include "SchedulerStatistics.h"
#include "llvm/Support/Format.h"
using namespace llvm;
namespace mca {
void SchedulerStatistics::onInstructionEvent(const HWInstructionEvent &Event) {
if (Event.Type == HWInstructionEvent::Issued)
++NumIssued;
}
void SchedulerStatistics::onReservedBuffers(ArrayRef<unsigned> Buffers) {
for (const unsigned Buffer : Buffers) {
if (BufferedResources.find(Buffer) != BufferedResources.end()) {
BufferUsage &BU = BufferedResources[Buffer];
BU.SlotsInUse++;
BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);
continue;
}
BufferedResources.insert(
std::pair<unsigned, BufferUsage>(Buffer, {1U, 1U}));
}
}
void SchedulerStatistics::onReleasedBuffers(ArrayRef<unsigned> Buffers) {
for (const unsigned Buffer : Buffers) {
assert(BufferedResources.find(Buffer) != BufferedResources.end() &&
"Buffered resource not in map?");
BufferUsage &BU = BufferedResources[Buffer];
BU.SlotsInUse--;
}
}
void SchedulerStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const {
std::string Buffer;
raw_string_ostream TempStream(Buffer);
TempStream << "\n\nSchedulers - number of cycles where we saw N instructions "
"issued:\n";
TempStream << "[# issued], [# cycles]\n";
for (const std::pair<unsigned, unsigned> &Entry : IssuedPerCycle) {
TempStream << " " << Entry.first << ", " << Entry.second << " ("
<< format("%.1f", ((double)Entry.second / NumCycles) * 100)
<< "%)\n";
}
TempStream.flush();
OS << Buffer;
}
void SchedulerStatistics::printSchedulerUsage(raw_ostream &OS,
const MCSchedModel &SM) const {
std::string Buffer;
raw_string_ostream TempStream(Buffer);
TempStream << "\n\nScheduler's queue usage:\n";
// Early exit if no buffered resources were consumed.
if (BufferedResources.empty()) {
TempStream << "No scheduler resources used.\n";
TempStream.flush();
OS << Buffer;
return;
}
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
if (ProcResource.BufferSize <= 0)
continue;
const BufferUsage &BU = BufferedResources.lookup(I);
TempStream << ProcResource.Name << ", " << BU.MaxUsedSlots << '/'
<< ProcResource.BufferSize << '\n';
}
TempStream.flush();
OS << Buffer;
}
} // namespace mca

View File

@ -0,0 +1,95 @@
//===--------------------- SchedulerStatistics.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 file defines class SchedulerStatistics. Class SchedulerStatistics is a
/// View that listens to instruction issue events in order to print general
/// statistics related to the hardware schedulers.
///
/// Example:
/// ========
///
/// Schedulers - number of cycles where we saw N instructions issued:
/// [# issued], [# cycles]
/// 0, 7 (5.4%)
/// 1, 4 (3.1%)
/// 2, 8 (6.2%)
///
/// Scheduler's queue usage:
/// JALU01, 0/20
/// JFPU01, 18/18
/// JLSAGU, 0/12
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
#define LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
#include "View.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCSubtargetInfo.h"
namespace mca {
class SchedulerStatistics : public View {
const llvm::MCSubtargetInfo &STI;
using Histogram = llvm::DenseMap<unsigned, unsigned>;
Histogram IssuedPerCycle;
unsigned NumIssued;
unsigned NumCycles;
// Tracks the usage of a scheduler's queue.
struct BufferUsage {
unsigned SlotsInUse;
unsigned MaxUsedSlots;
};
llvm::DenseMap<unsigned, BufferUsage> BufferedResources;
void updateHistograms() {
IssuedPerCycle[NumIssued]++;
NumIssued = 0;
}
void printSchedulerStatistics(llvm::raw_ostream &OS) const;
void printIssuePerCycle(const Histogram &IssuePerCycle,
unsigned TotalCycles) const;
void printSchedulerUsage(llvm::raw_ostream &OS,
const llvm::MCSchedModel &SM) const;
public:
SchedulerStatistics(const llvm::MCSubtargetInfo &sti)
: STI(sti), NumIssued(0), NumCycles(0) { }
void onInstructionEvent(const HWInstructionEvent &Event) override;
void onCycleBegin(unsigned Cycle) override { NumCycles++; }
void onCycleEnd(unsigned Cycle) override { updateHistograms(); }
// Increases the number of used scheduler queue slots of every buffered
// resource in the Buffers set.
void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
// Decreases by one the number of used scheduler queue slots of every
// buffered resource in the Buffers set.
void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
void printView(llvm::raw_ostream &OS) const override {
printSchedulerStatistics(OS);
printSchedulerUsage(OS, STI.getSchedModel());
}
};
} // namespace mca
#endif

View File

@ -29,6 +29,7 @@
#include "InstructionTables.h" #include "InstructionTables.h"
#include "RegisterFileStatistics.h" #include "RegisterFileStatistics.h"
#include "ResourcePressureView.h" #include "ResourcePressureView.h"
#include "SchedulerStatistics.h"
#include "SummaryView.h" #include "SummaryView.h"
#include "TimelineView.h" #include "TimelineView.h"
#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmInfo.h"
@ -99,6 +100,11 @@ static cl::opt<bool>
cl::desc("Print dispatch statistics"), cl::desc("Print dispatch statistics"),
cl::init(false)); cl::init(false));
static cl::opt<bool>
PrintiSchedulerStats("scheduler-stats",
cl::desc("Print scheduler statistics"),
cl::init(false));
static cl::opt<bool> static cl::opt<bool>
PrintResourcePressureView("resource-pressure", PrintResourcePressureView("resource-pressure",
cl::desc("Print the resource pressure view"), cl::desc("Print the resource pressure view"),
@ -432,6 +438,9 @@ int main(int argc, char **argv) {
if (PrintDispatchStats) if (PrintDispatchStats)
Printer.addView(llvm::make_unique<mca::DispatchStatistics>(*STI)); Printer.addView(llvm::make_unique<mca::DispatchStatistics>(*STI));
if (PrintiSchedulerStats)
Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI));
if (PrintModeVerbose) if (PrintModeVerbose)
Printer.addView(llvm::make_unique<mca::BackendStatistics>(*STI)); Printer.addView(llvm::make_unique<mca::BackendStatistics>(*STI));