Index: llvm/trunk/include/llvm/MC/MCSchedule.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSchedule.h +++ llvm/trunk/include/llvm/MC/MCSchedule.h @@ -182,6 +182,10 @@ // 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. Index: llvm/trunk/include/llvm/Target/TargetSchedule.td =================================================================== --- llvm/trunk/include/llvm/Target/TargetSchedule.td +++ llvm/trunk/include/llvm/Target/TargetSchedule.td @@ -550,3 +550,10 @@ // The list of counters that measure issue events. list Counters = counters; } + +// Each processor can define how to measure NumMicroOps by defining a +// PfmUopsCounter. +class PfmUopsCounter : PfmCounter { + string Counter = counter; +} + Index: llvm/trunk/lib/Target/X86/X86PfmCounters.td =================================================================== --- llvm/trunk/lib/Target/X86/X86PfmCounters.td +++ llvm/trunk/lib/Target/X86/X86PfmCounters.td @@ -32,6 +32,7 @@ def HWPort5Counter : PfmIssueCounter; def HWPort6Counter : PfmIssueCounter; def HWPort7Counter : PfmIssueCounter; +def HWUopsCounter : PfmUopsCounter<"uops_issued:any">; } let SchedModel = BroadwellModel in { Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h @@ -41,6 +41,10 @@ }; 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 @@ // 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; }; Index: llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp @@ -130,8 +130,7 @@ if (Value < MinLatency) MinLatency = Value; } - return {{"latency", static_cast(MinLatency), - static_cast(MinLatency), ""}}; + return {BenchmarkMeasure::Create("latency", MinLatency)}; } } // namespace exegesis Index: llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp @@ -255,23 +255,18 @@ ScratchSpace &Scratch) const { const auto &SchedModel = State.getSubtargetInfo().getSchedModel(); - std::vector 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 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 @@ Counter.stop(); CounterValue += Counter.read(); } - Result.push_back({llvm::itostr(ProcResIdx), - static_cast(CounterValue), - static_cast(CounterValue), - SchedModel.getProcResource(ProcResIdx)->Name}); + return CounterValue; + }; + + std::vector 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; } Index: llvm/trunk/utils/TableGen/CodeGenSchedule.h =================================================================== --- llvm/trunk/utils/TableGen/CodeGenSchedule.h +++ llvm/trunk/utils/TableGen/CodeGenSchedule.h @@ -242,6 +242,7 @@ // 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 @@ bool hasExtraProcessorInfo() const { return RetireControlUnit || !RegisterFiles.empty() || !PfmIssueCounterDefs.empty() || - PfmCycleCounterDef != nullptr; + PfmCycleCounterDef != nullptr || + PfmUopsCounterDef != nullptr; } unsigned getProcResourceIdx(Record *PRDef) const; Index: llvm/trunk/utils/TableGen/CodeGenSchedule.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeGenSchedule.cpp +++ llvm/trunk/utils/TableGen/CodeGenSchedule.cpp @@ -1787,6 +1787,15 @@ } 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. Index: llvm/trunk/utils/TableGen/SubtargetEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/SubtargetEmitter.cpp +++ llvm/trunk/utils/TableGen/SubtargetEmitter.cpp @@ -743,6 +743,13 @@ 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";