From 9b93c8bf0614e64352de8e210adf6ff316c0133e Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Mon, 19 Feb 2024 14:58:27 +0000 Subject: [PATCH 1/2] [llvm-exegesis][NFC] Refactor all `ValidationEvent` info in a single table. All data is derived from a single table rather than being spread out over an enum, a table and the main entry point. --- llvm/include/llvm/Target/TargetPfmCounters.td | 1 + .../llvm-exegesis/lib/BenchmarkResult.cpp | 49 +-------------- .../tools/llvm-exegesis/lib/BenchmarkResult.h | 15 +---- llvm/tools/llvm-exegesis/lib/CMakeLists.txt | 1 + .../lib/LatencyBenchmarkRunner.cpp | 4 +- llvm/tools/llvm-exegesis/lib/Target.h | 1 + .../llvm-exegesis/lib/ValidationEvent.cpp | 53 ++++++++++++++++ .../tools/llvm-exegesis/lib/ValidationEvent.h | 60 +++++++++++++++++++ llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 20 +------ 9 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp create mode 100644 llvm/tools/llvm-exegesis/lib/ValidationEvent.h diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td b/llvm/include/llvm/Target/TargetPfmCounters.td index 8c4d5f50c63a2..cfe432a992b71 100644 --- a/llvm/include/llvm/Target/TargetPfmCounters.td +++ b/llvm/include/llvm/Target/TargetPfmCounters.td @@ -35,6 +35,7 @@ class ValidationEvent { 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 189add6464173..f84ebd2a4e68e 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> { static void inputOne(IO &Io, StringRef KeyStr, std::map &VI) { Expected 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> { static void output(IO &Io, std::map &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 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("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 60115c51bba32..0aecaaeea4b2e 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 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 6ae441d31f07f..414b49e5e021c 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 a9917a29cce24..de61fff643294 100644 --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp @@ -107,8 +107,8 @@ Expected> 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 3d6169c965021..7bbd946b03331 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 0000000000000..a212e1c4fdf7c --- /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 getValidationEventByName(StringRef Name) { + int VE = 0; + for (const ValidationEventInfo &Info : ValidationEventInfos) { + if (Name == Info.Name) + return static_cast(VE); + ++VE; + } + + return make_error("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 0000000000000..8a9f3af57dca9 --- /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 getValidationEventByName(StringRef Name); + +// Command-line options for validation events. +struct ValidationEventOptions { + template void apply(Opt &O) const { + for (int I = 0; I < NumValidationEvents; ++I) { + const auto VE = static_cast(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 ac279029e6b00..66387bdec5a5a 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 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: "); From a4e177fd8fe0289742be8a4a90ae010b5fbd5630 Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Tue, 20 Feb 2024 08:43:23 +0000 Subject: [PATCH 2/2] `static_assert` that the size of `ValidationEventInfos` is consistent with that of the enum. --- .../llvm-exegesis/lib/ValidationEvent.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp b/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp index a212e1c4fdf7c..c965b7ae55e10 100644 --- a/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp +++ b/llvm/tools/llvm-exegesis/lib/ValidationEvent.cpp @@ -16,18 +16,21 @@ struct ValidationEventInfo { // 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"}, +static constexpr ValidationEventInfo ValidationEventInfos[] = { + {"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"}, }; +static_assert(sizeof(ValidationEventInfos) == + NumValidationEvents * sizeof(ValidationEventInfo), + "please update ValidationEventInfos"); + } // namespace const char *getValidationEventName(ValidationEvent VE) {