Skip to content

[llvm-exegesis][NFC] Refactor all ValidationEvent info in a single … #82256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 21, 2024

Conversation

legrosbuffle
Copy link
Contributor

…table.

All data is derived from a single table rather than being spread out over an enum, a table and the main entry point.

This is intended as a replacement for #82092.

…table.

All data is derived from a single table rather than being spread out
over an enum, a table and the main entry point.
@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2024

@llvm/pr-subscribers-tools-llvm-exegesis

Author: Clement Courbet (legrosbuffle)

Changes

…table.

All data is derived from a single table rather than being spread out over an enum, a table and the main entry point.

This is intended as a replacement for #82092.


Full diff: https://github.com/llvm/llvm-project/pull/82256.diff

9 Files Affected:

  • (modified) llvm/include/llvm/Target/TargetPfmCounters.td (+1)
  • (modified) llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp (+3-46)
  • (modified) llvm/tools/llvm-exegesis/lib/BenchmarkResult.h (+1-14)
  • (modified) llvm/tools/llvm-exegesis/lib/CMakeLists.txt (+1)
  • (modified) llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp (+2-2)
  • (modified) llvm/tools/llvm-exegesis/lib/Target.h (+1)
  • (added) llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp (+53)
  • (added) llvm/tools/llvm-exegesis/lib/ValidationEvent.h (+60)
  • (modified) llvm/tools/llvm-exegesis/llvm-exegesis.cpp (+2-18)
diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td b/llvm/include/llvm/Target/TargetPfmCounters.td
index 8c4d5f50c63a24..cfe432a992b71f 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -35,6 +35,7 @@ class ValidationEvent <int event_number> {
   int EventNumber = event_number;
 }
 
+// TableGen names for events defined in `llvm::exegesis::ValidationEvent`.
 def InstructionRetired  : ValidationEvent<0>;
 def L1DCacheLoadMiss : ValidationEvent<1>;
 def L1DCacheStoreMiss : ValidationEvent<2>;
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index 189add6464173f..f84ebd2a4e68ef 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -9,6 +9,7 @@
 #include "BenchmarkResult.h"
 #include "BenchmarkRunner.h"
 #include "Error.h"
+#include "ValidationEvent.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringRef.h"
@@ -198,7 +199,7 @@ struct CustomMappingTraits<std::map<exegesis::ValidationEvent, int64_t>> {
   static void inputOne(IO &Io, StringRef KeyStr,
                        std::map<exegesis::ValidationEvent, int64_t> &VI) {
     Expected<exegesis::ValidationEvent> Key =
-        exegesis::stringToValidationEvent(KeyStr);
+        exegesis::getValidationEventByName(KeyStr);
     if (!Key) {
       Io.setError("Key is not a valid validation event");
       return;
@@ -208,7 +209,7 @@ struct CustomMappingTraits<std::map<exegesis::ValidationEvent, int64_t>> {
 
   static void output(IO &Io, std::map<exegesis::ValidationEvent, int64_t> &VI) {
     for (auto &IndividualVI : VI) {
-      Io.mapRequired(exegesis::validationEventToString(IndividualVI.first),
+      Io.mapRequired(exegesis::getValidationEventName(IndividualVI.first),
                      IndividualVI.second);
     }
   }
@@ -441,49 +442,5 @@ bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B) {
          std::tie(B.Key, B.PerInstructionValue, B.PerSnippetValue);
 }
 
-const char *validationEventToString(ValidationEvent VE) {
-  switch (VE) {
-  case exegesis::ValidationEvent::InstructionRetired:
-    return "instructions-retired";
-  case exegesis::ValidationEvent::L1DCacheLoadMiss:
-    return "l1d-cache-load-misses";
-  case exegesis::ValidationEvent::L1DCacheStoreMiss:
-    return "l1d-cache-store-misses";
-  case exegesis::ValidationEvent::L1ICacheLoadMiss:
-    return "l1i-cache-load-misses";
-  case exegesis::ValidationEvent::DataTLBLoadMiss:
-    return "data-tlb-load-misses";
-  case exegesis::ValidationEvent::DataTLBStoreMiss:
-    return "data-tlb-store-misses";
-  case exegesis::ValidationEvent::InstructionTLBLoadMiss:
-    return "instruction-tlb-load-misses";
-  case exegesis::ValidationEvent::BranchPredictionMiss:
-    return "branch-prediction-misses";
-  }
-  llvm_unreachable("Unhandled exegesis::ValidationEvent enum");
-}
-
-Expected<ValidationEvent> stringToValidationEvent(StringRef Input) {
-  if (Input == "instructions-retired")
-    return exegesis::ValidationEvent::InstructionRetired;
-  else if (Input == "l1d-cache-load-misses")
-    return exegesis::ValidationEvent::L1DCacheLoadMiss;
-  else if (Input == "l1d-cache-store-misses")
-    return exegesis::ValidationEvent::L1DCacheStoreMiss;
-  else if (Input == "l1i-cache-load-misses")
-    return exegesis::ValidationEvent::L1ICacheLoadMiss;
-  else if (Input == "data-tlb-load-misses")
-    return exegesis::ValidationEvent::DataTLBLoadMiss;
-  else if (Input == "data-tlb-store-misses")
-    return exegesis::ValidationEvent::DataTLBStoreMiss;
-  else if (Input == "instruction-tlb-load-misses")
-    return exegesis::ValidationEvent::InstructionTLBLoadMiss;
-  else if (Input == "branch-prediction-misses")
-    return exegesis::ValidationEvent::BranchPredictionMiss;
-  else
-    return make_error<StringError>("Invalid validation event string",
-                                   errc::invalid_argument);
-}
-
 } // namespace exegesis
 } // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 60115c51bba321..0aecaaeea4b2e7 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -17,6 +17,7 @@
 
 #include "LlvmState.h"
 #include "RegisterValue.h"
+#include "ValidationEvent.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstBuilder.h"
@@ -32,20 +33,6 @@ class Error;
 
 namespace exegesis {
 
-enum ValidationEvent {
-  InstructionRetired,
-  L1DCacheLoadMiss,
-  L1DCacheStoreMiss,
-  L1ICacheLoadMiss,
-  DataTLBLoadMiss,
-  DataTLBStoreMiss,
-  InstructionTLBLoadMiss,
-  BranchPredictionMiss
-};
-
-const char *validationEventToString(exegesis::ValidationEvent VE);
-Expected<ValidationEvent> stringToValidationEvent(StringRef Input);
-
 enum class BenchmarkPhaseSelectorE {
   PrepareSnippet,
   PrepareAndAssembleSnippet,
diff --git a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
index 6ae441d31f07fe..414b49e5e021c2 100644
--- a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
+++ b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
@@ -73,6 +73,7 @@ add_llvm_library(LLVMExegesis
   SubprocessMemory.cpp
   Target.cpp
   UopsBenchmarkRunner.cpp
+  ValidationEvent.cpp
 
   LINK_LIBS ${libs}
 
diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
index a9917a29cce24d..de61fff6432944 100644
--- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
@@ -107,8 +107,8 @@ Expected<std::vector<BenchmarkMeasure>> LatencyBenchmarkRunner::runMeasurements(
     }
 
     for (size_t I = 0; I < ValCounterValues.size(); ++I) {
-      LLVM_DEBUG(dbgs() << validationEventToString(ValidationCounters[I])
-                        << ": " << IterationValCounterValues[I] << "\n");
+      LLVM_DEBUG(dbgs() << getValidationEventName(ValidationCounters[I]) << ": "
+                        << IterationValCounterValues[I] << "\n");
       ValCounterValues[I] += IterationValCounterValues[I];
     }
   }
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 3d6169c9650213..7bbd946b03331f 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -22,6 +22,7 @@
 #include "LlvmState.h"
 #include "PerfHelper.h"
 #include "SnippetGenerator.h"
+#include "ValidationEvent.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/LegacyPassManager.h"
diff --git a/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp b/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp
new file mode 100644
index 00000000000000..a212e1c4fdf7c8
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp
@@ -0,0 +1,53 @@
+
+#include "ValidationEvent.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace exegesis {
+
+namespace {
+
+struct ValidationEventInfo {
+  const char *const Name;
+  const char *const Description;
+};
+
+// Information about validation events, indexed by `ValidationEvent` enum
+// value.
+static constexpr ValidationEventInfo ValidationEventInfos[NumValidationEvents] =
+    {
+        {"instructions-retired", "Count retired instructions"},
+        {"l1d-cache-load-misses", "Count L1D load cache misses"},
+        {"l1d-cache-store-misses", "Count L1D store cache misses"},
+        {"l1i-cache-load-misses", "Count L1I load cache misses"},
+        {"data-tlb-load-misses", "Count DTLB load misses"},
+        {"data-tlb-store-misses", "Count DTLB store misses"},
+        {"instruction-tlb-load-misses", "Count ITLB load misses"},
+        {"branch-prediction-misses", "Branch prediction misses"},
+};
+
+} // namespace
+
+const char *getValidationEventName(ValidationEvent VE) {
+  return ValidationEventInfos[VE].Name;
+}
+const char *getValidationEventDescription(ValidationEvent VE) {
+  return ValidationEventInfos[VE].Description;
+}
+
+Expected<ValidationEvent> getValidationEventByName(StringRef Name) {
+  int VE = 0;
+  for (const ValidationEventInfo &Info : ValidationEventInfos) {
+    if (Name == Info.Name)
+      return static_cast<ValidationEvent>(VE);
+    ++VE;
+  }
+
+  return make_error<StringError>("Invalid validation event string",
+                                 errc::invalid_argument);
+}
+
+} // namespace exegesis
+} // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/ValidationEvent.h b/llvm/tools/llvm-exegesis/lib/ValidationEvent.h
new file mode 100644
index 00000000000000..8a9f3af57dca97
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/ValidationEvent.h
@@ -0,0 +1,60 @@
+//===-- ValidationEvent.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definitions and utilities for Validation Events.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_VALIDATIONEVENT_H
+#define LLVM_TOOLS_LLVM_EXEGESIS_VALIDATIONEVENT_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+namespace exegesis {
+
+// The main list of supported validation events. The mapping between validation
+// events and pfm counters is defined in TableDef files for each target.
+enum ValidationEvent {
+  InstructionRetired,
+  L1DCacheLoadMiss,
+  L1DCacheStoreMiss,
+  L1ICacheLoadMiss,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss,
+  InstructionTLBLoadMiss,
+  BranchPredictionMiss,
+  // Number of events.
+  NumValidationEvents,
+};
+
+// Returns the name/description of the given event.
+const char *getValidationEventName(ValidationEvent VE);
+const char *getValidationEventDescription(ValidationEvent VE);
+
+// Returns the ValidationEvent with the given name.
+Expected<ValidationEvent> getValidationEventByName(StringRef Name);
+
+// Command-line options for validation events.
+struct ValidationEventOptions {
+  template <class Opt> void apply(Opt &O) const {
+    for (int I = 0; I < NumValidationEvents; ++I) {
+      const auto VE = static_cast<ValidationEvent>(I);
+      O.getParser().addLiteralOption(getValidationEventName(VE), VE,
+                                     getValidationEventDescription(VE));
+    }
+  }
+};
+
+} // namespace exegesis
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index ac279029e6b004..66387bdec5a5a6 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -25,6 +25,7 @@
 #include "lib/SnippetRepetitor.h"
 #include "lib/Target.h"
 #include "lib/TargetSelect.h"
+#include "lib/ValidationEvent.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/MC/MCInstBuilder.h"
@@ -278,24 +279,7 @@ static cl::list<ValidationEvent> ValidationCounters(
     cl::desc(
         "The name of a validation counter to run concurrently with the main "
         "counter to validate benchmarking assumptions"),
-    cl::CommaSeparated, cl::cat(BenchmarkOptions),
-    cl::values(
-        clEnumValN(ValidationEvent::InstructionRetired, "instructions-retired",
-                   "Count retired instructions"),
-        clEnumValN(ValidationEvent::L1DCacheLoadMiss, "l1d-cache-load-misses",
-                   "Count L1D load cache misses"),
-        clEnumValN(ValidationEvent::L1DCacheStoreMiss, "l1d-cache-store-misses",
-                   "Count L1D store cache misses"),
-        clEnumValN(ValidationEvent::L1ICacheLoadMiss, "l1i-cache-load-misses",
-                   "Count L1I load cache misses"),
-        clEnumValN(ValidationEvent::DataTLBLoadMiss, "data-tlb-load-misses",
-                   "Count DTLB load misses"),
-        clEnumValN(ValidationEvent::DataTLBStoreMiss, "data-tlb-store-misses",
-                   "Count DTLB store misses"),
-        clEnumValN(ValidationEvent::InstructionTLBLoadMiss,
-                   "instruction-tlb-load-misses", "Count ITLB load misses"),
-        clEnumValN(ValidationEvent::BranchPredictionMiss,
-                   "branch-prediction-misses", "Branch prediction misses")));
+    cl::CommaSeparated, cl::cat(BenchmarkOptions), ValidationEventOptions());
 
 static ExitOnError ExitOnErr("llvm-exegesis error: ");
 

Copy link
Contributor

@boomanaiden154 boomanaiden154 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together. This is definitely improves in a couple ways compared to my patch.


// Information about validation events, indexed by `ValidationEvent` enum
// value.
static constexpr ValidationEventInfo ValidationEventInfos[NumValidationEvents] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to use a static_assert to ensure that the length of this array is the same as the enum to prevent someone missing the implementation of a validation counter here? I think it would be tricky with a standard array, but with a std::array, I think we should have access to a constexpr size() method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my intent by specifying the array bound. I had forgotten that int arr[3] = {1,2}; compiled perfectly fine in c++ :( Done, thanks.

Copy link
Contributor

@boomanaiden154 boomanaiden154 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

namespace exegesis {

// The main list of supported validation events. The mapping between validation
// events and pfm counters is defined in TableDef files for each target.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Maybe add a note here that the text mapping in ValidationEvent.cpp needs to be updated as well? The static_assert should take care of it, but having the info in the comment wouldn't hurt.

@legrosbuffle legrosbuffle merged commit 8b84de2 into llvm:main Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants