[llvm] [llvm-exegesis] Add raw PMU encoding in TargetPfmCounters tablegen (PR #201228)
Maxim Potapchik via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 06:27:05 PDT 2026
https://github.com/MaximPotapchik updated https://github.com/llvm/llvm-project/pull/201228
>From dbc8e829cb3a7b191362a7019a15566abeab1d6d Mon Sep 17 00:00:00 2001
From: MaximPotapchik <maximp1012 at gmail.com>
Date: Tue, 2 Jun 2026 17:59:51 -0400
Subject: [PATCH] [llvm-exegesis] Add raw PMU encoding in TargetPfmCounters
tablegen
Adds optional EventSelect and UMask fields to PfmCounter in
TargetPfmCounters.td. EventSelect defaults to -1 (no raw encoding).
When set, ExegesisEmitter outputs raw hex values instead of a libpfm
symbolic name, allowing per-CPU .td entries to bypass
pfm_get_os_event_encoding for counters that are undocumented or
unsupported in libpfm.
Extends PfmCountersInfo with CycleCounterEventSelect, CycleCounterUMask,
UopsCounterEventSelect, and UopsCounterUMask fields. PerfHelper wiring
in a subsequent patch.
Towards #187930
---
llvm/include/llvm/Target/TargetPfmCounters.td | 5 ++
llvm/test/TableGen/ExegesisRawPfmCounters.td | 32 +++++++++++++
llvm/tools/llvm-exegesis/lib/Target.cpp | 8 +++-
llvm/tools/llvm-exegesis/lib/Target.h | 8 ++++
llvm/utils/TableGen/ExegesisEmitter.cpp | 47 +++++++++++++++----
5 files changed, 90 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/TableGen/ExegesisRawPfmCounters.td
diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td b/llvm/include/llvm/Target/TargetPfmCounters.td
index cfe432a992b71..f822636fb9a52 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -16,6 +16,11 @@ class PfmCounter<string counter> {
// The name can be "some_counter + some_other_counter", in which case the
// measured value is the sum of events on these counters.
string Counter = counter;
+ // Optional raw PMU encoding that bypasses libpfm symbolic lookup.
+ // EventSelect is an up to 16-bit event identifier.
+ // UMask is an 8-bit unit mask qualifying the event.
+ int EventSelect = -1;
+ int UMask = 0;
}
// Issue counters can be tied to a ProcResource
diff --git a/llvm/test/TableGen/ExegesisRawPfmCounters.td b/llvm/test/TableGen/ExegesisRawPfmCounters.td
new file mode 100644
index 0000000000000..60f87c7812866
--- /dev/null
+++ b/llvm/test/TableGen/ExegesisRawPfmCounters.td
@@ -0,0 +1,32 @@
+// RUN: llvm-tblgen --gen-exegesis -I %p/../../include %s | FileCheck %s
+// CHECK-LABEL: static const PfmCountersInfo TestTargetTestPfmCounters = {
+// CHECK-NEXT: nullptr, // Cycle counter uses raw encoding below.
+// CHECK-NEXT: 0x003c, 0x00, // Raw cycle counter
+// CHECK-NEXT: nullptr, // Uops counter uses raw encoding below.
+// CHECK-NEXT: 0x00c2, 0x01, // Raw uops counter
+// CHECK-NEXT: nullptr, 0, // No issue counters
+// CHECK-NEXT: nullptr, 0 // No validation counters.
+// CHECK-NEXT: };
+
+include "llvm/Target/TargetPfmCounters.td"
+
+// Fake target for ExegesisEmitter
+class Target {}
+def TestTarget : Target {}
+
+def TestRawCycleCounter : PfmCounter<"testCycles"> {
+ let EventSelect = 0x003c;
+ let UMask = 0x00;
+}
+
+def TestRawUopsCounter : PfmCounter<"testUops"> {
+ let EventSelect = 0x00c2;
+ let UMask = 0x01;
+}
+
+def TestPfmCounters : ProcPfmCounters {
+ let CycleCounter = TestRawCycleCounter;
+ let UopsCounter = TestRawUopsCounter;
+}
+
+def : PfmCountersDefaultBinding<TestPfmCounters>;
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 2ad6c5af4de4d..9dc58dafbef7a 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -179,11 +179,15 @@ std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
static_assert(std::is_trivial_v<PfmCountersInfo>,
"We shouldn't have dynamic initialization here");
-const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
- 0u, nullptr, 0u};
+const PfmCountersInfo PfmCountersInfo::Default = {
+ nullptr, -1, 0, nullptr, -1, 0, nullptr, 0u, nullptr, 0u};
const PfmCountersInfo PfmCountersInfo::Dummy = {
pfm::PerfEvent::DummyEventString,
+ -1,
+ 0,
pfm::PerfEvent::DummyEventString,
+ -1,
+ 0,
nullptr,
0u,
nullptr,
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 77fbaa6e95412..1d01b0558f75c 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -45,10 +45,18 @@ struct PfmCountersInfo {
// cycles.
const char *CycleCounter;
+ // Optional raw PMU encoding for Cycle counter.
+ int CycleCounterEventSelect;
+ int CycleCounterUMask;
+
// An optional name of a performance counter that can be used to measure
// uops.
const char *UopsCounter;
+ // Optional raw PMU encoding for Uops counter.
+ int UopsCounterEventSelect;
+ int UopsCounterUMask;
+
// An IssueCounter specifies how to measure uops issued to specific proc
// resources.
struct IssueCounter {
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index bd69919bb462e..8aaecb9c1cdbd 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -13,11 +13,14 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
+#include <cstdint>
#include <map>
#include <string>
#include <vector>
@@ -122,10 +125,10 @@ static bool EventNumberLess(const ValidationCounterInfo &LHS,
void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
unsigned &IssueCountersTableOffset,
raw_ostream &OS) const {
- const auto CycleCounter =
- Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
- const auto UopsCounter =
- Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
+ const Record *CycleCounterDef = Def.getValueAsDef("CycleCounter");
+ const auto CycleCounter = CycleCounterDef->getValueAsString("Counter");
+ const Record *UopsCounterDef = Def.getValueAsDef("UopsCounter");
+ const auto UopsCounter = UopsCounterDef->getValueAsString("Counter");
const size_t NumIssueCounters =
Def.getValueAsListOfDefs("IssueCounters").size();
const size_t NumValidationCounters =
@@ -158,18 +161,46 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
<< " = {\n";
// Cycle Counter.
- if (CycleCounter.empty())
+ if (CycleCounterDef->getValueAsInt("EventSelect") != -1) {
+ const int64_t EventSelect = CycleCounterDef->getValueAsInt("EventSelect");
+ if (!isInt<16>(EventSelect))
+ PrintFatalError(CycleCounterDef->getLoc(),
+ "EventSelect must fit in 16 bits");
+ const int64_t UMask = CycleCounterDef->getValueAsInt("UMask");
+ if (!isInt<8>(UMask))
+ PrintFatalError(CycleCounterDef->getLoc(), "UMask must fit in 8 bits");
+ OS << " nullptr, // Cycle counter uses raw encoding below.\n";
+ OS << " 0x" << format_hex_no_prefix(EventSelect, 4) << ", 0x"
+ << format_hex_no_prefix(UMask, 2) << ", // Raw cycle counter\n";
+ } else if (CycleCounter.empty()) {
OS << " nullptr, // No cycle counter.\n";
- else
+ OS << " -1, 0, // No raw cycle counter\n";
+ } else {
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
<< "], // Cycle counter\n";
+ OS << " -1, 0, // No raw cycle counter\n";
+ }
// Uops Counter.
- if (UopsCounter.empty())
+ if (UopsCounterDef->getValueAsInt("EventSelect") != -1) {
+ const int64_t EventSelect = UopsCounterDef->getValueAsInt("EventSelect");
+ if (!isInt<16>(EventSelect))
+ PrintFatalError(UopsCounterDef->getLoc(),
+ "EventSelect must fit in 16 bits");
+ const int64_t UMask = UopsCounterDef->getValueAsInt("UMask");
+ if (!isInt<8>(UMask))
+ PrintFatalError(UopsCounterDef->getLoc(), "UMask must fit in 8 bits");
+ OS << " nullptr, // Uops counter uses raw encoding below.\n";
+ OS << " 0x" << format_hex_no_prefix(EventSelect, 4) << ", 0x"
+ << format_hex_no_prefix(UMask, 2) << ", // Raw uops counter\n";
+ } else if (UopsCounter.empty()) {
OS << " nullptr, // No uops counter.\n";
- else
+ OS << " -1, 0, // No raw uops counter\n";
+ } else {
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
<< "], // Uops counter\n";
+ OS << " -1, 0, // No raw uops counter\n";
+ }
// Issue Counters
if (NumIssueCounters == 0)
More information about the llvm-commits
mailing list