forked from OSchip/llvm-project
[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:
parent
d928201ac5
commit
1cc29c045e
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue