diff --git a/llvm/docs/CommandGuide/llvm-exegesis.rst b/llvm/docs/CommandGuide/llvm-exegesis.rst --- a/llvm/docs/CommandGuide/llvm-exegesis.rst +++ b/llvm/docs/CommandGuide/llvm-exegesis.rst @@ -204,6 +204,11 @@ But sometimes, you just want to generate snippets, and this is exactly what this options allows one to do. +.. option:: --skip-codegen + + In addition to `--skip-measurements`, also skips target machine code + generation for the snippets that would normally be executed and measured. + .. option:: -x86-lbr-sample-period= Specify the LBR sampling period - how many branches before we take a sample. diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/skip-codegen.s b/llvm/test/tools/llvm-exegesis/X86/latency/skip-codegen.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/X86/latency/skip-codegen.s @@ -0,0 +1,11 @@ +# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mode=latency --skip-measurements -opcode-name=LEA64r -repetition-mode=duplicate | FileCheck %s --check-prefixes=CHECK,CHECK-CODEGEN +# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mode=latency --skip-measurements --skip-codegen -opcode-name=LEA64r -repetition-mode=duplicate | FileCheck %s --check-prefixes=CHECK,CHECK-NO-CODEGEN +# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mode=latency --skip-codegen -opcode-name=LEA64r -repetition-mode=duplicate | FileCheck %s --check-prefixes=CHECK,CHECK-NO-CODEGEN + +CHECK: --- +CHECK-NEXT: mode: latency +CHECK-NEXT: key: +CHECK-NEXT: instructions: +CHECK-NEXT: LEA64r +CHECK-CODEGEN: assembled_snippet: {{[A-Z0-9]+}}{{$}} +CHECK-NO-CODEGEN: assembled_snippet: ''{{$}} diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -36,6 +36,7 @@ public: explicit BenchmarkRunner(const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements); virtual ~BenchmarkRunner(); @@ -98,6 +99,7 @@ protected: const LLVMState &State; const InstructionBenchmark::ModeE Mode; + const bool BenchmarkSkipCodegen; const bool BenchmarkSkipMeasurements; private: diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -31,8 +31,9 @@ BenchmarkRunner::BenchmarkRunner(const LLVMState &State, InstructionBenchmark::ModeE Mode, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements) - : State(State), Mode(Mode), + : State(State), Mode(Mode), BenchmarkSkipCodegen(BenchmarkSkipCodegen), BenchmarkSkipMeasurements(BenchmarkSkipMeasurements), Scratch(std::make_unique()) {} @@ -173,7 +174,7 @@ // understands that the inside instructions are repeated. const int MinInstructionsForSnippet = 4 * Instructions.size(); const int LoopBodySizeForSnippet = 2 * Instructions.size(); - { + if (!BenchmarkSkipCodegen) { auto Snippet = assembleSnippet(BC, Repetitor, MinInstructionsForSnippet, LoopBodySizeForSnippet); if (Error E = Snippet.takeError()) @@ -186,7 +187,7 @@ // Assemble NumRepetitions instructions repetitions of the snippet for // measurements. - { + if (!BenchmarkSkipCodegen) { auto Snippet = assembleSnippet(BC, Repetitor, InstrBenchmark.NumRepetitions, LoopBodySize); if (Error E = Snippet.takeError()) diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h @@ -23,7 +23,7 @@ public: LatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode); ~LatencyBenchmarkRunner() override; diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp @@ -20,9 +20,10 @@ LatencyBenchmarkRunner::LatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAgg) - : BenchmarkRunner(State, Mode, BenchmarkSkipMeasurements) { + : BenchmarkRunner(State, Mode, BenchmarkSkipCodegen, + BenchmarkSkipMeasurements) { assert((Mode == InstructionBenchmark::Latency || Mode == InstructionBenchmark::InverseThroughput) && "invalid mode"); diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -157,10 +157,11 @@ createSnippetGenerator(InstructionBenchmark::ModeE Mode, const LLVMState &State, const SnippetGenerator::Options &Opts) const; + // Creates a benchmark runner for the given mode. Expected> createBenchmarkRunner( InstructionBenchmark::ModeE Mode, const LLVMState &State, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode = InstructionBenchmark::Min) const; @@ -199,10 +200,11 @@ const LLVMState &State, const SnippetGenerator::Options &Opts) const; std::unique_ptr virtual createLatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; std::unique_ptr virtual createUopsBenchmarkRunner( - const LLVMState &State, bool BenchmarkSkipMeasurements, + const LLVMState &State, bool BenchmarkSkipCodegen, + bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; const ExegesisTarget *Next = nullptr; diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp --- a/llvm/tools/llvm-exegesis/lib/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/Target.cpp @@ -74,7 +74,7 @@ Expected> ExegesisTarget::createBenchmarkRunner( InstructionBenchmark::ModeE Mode, const LLVMState &State, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const { PfmCountersInfo PfmCounters = State.getPfmCounters(); switch (Mode) { @@ -94,7 +94,8 @@ "can pass --skip-measurements to skip the actual " "benchmarking.")); } - return createLatencyBenchmarkRunner(State, Mode, BenchmarkSkipMeasurements, + return createLatencyBenchmarkRunner(State, Mode, BenchmarkSkipCodegen, + BenchmarkSkipMeasurements, ResultAggMode); case InstructionBenchmark::Uops: if (!BenchmarkSkipMeasurements && !PfmCounters.UopsCounter && @@ -103,8 +104,8 @@ "can't run 'uops' mode, sched model does not define uops or issue " "counters. You can pass --skip-measurements to skip the actual " "benchmarking."); - return createUopsBenchmarkRunner(State, BenchmarkSkipMeasurements, - ResultAggMode); + return createUopsBenchmarkRunner(State, BenchmarkSkipCodegen, + BenchmarkSkipMeasurements, ResultAggMode); } return nullptr; } @@ -121,16 +122,18 @@ std::unique_ptr ExegesisTarget::createLatencyBenchmarkRunner( const LLVMState &State, InstructionBenchmark::ModeE Mode, - bool BenchmarkSkipMeasurements, + bool BenchmarkSkipCodegen, bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE ResultAggMode) const { return std::make_unique( - State, Mode, BenchmarkSkipMeasurements, ResultAggMode); + State, Mode, BenchmarkSkipCodegen, BenchmarkSkipMeasurements, + ResultAggMode); } std::unique_ptr ExegesisTarget::createUopsBenchmarkRunner( - const LLVMState &State, bool BenchmarkSkipMeasurements, + const LLVMState &State, bool BenchmarkSkipCodegen, + bool BenchmarkSkipMeasurements, InstructionBenchmark::ResultAggregationModeE /*unused*/) const { - return std::make_unique(State, + return std::make_unique(State, BenchmarkSkipCodegen, BenchmarkSkipMeasurements); } diff --git a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h @@ -21,8 +21,9 @@ class UopsBenchmarkRunner : public BenchmarkRunner { public: - UopsBenchmarkRunner(const LLVMState &State, bool BenchmarkSkipMeasurements) - : BenchmarkRunner(State, InstructionBenchmark::Uops, + UopsBenchmarkRunner(const LLVMState &State, bool BenchmarkSkipCodegen, + bool BenchmarkSkipMeasurements) + : BenchmarkRunner(State, InstructionBenchmark::Uops, BenchmarkSkipCodegen, BenchmarkSkipMeasurements) {} ~UopsBenchmarkRunner() override; diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -116,9 +116,16 @@ cl::desc("Produce progress indicator when performing measurements"), cl::cat(BenchmarkOptions), cl::init(false)); +static cl::opt BenchmarkSkipCodegen( + "skip-codegen", + cl::desc("do everything except actually assembling the snippets to be " + "measured, implies --skip-measurements"), + cl::cat(BenchmarkOptions), cl::init(false)); + static cl::opt BenchmarkSkipMeasurements( "skip-measurements", - cl::desc("do everything except actually performing the measurements"), + cl::desc("do everything except actually performing the measurements, is " + "implied by --skip-codegen"), cl::cat(BenchmarkOptions), cl::init(false)); static cl::opt @@ -410,7 +417,8 @@ const std::unique_ptr Runner = ExitOnErr(State.getExegesisTarget().createBenchmarkRunner( - BenchmarkMode, State, BenchmarkSkipMeasurements, ResultAggMode)); + BenchmarkMode, State, BenchmarkSkipCodegen, BenchmarkSkipMeasurements, + ResultAggMode)); if (!Runner) { ExitWithError("cannot create benchmark runner"); } @@ -592,6 +600,11 @@ "llvm host machine instruction characteristics " "measurment and analysis.\n"); + if (llvm::exegesis::BenchmarkSkipCodegen) { + llvm::exegesis::DumpObjectToDisk = false; + llvm::exegesis::BenchmarkSkipMeasurements = true; + } + exegesis::ExitOnErr.setExitCodeMapper([](const Error &Err) { if (Err.isA()) return EXIT_SUCCESS;