[clang] [llvm] [clang-tools-extra] [llvm-exegesis] Add tablegen support for validation counters (PR #76652)

Aiden Grossman via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 10 14:34:53 PST 2024


https://github.com/boomanaiden154 updated https://github.com/llvm/llvm-project/pull/76652

>From 0196a8780f2d3a378f0fd3b86a6e6b6590ca02de Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Sat, 30 Dec 2023 15:37:56 -0800
Subject: [PATCH 1/5] [llvm-exegesis] Remove unused Counter::read method

This method was simply a wrapper around readOrError. All users within
the llvm-exegesis code base should have been processing an actual error
rather than using the wrapper. This patch removes the wrapper and
rewrites the users (just 1) to use the readOrError method.
---
 llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp |  6 +++++-
 llvm/tools/llvm-exegesis/lib/PerfHelper.cpp      | 13 -------------
 llvm/tools/llvm-exegesis/lib/PerfHelper.h        |  3 ---
 3 files changed, 5 insertions(+), 17 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 1ee59a86ebbdcf..c57fce970b2139 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -356,7 +356,11 @@ class SubProcessFunctionExecutorImpl
       if (ChildExitCode == 0) {
         // The child exited succesfully, read counter values and return
         // success
-        CounterValues[0] = Counter->read();
+        auto CounterValueOrErr = Counter->readOrError();
+        if (!CounterValueOrErr)
+          return CounterValueOrErr.takeError();
+        CounterValues.swap(*CounterValueOrErr);
+
         return Error::success();
       }
       // The child exited, but not successfully
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
index 3ff1745e9e0629..314de1ec32366f 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
@@ -148,17 +148,6 @@ void Counter::stop() {
     ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0);
 }
 
-int64_t Counter::read() const {
-  auto ValueOrError = readOrError();
-  if (ValueOrError) {
-    if (!ValueOrError.get().empty())
-      return ValueOrError.get()[0];
-    errs() << "Counter has no reading\n";
-  } else
-    errs() << ValueOrError.takeError() << "\n";
-  return -1;
-}
-
 llvm::Expected<llvm::SmallVector<int64_t, 4>>
 Counter::readOrError(StringRef /*unused*/) const {
   int64_t Count = 0;
@@ -187,8 +176,6 @@ void Counter::start() {}
 
 void Counter::stop() {}
 
-int64_t Counter::read() const { return 42; }
-
 llvm::Expected<llvm::SmallVector<int64_t, 4>>
 Counter::readOrError(StringRef /*unused*/) const {
   if (IsDummyEvent) {
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
index a50974f0a67be9..894aac1f197ed1 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
@@ -95,9 +95,6 @@ class Counter {
   /// Stops the measurement of the event.
   void stop();
 
-  /// Returns the current value of the counter or -1 if it cannot be read.
-  int64_t read() const;
-
   /// Returns the current value of the counter or error if it cannot be read.
   /// FunctionBytes: The benchmark function being executed.
   /// This is used to filter out the measurements to ensure they are only

>From 75261b9626878b92fa4bde2b4801815251238748 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Sat, 30 Dec 2023 17:03:59 -0800
Subject: [PATCH 2/5] [llvm-exegesis] Add tablegen support for validation
 counters

---
 llvm/include/llvm/Target/TargetPfmCounters.td | 19 +++++++++++++
 llvm/lib/Target/X86/X86PfmCounters.td         |  6 ++++
 llvm/tools/llvm-exegesis/lib/Target.cpp       | 13 +++++----
 llvm/tools/llvm-exegesis/lib/Target.h         | 11 ++++++++
 llvm/utils/TableGen/ExegesisEmitter.cpp       | 28 +++++++++++++++++--
 5 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td b/llvm/include/llvm/Target/TargetPfmCounters.td
index b00f3e19c35f90..72f6b39f4878f4 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -28,6 +28,22 @@ class PfmIssueCounter<string resource_name, string counter>
   string ResourceName = resource_name;
 }
 
+class ValidationEvent <int event_number> {
+  int EventNumber = event_number;
+}
+
+def L1DCacheLoadMiss    : ValidationEvent<0>;
+def InstructionRetired  : ValidationEvent<1>;
+def DataTLBLoadMiss     : ValidationEvent<2>;
+def DataTLBStoreMiss    : ValidationEvent<3>;
+
+// Validation counters can be tied to a specific event
+class PfmValidationCounter<ValidationEvent event_type, string counter>
+    : PfmCounter<counter> {
+  // The name of the event that the validation counter detects.
+  ValidationEvent EventType = event_type;
+}
+
 def NoPfmCounter : PfmCounter <""> {}
 
 // Set of PfmCounters for measuring sched model characteristics.
@@ -38,6 +54,9 @@ class ProcPfmCounters {
   PfmCounter UopsCounter = NoPfmCounter;
   // Processors can define how to measure issued uops by defining IssueCounters.
   list<PfmIssueCounter> IssueCounters = [];
+  // Processor can list mappings between validation events and real counters
+  // to measure the specified events.
+  list<PfmValidationCounter> ValidationCounters = [];
 }
 
 // A binding of a set of counters to a CPU.
diff --git a/llvm/lib/Target/X86/X86PfmCounters.td b/llvm/lib/Target/X86/X86PfmCounters.td
index 49ef6efc6aecf2..99cac504f157d3 100644
--- a/llvm/lib/Target/X86/X86PfmCounters.td
+++ b/llvm/lib/Target/X86/X86PfmCounters.td
@@ -275,6 +275,9 @@ def ZnVer2PfmCounters : ProcPfmCounters {
     PfmIssueCounter<"Zn2AGU", "ls_dispatch:ld_st_dispatch + ls_dispatch:ld_dispatch + ls_dispatch:store_dispatch">,
     PfmIssueCounter<"Zn2Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+    PfmValidationCounter<InstructionRetired, "RETIRED_INSTRUCTIONS">
+  ];
 }
 def : PfmCountersBinding<"znver2", ZnVer2PfmCounters>;
 
@@ -288,6 +291,9 @@ def ZnVer3PfmCounters : ProcPfmCounters {
     PfmIssueCounter<"Zn3Store", "ls_dispatch:store_dispatch">,
     PfmIssueCounter<"Zn3Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+    PfmValidationCounter<InstructionRetired, "RETIRED_INSTRUCTIONS">
+  ];
 }
 def : PfmCountersBinding<"znver3", ZnVer3PfmCounters>;
 
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 23c80e5b98953a..20b4afb9b8f676 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -147,13 +147,14 @@ std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
                                                ExecutionMode);
 }
 
-static_assert(std::is_trivial_v<PfmCountersInfo>,
-              "We shouldn't have dynamic initialization here");
-const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
-                                                  0u};
+const PfmCountersInfo PfmCountersInfo::Default = {
+    nullptr, nullptr, nullptr, 0u, {}};
 const PfmCountersInfo PfmCountersInfo::Dummy = {
-    pfm::PerfEvent::DummyEventString, pfm::PerfEvent::DummyEventString, nullptr,
-    0u};
+    pfm::PerfEvent::DummyEventString,
+    pfm::PerfEvent::DummyEventString,
+    nullptr,
+    0u,
+    {}};
 
 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
   assert(llvm::is_sorted(
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index c37dd8b7082162..3956bc983181f6 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -32,6 +32,8 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
+#include <unordered_map>
+
 namespace llvm {
 namespace exegesis {
 
@@ -39,6 +41,13 @@ extern cl::OptionCategory Options;
 extern cl::OptionCategory BenchmarkOptions;
 extern cl::OptionCategory AnalysisOptions;
 
+enum ValidationEvent {
+  L1DCacheLoadMiss,
+  InstructionRetired,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss
+};
+
 struct PfmCountersInfo {
   // An optional name of a performance counter that can be used to measure
   // cycles.
@@ -59,6 +68,8 @@ struct PfmCountersInfo {
   const IssueCounter *IssueCounters;
   unsigned NumIssueCounters;
 
+  std::unordered_map<ValidationEvent, const char *> ValidationCounters;
+
   static const PfmCountersInfo Default;
   static const PfmCountersInfo Dummy;
 };
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index 736f1220be14dd..247ed83f25ea64 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -22,6 +22,8 @@
 #include <string>
 #include <vector>
 
+#include <iostream>
+
 using namespace llvm;
 
 #define DEBUG_TYPE "exegesis-emitter"
@@ -81,6 +83,11 @@ collectPfmCounters(const RecordKeeper &Records) {
                         "duplicate ResourceName " + ResourceName);
       AddPfmCounterName(IssueCounter);
     }
+
+    for (const Record *ValidationCounter :
+         Def->getValueAsListOfDefs("ValidationCounters"))
+      AddPfmCounterName(ValidationCounter);
+
     AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
     AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
   }
@@ -109,6 +116,8 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
       Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
   const size_t NumIssueCounters =
       Def.getValueAsListOfDefs("IssueCounters").size();
+  const size_t NumValidationCounters =
+      Def.getValueAsListOfDefs("ValidationCounters").size();
 
   OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
      << " = {\n";
@@ -129,10 +138,25 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
 
   // Issue Counters
   if (NumIssueCounters == 0)
-    OS << "  nullptr,  // No issue counters.\n  0\n";
+    OS << "  nullptr, 0, // No issue counters\n";
   else
     OS << "  " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
-       << ", " << NumIssueCounters << " // Issue counters.\n";
+       << ", " << NumIssueCounters << ", // Issue counters.\n";
+
+  // Validation Counters
+  if (NumValidationCounters == 0)
+    OS << "  {} // No validation counters.\n";
+  else {
+    OS << "  {\n";
+    for (const Record *ValidationCounter :
+         Def.getValueAsListOfDefs("ValidationCounters")) {
+      OS << "    { " << ValidationCounter->getValueAsDef("EventType")->getName()
+         << ", " << Target << "PfmCounterNames["
+         << getPfmCounterId(ValidationCounter->getValueAsString("Counter"))
+         << "]}\n";
+    }
+    OS << "  } // Validation counters.\n";
+  }
 
   OS << "};\n";
   IssueCountersTableOffset += NumIssueCounters;

>From 832d75cc4e8dabc4a5eeccf45ca51dee2d92ab15 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Tue, 2 Jan 2024 22:28:26 -0800
Subject: [PATCH 3/5] Add comma to end of validation counters to support
 multiple

---
 llvm/utils/TableGen/ExegesisEmitter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index 247ed83f25ea64..6c1f7af5fd5724 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -153,7 +153,7 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
       OS << "    { " << ValidationCounter->getValueAsDef("EventType")->getName()
          << ", " << Target << "PfmCounterNames["
          << getPfmCounterId(ValidationCounter->getValueAsString("Counter"))
-         << "]}\n";
+         << "]},\n";
     }
     OS << "  } // Validation counters.\n";
   }

>From 1841c85d87df01fa2686d406265bc81b766f85a8 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Fri, 5 Jan 2024 18:53:46 -0800
Subject: [PATCH 4/5] Switch to using static array

---
 llvm/tools/llvm-exegesis/lib/Target.cpp | 10 +++--
 llvm/tools/llvm-exegesis/lib/Target.h   |  5 +--
 llvm/utils/TableGen/ExegesisEmitter.cpp | 52 ++++++++++++++++++-------
 3 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 20b4afb9b8f676..fe1eded63dc51a 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -147,14 +147,18 @@ std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
                                                ExecutionMode);
 }
 
-const PfmCountersInfo PfmCountersInfo::Default = {
-    nullptr, nullptr, nullptr, 0u, {}};
+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::Dummy = {
     pfm::PerfEvent::DummyEventString,
     pfm::PerfEvent::DummyEventString,
     nullptr,
     0u,
-    {}};
+    nullptr,
+    0u};
 
 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
   assert(llvm::is_sorted(
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 3956bc983181f6..8da748f51dc952 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -32,8 +32,6 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
-#include <unordered_map>
-
 namespace llvm {
 namespace exegesis {
 
@@ -68,7 +66,8 @@ struct PfmCountersInfo {
   const IssueCounter *IssueCounters;
   unsigned NumIssueCounters;
 
-  std::unordered_map<ValidationEvent, const char *> ValidationCounters;
+  const std::pair<ValidationEvent, const char *> *ValidationEvents;
+  unsigned NumValidationCounters;
 
   static const PfmCountersInfo Default;
   static const PfmCountersInfo Dummy;
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index 6c1f7af5fd5724..111aa449ae4f3a 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -22,8 +22,6 @@
 #include <string>
 #include <vector>
 
-#include <iostream>
-
 using namespace llvm;
 
 #define DEBUG_TYPE "exegesis-emitter"
@@ -107,6 +105,17 @@ ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
   Target = std::string(Targets[0]->getName());
 }
 
+struct ValidationCounterInfo {
+  int64_t EventNumber;
+  StringRef EventName;
+  unsigned PfmCounterID;
+};
+
+bool CompareValidationCounterInfo(ValidationCounterInfo &LHS,
+                                  ValidationCounterInfo &RHS) {
+  return LHS.EventNumber < RHS.EventNumber;
+}
+
 void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
                                           unsigned &IssueCountersTableOffset,
                                           raw_ostream &OS) const {
@@ -119,6 +128,29 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
   const size_t NumValidationCounters =
       Def.getValueAsListOfDefs("ValidationCounters").size();
 
+  // Emit Validation Counters Array
+  if (NumValidationCounters != 0) {
+    std::vector<ValidationCounterInfo> ValidationCounters;
+    ValidationCounters.reserve(NumValidationCounters);
+    for (const Record *ValidationCounter :
+         Def.getValueAsListOfDefs("ValidationCounters")) {
+      ValidationCounters.push_back(
+          {ValidationCounter->getValueAsDef("EventType")
+               ->getValueAsInt("EventNumber"),
+           ValidationCounter->getValueAsDef("EventType")->getName(),
+           getPfmCounterId(ValidationCounter->getValueAsString("Counter"))});
+    }
+    std::sort(ValidationCounters.begin(), ValidationCounters.end(),
+              CompareValidationCounterInfo);
+    OS << "\nstatic const std::pair<ValidationEvent, const char*> " << Target
+       << Def.getName() << "ValidationCounters[] = {\n";
+    for (const ValidationCounterInfo &VCI : ValidationCounters) {
+      OS << "  { " << VCI.EventName << ", " << Target << "PfmCounterNames["
+         << VCI.PfmCounterID << "]},\n";
+    }
+    OS << "};\n";
+  }
+
   OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
      << " = {\n";
 
@@ -145,18 +177,10 @@ void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
 
   // Validation Counters
   if (NumValidationCounters == 0)
-    OS << "  {} // No validation counters.\n";
-  else {
-    OS << "  {\n";
-    for (const Record *ValidationCounter :
-         Def.getValueAsListOfDefs("ValidationCounters")) {
-      OS << "    { " << ValidationCounter->getValueAsDef("EventType")->getName()
-         << ", " << Target << "PfmCounterNames["
-         << getPfmCounterId(ValidationCounter->getValueAsString("Counter"))
-         << "]},\n";
-    }
-    OS << "  } // Validation counters.\n";
-  }
+    OS << "  nullptr, 0 // No validation counters.\n";
+  else
+    OS << "  " << Target << Def.getName() << "ValidationCounters, "
+       << NumValidationCounters << " // Validation counters.\n";
 
   OS << "};\n";
   IssueCountersTableOffset += NumIssueCounters;

>From 6d5262636250aa0e2f1c889ee49f609efde9ea06 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Fri, 5 Jan 2024 20:43:08 -0800
Subject: [PATCH 5/5] Add better docs

---
 llvm/include/llvm/Target/TargetPfmCounters.td | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td b/llvm/include/llvm/Target/TargetPfmCounters.td
index 72f6b39f4878f4..edd3505409eba1 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -28,6 +28,9 @@ class PfmIssueCounter<string resource_name, string counter>
   string ResourceName = resource_name;
 }
 
+// Definition of a validation event. A validation event represents a specific
+// event that can be meaasured using performance counters that is interesting
+// in regard to the snippet state.
 class ValidationEvent <int event_number> {
   int EventNumber = event_number;
 }
@@ -37,7 +40,9 @@ def InstructionRetired  : ValidationEvent<1>;
 def DataTLBLoadMiss     : ValidationEvent<2>;
 def DataTLBStoreMiss    : ValidationEvent<3>;
 
-// Validation counters can be tied to a specific event
+// PfmValidationCounter provides a mapping between the events that are
+// are interesting in regards to the snippet execution environment and
+// a concrete performance counter name that can be looked up in libpfm.
 class PfmValidationCounter<ValidationEvent event_type, string counter>
     : PfmCounter<counter> {
   // The name of the event that the validation counter detects.



More information about the cfe-commits mailing list