[llvm] [Exegesis] Add `--dry-run-measurement` (PR #121991)
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 7 16:44:36 PST 2025
https://github.com/mshockwave updated https://github.com/llvm/llvm-project/pull/121991
>From d4edd1dccee66ba64fee32290278aeeb507121a8 Mon Sep 17 00:00:00 2001
From: Min Hsu <min.hsu at sifive.com>
Date: Tue, 7 Jan 2025 12:30:11 -0800
Subject: [PATCH 1/2] [Exegesis] Add `--dry-run-measurement`
This flag will make llvm-exegesis run everything except the actual
snippet execution.
---
llvm/docs/CommandGuide/llvm-exegesis.rst | 5 ++++
.../llvm-exegesis/dry-run-measurement.test | 11 +++++++++
.../llvm-exegesis/lib/BenchmarkRunner.cpp | 24 +++++++++++++++----
3 files changed, 35 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/tools/llvm-exegesis/dry-run-measurement.test
diff --git a/llvm/docs/CommandGuide/llvm-exegesis.rst b/llvm/docs/CommandGuide/llvm-exegesis.rst
index 8266d891a5e6b1..cd0bce9e2dbcc3 100644
--- a/llvm/docs/CommandGuide/llvm-exegesis.rst
+++ b/llvm/docs/CommandGuide/llvm-exegesis.rst
@@ -449,6 +449,11 @@ OPTIONS
crash when hardware performance counters are unavailable and for
debugging :program:`llvm-exegesis` itself.
+.. option:: --dry-run-measurement
+ If set, llvm-exegesis runs everything except the actual snippet execution.
+ This is useful if we want to test some part of the code without actually
+ running on native platforms.
+
.. option:: --execution-mode=[inprocess,subprocess]
This option specifies what execution mode to use. The `inprocess` execution
diff --git a/llvm/test/tools/llvm-exegesis/dry-run-measurement.test b/llvm/test/tools/llvm-exegesis/dry-run-measurement.test
new file mode 100644
index 00000000000000..82857e7998b5e6
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/dry-run-measurement.test
@@ -0,0 +1,11 @@
+# RUN: llvm-exegesis --mtriple=riscv64 --mcpu=sifive-p470 --mode=latency --opcode-name=ADD --use-dummy-perf-counters --dry-run-measurement | FileCheck %s
+# REQUIRES: riscv-registered-target
+
+# This test makes sure that llvm-exegesis doesn't execute "cross-compiled" snippets in the presence of
+# --dry-run-measurement. RISC-V was chosen simply because most of the time we run tests on X86 machines.
+
+# Should not contain misleading results.
+# CHECK: measurements: []
+
+# Should not contain error messages like "snippet crashed while running: Segmentation fault".
+# CHECK: error: ''
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index a7771b99e97b1a..9b978c558c1fe7 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -53,6 +53,12 @@
namespace llvm {
namespace exegesis {
+static cl::opt<bool>
+ DryRunMeasurement("dry-run-measurement",
+ cl::desc("Run every steps in the measurement phase "
+ "except executing the snippet."),
+ cl::init(false), cl::Hidden);
+
BenchmarkRunner::BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
ExecutionModeE ExecutionMode,
@@ -140,13 +146,21 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
Scratch->clear();
{
auto PS = ET.withSavedState();
+ // We can't directly capture DryRunMeasurement in the lambda below.
+ bool DryRun = DryRunMeasurement;
CrashRecoveryContext CRC;
CrashRecoveryContext::Enable();
- const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() {
- Counter->start();
- this->Function(ScratchPtr);
- Counter->stop();
- });
+ const bool Crashed =
+ !CRC.RunSafely([this, Counter, ScratchPtr, DryRun]() {
+ if (DryRun) {
+ Counter->start();
+ Counter->stop();
+ } else {
+ Counter->start();
+ this->Function(ScratchPtr);
+ Counter->stop();
+ }
+ });
CrashRecoveryContext::Disable();
PS.reset();
if (Crashed) {
>From a5403854cfa2d49d1ed69413bfa6194a7ab2c012 Mon Sep 17 00:00:00 2001
From: Min Hsu <min.hsu at sifive.com>
Date: Tue, 7 Jan 2025 16:41:07 -0800
Subject: [PATCH 2/2] Use benchmark phase instead of command line flag to
select dry-run-measurement
---
llvm/docs/CommandGuide/llvm-exegesis.rst | 6 +--
.../llvm-exegesis/dry-run-measurement.test | 2 +-
.../tools/llvm-exegesis/lib/BenchmarkResult.h | 1 +
.../llvm-exegesis/lib/BenchmarkRunner.cpp | 51 ++++++++++---------
llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 5 +-
5 files changed, 34 insertions(+), 31 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-exegesis.rst b/llvm/docs/CommandGuide/llvm-exegesis.rst
index cd0bce9e2dbcc3..d357c2ceea4189 100644
--- a/llvm/docs/CommandGuide/llvm-exegesis.rst
+++ b/llvm/docs/CommandGuide/llvm-exegesis.rst
@@ -301,6 +301,7 @@ OPTIONS
* ``prepare-and-assemble-snippet``: Same as ``prepare-snippet``, but also dumps an excerpt of the sequence (hex encoded).
* ``assemble-measured-code``: Same as ``prepare-and-assemble-snippet``. but also creates the full sequence that can be dumped to a file using ``--dump-object-to-disk``.
* ``measure``: Same as ``assemble-measured-code``, but also runs the measurement.
+ * ``dry-run-measurement``: Same as measure, but does not actually execute the snippet.
.. option:: --x86-lbr-sample-period=<nBranches/sample>
@@ -449,11 +450,6 @@ OPTIONS
crash when hardware performance counters are unavailable and for
debugging :program:`llvm-exegesis` itself.
-.. option:: --dry-run-measurement
- If set, llvm-exegesis runs everything except the actual snippet execution.
- This is useful if we want to test some part of the code without actually
- running on native platforms.
-
.. option:: --execution-mode=[inprocess,subprocess]
This option specifies what execution mode to use. The `inprocess` execution
diff --git a/llvm/test/tools/llvm-exegesis/dry-run-measurement.test b/llvm/test/tools/llvm-exegesis/dry-run-measurement.test
index 82857e7998b5e6..e4449d7df3d826 100644
--- a/llvm/test/tools/llvm-exegesis/dry-run-measurement.test
+++ b/llvm/test/tools/llvm-exegesis/dry-run-measurement.test
@@ -1,4 +1,4 @@
-# RUN: llvm-exegesis --mtriple=riscv64 --mcpu=sifive-p470 --mode=latency --opcode-name=ADD --use-dummy-perf-counters --dry-run-measurement | FileCheck %s
+# RUN: llvm-exegesis --mtriple=riscv64 --mcpu=sifive-p470 --mode=latency --opcode-name=ADD --use-dummy-perf-counters --benchmark-phase=dry-run-measurement | FileCheck %s
# REQUIRES: riscv-registered-target
# This test makes sure that llvm-exegesis doesn't execute "cross-compiled" snippets in the presence of
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 3c09a8380146e5..5480d856168784 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -38,6 +38,7 @@ enum class BenchmarkPhaseSelectorE {
PrepareAndAssembleSnippet,
AssembleMeasuredCode,
Measure,
+ DryRunMeasure,
};
enum class BenchmarkFilter { All, RegOnly, WithMem };
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 9b978c558c1fe7..cc46f7feb6cf7f 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -53,12 +53,6 @@
namespace llvm {
namespace exegesis {
-static cl::opt<bool>
- DryRunMeasurement("dry-run-measurement",
- cl::desc("Run every steps in the measurement phase "
- "except executing the snippet."),
- cl::init(false), cl::Hidden);
-
BenchmarkRunner::BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
ExecutionModeE ExecutionMode,
@@ -105,7 +99,7 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
static Expected<std::unique_ptr<InProcessFunctionExecutorImpl>>
create(const LLVMState &State, object::OwningBinary<object::ObjectFile> Obj,
BenchmarkRunner::ScratchSpace *Scratch,
- std::optional<int> BenchmarkProcessCPU) {
+ std::optional<int> BenchmarkProcessCPU, bool DryRun) {
Expected<ExecutableFunction> EF =
ExecutableFunction::create(State.createTargetMachine(), std::move(Obj));
@@ -113,14 +107,17 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
return EF.takeError();
return std::unique_ptr<InProcessFunctionExecutorImpl>(
- new InProcessFunctionExecutorImpl(State, std::move(*EF), Scratch));
+ new InProcessFunctionExecutorImpl(State, std::move(*EF), Scratch,
+ DryRun));
}
private:
InProcessFunctionExecutorImpl(const LLVMState &State,
ExecutableFunction Function,
- BenchmarkRunner::ScratchSpace *Scratch)
- : State(State), Function(std::move(Function)), Scratch(Scratch) {}
+ BenchmarkRunner::ScratchSpace *Scratch,
+ bool DryRun)
+ : State(State), Function(std::move(Function)), Scratch(Scratch),
+ DryRun(DryRun) {}
static void accumulateCounterValues(const SmallVector<int64_t, 4> &NewValues,
SmallVector<int64_t, 4> *Result) {
@@ -146,21 +143,18 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
Scratch->clear();
{
auto PS = ET.withSavedState();
- // We can't directly capture DryRunMeasurement in the lambda below.
- bool DryRun = DryRunMeasurement;
CrashRecoveryContext CRC;
CrashRecoveryContext::Enable();
- const bool Crashed =
- !CRC.RunSafely([this, Counter, ScratchPtr, DryRun]() {
- if (DryRun) {
- Counter->start();
- Counter->stop();
- } else {
- Counter->start();
- this->Function(ScratchPtr);
- Counter->stop();
- }
- });
+ const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() {
+ if (DryRun) {
+ Counter->start();
+ Counter->stop();
+ } else {
+ Counter->start();
+ this->Function(ScratchPtr);
+ Counter->stop();
+ }
+ });
CrashRecoveryContext::Disable();
PS.reset();
if (Crashed) {
@@ -191,6 +185,7 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
const LLVMState &State;
const ExecutableFunction Function;
BenchmarkRunner::ScratchSpace *const Scratch;
+ bool DryRun = false;
};
#ifdef __linux__
@@ -678,6 +673,9 @@ Expected<std::unique_ptr<BenchmarkRunner::FunctionExecutor>>
BenchmarkRunner::createFunctionExecutor(
object::OwningBinary<object::ObjectFile> ObjectFile,
const BenchmarkKey &Key, std::optional<int> BenchmarkProcessCPU) const {
+ bool DryRun =
+ BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::DryRunMeasure;
+
switch (ExecutionMode) {
case ExecutionModeE::InProcess: {
if (BenchmarkProcessCPU.has_value())
@@ -685,7 +683,8 @@ BenchmarkRunner::createFunctionExecutor(
"support benchmark core pinning.");
auto InProcessExecutorOrErr = InProcessFunctionExecutorImpl::create(
- State, std::move(ObjectFile), Scratch.get(), BenchmarkProcessCPU);
+ State, std::move(ObjectFile), Scratch.get(), BenchmarkProcessCPU,
+ DryRun);
if (!InProcessExecutorOrErr)
return InProcessExecutorOrErr.takeError();
@@ -693,6 +692,10 @@ BenchmarkRunner::createFunctionExecutor(
}
case ExecutionModeE::SubProcess: {
#ifdef __linux__
+ if (DryRun)
+ return make_error<Failure>("The subprocess execution mode cannot "
+ "dry-run measurement at this moment.");
+
auto SubProcessExecutorOrErr = SubProcessFunctionExecutorImpl::create(
State, std::move(ObjectFile), Key, BenchmarkProcessCPU);
if (!SubProcessExecutorOrErr)
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index fa37e05956be8c..2ae76914ac2b46 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -132,7 +132,10 @@ static cl::opt<BenchmarkPhaseSelectorE> BenchmarkPhaseSelector(
clEnumValN(
BenchmarkPhaseSelectorE::Measure, "measure",
"Same as prepare-measured-code, but also runs the measurement "
- "(default)")),
+ "(default)"),
+ clEnumValN(
+ BenchmarkPhaseSelectorE::DryRunMeasure, "dry-run-measurement",
+ "Same as measure, but does not actually execute the snippet")),
cl::init(BenchmarkPhaseSelectorE::Measure));
static cl::opt<bool>
More information about the llvm-commits
mailing list