From 1dd4a6aac6498c6ebdcfcc3da0beb440e4650b20 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 18 Dec 2022 04:15:04 +0300 Subject: [PATCH] [NFC][llvm-exegesis] `BenchmarkRunner`: split `runConfiguration()` into `getRunnableConfiguration()` + `runConfiguration()` We can run as many `getRunnableConfiguration()` in parallel as we want, but `runConfiguration()` must be run *completely* standalone from everything. This is a step towards enabling threading. --- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 37 ++++++++++++++++-------- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h | 28 ++++++++++++++++-- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 6 ++-- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index db7d49f..eb90f43 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -150,10 +150,15 @@ Expected> BenchmarkRunner::assembleSnippet( return Buffer; } -Expected BenchmarkRunner::runConfiguration( - const BenchmarkCode &BC, unsigned NumRepetitions, unsigned LoopBodySize, - const SnippetRepetitor &Repetitor, bool DumpObjectToDisk) const { - InstructionBenchmark InstrBenchmark; +Expected +BenchmarkRunner::getRunnableConfiguration(const BenchmarkCode &BC, + unsigned NumRepetitions, + unsigned LoopBodySize, + const SnippetRepetitor &Repetitor, + bool DumpObjectToDisk) const { + RunnableConfiguration RC; + + InstructionBenchmark &InstrBenchmark = RC.InstrBenchmark; InstrBenchmark.Mode = Mode; InstrBenchmark.CpuName = std::string(State.getTargetMachine().getTargetCPU()); InstrBenchmark.LLVMTriple = @@ -183,7 +188,6 @@ Expected BenchmarkRunner::runConfiguration( // Assemble NumRepetitions instructions repetitions of the snippet for // measurements. - object::OwningBinary ObjectFile; { auto Snippet = assembleSnippet(BC, Repetitor, InstrBenchmark.NumRepetitions, LoopBodySize); @@ -193,18 +197,26 @@ Expected BenchmarkRunner::runConfiguration( auto ObjectFilePath = writeObjectFile(*Snippet); if (Error E = ObjectFilePath.takeError()) { InstrBenchmark.Error = toString(std::move(E)); - return InstrBenchmark; + return std::move(RC); } outs() << "Check generated assembly with: /usr/bin/objdump -d " << *ObjectFilePath << "\n"; } - ObjectFile = getObjectFromBuffer(*Snippet); + RC.ObjectFile = getObjectFromBuffer(*Snippet); } + return std::move(RC); +} + +Expected +BenchmarkRunner::runConfiguration(RunnableConfiguration &&RC) const { + InstructionBenchmark &InstrBenchmark = RC.InstrBenchmark; + object::OwningBinary &ObjectFile = RC.ObjectFile; + if (BenchmarkSkipMeasurements) { InstrBenchmark.Error = "in --skip-measurements mode, actual measurements skipped."; - return InstrBenchmark; + return std::move(InstrBenchmark); } const FunctionExecutorImpl Executor(State, std::move(ObjectFile), @@ -214,19 +226,20 @@ Expected BenchmarkRunner::runConfiguration( if (!E.isA()) return std::move(E); InstrBenchmark.Error = toString(std::move(E)); - return InstrBenchmark; + return std::move(InstrBenchmark); } assert(InstrBenchmark.NumRepetitions > 0 && "invalid NumRepetitions"); for (BenchmarkMeasure &BM : *NewMeasurements) { // Scale the measurements by instruction. BM.PerInstructionValue /= InstrBenchmark.NumRepetitions; // Scale the measurements by snippet. - BM.PerSnippetValue *= static_cast(Instructions.size()) / - InstrBenchmark.NumRepetitions; + BM.PerSnippetValue *= + static_cast(InstrBenchmark.Key.Instructions.size()) / + InstrBenchmark.NumRepetitions; } InstrBenchmark.Measurements = std::move(*NewMeasurements); - return InstrBenchmark; + return std::move(InstrBenchmark); } Expected BenchmarkRunner::writeObjectFile(StringRef Buffer) const { diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h index dd935c3..5bd9bc2 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -40,10 +40,32 @@ public: virtual ~BenchmarkRunner(); + class RunnableConfiguration { + friend class BenchmarkRunner; + + public: + ~RunnableConfiguration() = default; + RunnableConfiguration(RunnableConfiguration &&) = default; + + RunnableConfiguration(const RunnableConfiguration &) = delete; + RunnableConfiguration &operator=(RunnableConfiguration &&) = delete; + RunnableConfiguration &operator=(const RunnableConfiguration &) = delete; + + private: + RunnableConfiguration() = default; + + InstructionBenchmark InstrBenchmark; + object::OwningBinary ObjectFile; + }; + + Expected + getRunnableConfiguration(const BenchmarkCode &Configuration, + unsigned NumRepetitions, unsigned LoopUnrollFactor, + const SnippetRepetitor &Repetitor, + bool DumpObjectToDisk) const; + Expected - runConfiguration(const BenchmarkCode &Configuration, unsigned NumRepetitions, - unsigned LoopUnrollFactor, const SnippetRepetitor &Repetitor, - bool DumpObjectToDisk) const; + runConfiguration(RunnableConfiguration &&RC) const; // Scratch space to run instructions that touch memory. struct ScratchSpace { diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index e74fb15..02d3b90 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -421,8 +421,10 @@ void benchmarkMain() { for (const std::unique_ptr &Repetitor : Repetitors) { - AllResults.emplace_back(ExitOnErr(Runner->runConfiguration( - Conf, NumRepetitions, LoopBodySize, *Repetitor, DumpObjectToDisk))); + auto RC = ExitOnErr(Runner->getRunnableConfiguration( + Conf, NumRepetitions, LoopBodySize, *Repetitor, DumpObjectToDisk)); + AllResults.emplace_back( + ExitOnErr(Runner->runConfiguration(std::move(RC)))); } InstructionBenchmark &Result = AllResults.front(); -- 2.7.4