[llvm] [llvm-exegesis] Add raw PMU encoding in TargetPfmCounters tablegen (PR #201228)

Maxim Potapchik via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 18:49:30 PDT 2026


https://github.com/MaximPotapchik updated https://github.com/llvm/llvm-project/pull/201228

>From cbdded6272bcc87e3380147a46d8b8c312fe369a 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, UMask, and HasRawEncoding fields to PfmCounter
in TargetPfmCounters.td. When HasRawEncoding is set, ExegesisEmitter outputs
raw hex integer 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.

No runtime behavior changes in this patch. PerfHelper wiring is a follow-up.

Towards #187930
---
 llvm/include/llvm/Target/TargetPfmCounters.td |  6 ++++
 llvm/test/TableGen/ExegesisRawPfmCounters.td  | 29 +++++++++++++++++++
 llvm/utils/TableGen/ExegesisEmitter.cpp       | 24 +++++++++++----
 3 files changed, 53 insertions(+), 6 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..030a877150f4d 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -16,6 +16,12 @@ 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 = 0;
+  int UMask = 0;
+  bit HasRawEncoding = 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..23e9721444fa3
--- /dev/null
+++ b/llvm/test/TableGen/ExegesisRawPfmCounters.td
@@ -0,0 +1,29 @@
+// RUN: llvm-tblgen --gen-exegesis -I %p/../../include %s | FileCheck %s
+// CHECK: 0x003c, 0x00,
+// CHECK: 0x00c2, 0x01,
+// CHECK: nullptr,
+
+include "llvm/Target/TargetPfmCounters.td"
+
+// Fake target for ExegesisEmitter
+class Target {}
+def TestTarget : Target {}
+
+def TestRawCycleCounter : PfmCounter<"testCycles"> {
+  let EventSelect = 0x003c;
+  let UMask = 0x00;
+  let HasRawEncoding = 1;
+}
+
+def TestRawUopsCounter : PfmCounter<"testUops"> {
+  let EventSelect = 0x00c2;
+  let UMask = 0x01;
+  let HasRawEncoding = 1;
+}
+
+def TestPfmCounters : ProcPfmCounters {
+  let CycleCounter = TestRawCycleCounter;
+  let UopsCounter = TestRawUopsCounter;
+}
+
+def : PfmCountersDefaultBinding<TestPfmCounters>;
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index bd69919bb462e..6cef7e7d15e46 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -13,11 +13,13 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.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 +124,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,14 +160,24 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
      << " = {\n";
 
   // Cycle Counter.
-  if (CycleCounter.empty())
+  if (CycleCounterDef->getValueAsBit("HasRawEncoding")) {
+    const int64_t EventSelect = CycleCounterDef->getValueAsInt("EventSelect");
+    const int64_t UMask = CycleCounterDef->getValueAsInt("UMask");
+    OS << "  0x" << llvm::format_hex_no_prefix(EventSelect, 4) << ", 0x"
+       << llvm::format_hex_no_prefix(UMask, 2) << ", // Raw Cycle Counter\n";
+  } else if (CycleCounter.empty())
     OS << "  nullptr,  // No cycle counter.\n";
   else
     OS << "  " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
        << "],  // Cycle counter\n";
 
   // Uops Counter.
-  if (UopsCounter.empty())
+  if (UopsCounterDef->getValueAsBit("HasRawEncoding")) {
+    const int64_t EventSelect = UopsCounterDef->getValueAsInt("EventSelect");
+    const int64_t UMask = UopsCounterDef->getValueAsInt("UMask");
+    OS << "  0x" << llvm::format_hex_no_prefix(EventSelect, 4) << ", 0x"
+       << llvm::format_hex_no_prefix(UMask, 2) << ", // Raw Uops Counter\n";
+  } else if (UopsCounter.empty())
     OS << "  nullptr,  // No uops counter.\n";
   else
     OS << "  " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)



More information about the llvm-commits mailing list