[llvm-exegesis] Add support for measuring NumMicroOps.

Summary:
Example output for vzeroall:

---
mode:            uops
key:
  instructions:
    - 'VZEROALL'
  config:          ''
  register_initial_values:
cpu_name:        haswell
llvm_triple:     x86_64-unknown-linux-gnu
num_repetitions: 10000
measurements:
  - { debug_string: HWPort0, value: 0.0006, per_snippet_value: 0.0006,
      key: '3' }
  - { debug_string: HWPort1, value: 0.0011, per_snippet_value: 0.0011,
      key: '4' }
  - { debug_string: HWPort2, value: 0.0004, per_snippet_value: 0.0004,
      key: '5' }
  - { debug_string: HWPort3, value: 0.0018, per_snippet_value: 0.0018,
      key: '6' }
  - { debug_string: HWPort4, value: 0.0002, per_snippet_value: 0.0002,
      key: '7' }
  - { debug_string: HWPort5, value: 1.0019, per_snippet_value: 1.0019,
      key: '8' }
  - { debug_string: HWPort6, value: 1.0033, per_snippet_value: 1.0033,
      key: '9' }
  - { debug_string: HWPort7, value: 0.0001, per_snippet_value: 0.0001,
      key: '10' }
  - { debug_string: NumMicroOps, value: 20.0069, per_snippet_value: 20.0069,
      key: NumMicroOps }
error:           ''
info:            ''
assembled_snippet: C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C5FC77C3
...

Reviewers: gchatelet

Subscribers: tschuett, RKSimon, andreadb, llvm-commits

Differential Revision: https://reviews.llvm.org/D52539

llvm-svn: 343094
This commit is contained in:
Clement Courbet 2018-09-26 11:22:56 +00:00
parent 5beaac433d
commit 596c56ff9c
9 changed files with 59 additions and 16 deletions

View File

@ -182,6 +182,10 @@ struct MCExtraProcessorInfo {
// cycles.
const char *CycleCounter;
// An optional name of a performance counter that can be used to measure
// uops.
const char *UopsCounter;
// For each MCProcResourceDesc defined by the processor, an optional list of
// names of performance counters that can be used to measure the resource
// utilization.

View File

@ -550,3 +550,10 @@ class PfmIssueCounter<ProcResourceUnits resource, list<string> counters>
// The list of counters that measure issue events.
list<string> Counters = counters;
}
// Each processor can define how to measure NumMicroOps by defining a
// PfmUopsCounter.
class PfmUopsCounter<string counter> : PfmCounter {
string Counter = counter;
}

View File

@ -32,6 +32,7 @@ def HWPort4Counter : PfmIssueCounter<HWPort4, ["uops_dispatched_port:port_4"]>;
def HWPort5Counter : PfmIssueCounter<HWPort5, ["uops_dispatched_port:port_5"]>;
def HWPort6Counter : PfmIssueCounter<HWPort6, ["uops_dispatched_port:port_6"]>;
def HWPort7Counter : PfmIssueCounter<HWPort7, ["uops_dispatched_port:port_7"]>;
def HWUopsCounter : PfmUopsCounter<"uops_issued:any">;
}
let SchedModel = BroadwellModel in {

View File

@ -41,6 +41,10 @@ struct InstructionBenchmarkKey {
};
struct BenchmarkMeasure {
// A helper to create an unscaled BenchmarkMeasure.
static BenchmarkMeasure Create(std::string Key, double Value) {
return {Key, Value, Value, Key};
}
std::string Key;
// This is the per-instruction value, i.e. measured quantity scaled per
// instruction.
@ -48,6 +52,7 @@ struct BenchmarkMeasure {
// This is the per-snippet value, i.e. measured quantity for one repetition of
// the whole snippet.
double PerSnippetValue;
// FIXME: remove, use `Key` instead.
std::string DebugString;
};

View File

@ -130,8 +130,7 @@ LatencyBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
if (Value < MinLatency)
MinLatency = Value;
}
return {{"latency", static_cast<double>(MinLatency),
static_cast<double>(MinLatency), ""}};
return {BenchmarkMeasure::Create("latency", MinLatency)};
}
} // namespace exegesis

View File

@ -255,23 +255,18 @@ UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
ScratchSpace &Scratch) const {
const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
std::vector<BenchmarkMeasure> Result;
for (unsigned ProcResIdx = 1;
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
const char *const PfmCounters = SchedModel.getExtraProcessorInfo()
.PfmCounters.IssueCounters[ProcResIdx];
if (!PfmCounters)
continue;
const auto RunMeasurement = [&Function,
&Scratch](const char *const Counters) {
// We sum counts when there are several counters for a single ProcRes
// (e.g. P23 on SandyBridge).
int64_t CounterValue = 0;
llvm::SmallVector<llvm::StringRef, 2> CounterNames;
llvm::StringRef(PfmCounters).split(CounterNames, ',');
llvm::StringRef(Counters).split(CounterNames, ',');
for (const auto &CounterName : CounterNames) {
pfm::PerfEvent UopPerfEvent(CounterName);
if (!UopPerfEvent.valid())
llvm::report_fatal_error(
llvm::Twine("invalid perf event ").concat(PfmCounters));
llvm::Twine("invalid perf event ").concat(Counters));
pfm::Counter Counter(UopPerfEvent);
Scratch.clear();
Counter.start();
@ -279,10 +274,24 @@ UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
Counter.stop();
CounterValue += Counter.read();
}
Result.push_back({llvm::itostr(ProcResIdx),
static_cast<double>(CounterValue),
static_cast<double>(CounterValue),
SchedModel.getProcResource(ProcResIdx)->Name});
return CounterValue;
};
std::vector<BenchmarkMeasure> Result;
const auto& PfmCounters = SchedModel.getExtraProcessorInfo().PfmCounters;
// Uops per port.
for (unsigned ProcResIdx = 1;
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
const char *const Counters = PfmCounters.IssueCounters[ProcResIdx];
if (!Counters)
continue;
const double CounterValue = RunMeasurement(Counters);
Result.push_back(BenchmarkMeasure::Create(SchedModel.getProcResource(ProcResIdx)->Name, CounterValue));
}
// NumMicroOps.
if (const char *const UopsCounter = PfmCounters.UopsCounter) {
const double CounterValue = RunMeasurement(UopsCounter);
Result.push_back(BenchmarkMeasure::Create("NumMicroOps", CounterValue));
}
return Result;
}

View File

@ -1787,6 +1787,15 @@ void CodeGenSchedModels::collectPfmCounters() {
}
PM.PfmCycleCounterDef = Def;
}
for (Record *Def : Records.getAllDerivedDefinitions("PfmUopsCounter")) {
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
if (PM.PfmUopsCounterDef) {
PrintFatalError(Def->getLoc(),
"multiple uops counters for " +
Def->getValueAsDef("SchedModel")->getName());
}
PM.PfmUopsCounterDef = Def;
}
}
// Collect and sort WriteRes, ReadAdvance, and ProcResources.

View File

@ -242,6 +242,7 @@ struct CodeGenProcModel {
// List of PfmCounters.
RecVec PfmIssueCounterDefs;
Record *PfmCycleCounterDef = nullptr;
Record *PfmUopsCounterDef = nullptr;
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
Record *IDef) :
@ -259,7 +260,8 @@ struct CodeGenProcModel {
bool hasExtraProcessorInfo() const {
return RetireControlUnit || !RegisterFiles.empty() ||
!PfmIssueCounterDefs.empty() ||
PfmCycleCounterDef != nullptr;
PfmCycleCounterDef != nullptr ||
PfmUopsCounterDef != nullptr;
}
unsigned getProcResourceIdx(Record *PRDef) const;

View File

@ -743,6 +743,13 @@ static void EmitPfmCounters(const CodeGenProcModel &ProcModel,
else
OS << " nullptr, // No cycle counter.\n";
// Emit the uops counter.
if (ProcModel.PfmUopsCounterDef)
OS << " \"" << ProcModel.PfmUopsCounterDef->getValueAsString("Counter")
<< "\", // Uops counter.\n";
else
OS << " nullptr, // No uops counter.\n";
// Emit a reference to issue counters table.
if (HasPfmIssueCounters)
OS << " " << ProcModel.ModelName << "PfmIssueCounters\n";