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 @@ -34,9 +34,12 @@ // Common code for all benchmark modes. class BenchmarkRunner { public: + enum ExecutionModeE { InProcess }; + explicit BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode, - BenchmarkPhaseSelectorE BenchmarkPhaseSelector); + BenchmarkPhaseSelectorE BenchmarkPhaseSelector, + ExecutionModeE ExecutionMode); virtual ~BenchmarkRunner(); @@ -105,6 +108,7 @@ const LLVMState &State; const Benchmark::ModeE Mode; const BenchmarkPhaseSelectorE BenchmarkPhaseSelector; + const ExecutionModeE ExecutionMode; private: virtual Expected> @@ -119,6 +123,10 @@ StringRef FileName) const; const std::unique_ptr Scratch; + + Expected> + getFunctionExecutor(object::OwningBinary Obj, + const BenchmarkKey &Key) const; }; } // namespace exegesis 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,9 +31,10 @@ BenchmarkRunner::BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode, - BenchmarkPhaseSelectorE BenchmarkPhaseSelector) + BenchmarkPhaseSelectorE BenchmarkPhaseSelector, + ExecutionModeE ExecutionMode) : State(State), Mode(Mode), BenchmarkPhaseSelector(BenchmarkPhaseSelector), - Scratch(std::make_unique()) {} + ExecutionMode(ExecutionMode), Scratch(std::make_unique()) {} BenchmarkRunner::~BenchmarkRunner() = default; @@ -66,9 +67,9 @@ } namespace { -class FunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor { +class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor { public: - FunctionExecutorImpl(const LLVMState &State, + InProcessFunctionExecutorImpl(const LLVMState &State, object::OwningBinary Obj, BenchmarkRunner::ScratchSpace *Scratch) : State(State), Function(State.createTargetMachine(), std::move(Obj)), @@ -193,6 +194,18 @@ return std::move(RC); } +Expected> +BenchmarkRunner::getFunctionExecutor( + object::OwningBinary ObjectFile, + const BenchmarkKey &Key) const { + switch (ExecutionMode) { + case ExecutionModeE::InProcess: + return std::make_unique( + State, std::move(ObjectFile), Scratch.get()); + } + llvm_unreachable("ExecutionMode is outside expected range"); +} + Expected BenchmarkRunner::runConfiguration( RunnableConfiguration &&RC, const std::optional &DumpFile) const { @@ -216,9 +229,12 @@ return std::move(InstrBenchmark); } - const FunctionExecutorImpl Executor(State, std::move(ObjectFile), - Scratch.get()); - auto NewMeasurements = runMeasurements(Executor); + Expected> Executor = + getFunctionExecutor(std::move(ObjectFile), RC.InstrBenchmark.Key); + if (!Executor) + return Executor.takeError(); + auto NewMeasurements = runMeasurements(**Executor); + if (Error E = NewMeasurements.takeError()) { if (!E.isA()) return std::move(E); 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 @@ -24,7 +24,8 @@ LatencyBenchmarkRunner( const LLVMState &State, Benchmark::ModeE Mode, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAggMode); + Benchmark::ResultAggregationModeE ResultAggMode, + ExecutionModeE ExecutionMode); ~LatencyBenchmarkRunner() override; private: 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 @@ -21,10 +21,9 @@ LatencyBenchmarkRunner::LatencyBenchmarkRunner( const LLVMState &State, Benchmark::ModeE Mode, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAgg) - : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector) { - assert((Mode == Benchmark::Latency || - Mode == Benchmark::InverseThroughput) && + Benchmark::ResultAggregationModeE ResultAgg, ExecutionModeE ExecutionMode) + : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector, ExecutionMode) { + assert((Mode == Benchmark::Latency || Mode == Benchmark::InverseThroughput) && "invalid mode"); ResultAggMode = ResultAgg; } 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 @@ -162,8 +162,8 @@ Expected> createBenchmarkRunner( Benchmark::ModeE Mode, const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAggMode = - Benchmark::Min) const; + BenchmarkRunner::ExecutionModeE ExecutionMode, + Benchmark::ResultAggregationModeE ResultAggMode = Benchmark::Min) const; // Returns the ExegesisTarget for the given triple or nullptr if the target // does not exist. @@ -205,10 +205,12 @@ std::unique_ptr virtual createLatencyBenchmarkRunner( const LLVMState &State, Benchmark::ModeE Mode, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAggMode) const; + Benchmark::ResultAggregationModeE ResultAggMode, + BenchmarkRunner::ExecutionModeE ExecutionMode) const; std::unique_ptr virtual createUopsBenchmarkRunner( const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAggMode) const; + Benchmark::ResultAggregationModeE ResultAggMode, + BenchmarkRunner::ExecutionModeE ExecutionMode) const; const ExegesisTarget *Next = nullptr; const ArrayRef CpuPfmCounters; 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 @@ -76,6 +76,7 @@ ExegesisTarget::createBenchmarkRunner( Benchmark::ModeE Mode, const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, + BenchmarkRunner::ExecutionModeE ExecutionMode, Benchmark::ResultAggregationModeE ResultAggMode) const { PfmCountersInfo PfmCounters = State.getPfmCounters(); switch (Mode) { @@ -98,7 +99,7 @@ "the kernel for real event counts.")); } return createLatencyBenchmarkRunner(State, Mode, BenchmarkPhaseSelector, - ResultAggMode); + ResultAggMode, ExecutionMode); case Benchmark::Uops: if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure && !PfmCounters.UopsCounter && !PfmCounters.IssueCounters) @@ -108,7 +109,7 @@ "benchmarking or --use-dummy-perf-counters to not query the kernel " "for real event counts."); return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector, - ResultAggMode); + ResultAggMode, ExecutionMode); } return nullptr; } @@ -126,15 +127,18 @@ std::unique_ptr ExegesisTarget::createLatencyBenchmarkRunner( const LLVMState &State, Benchmark::ModeE Mode, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE ResultAggMode) const { + Benchmark::ResultAggregationModeE ResultAggMode, + BenchmarkRunner::ExecutionModeE ExecutionMode) const { return std::make_unique( - State, Mode, BenchmarkPhaseSelector, ResultAggMode); + State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode); } std::unique_ptr ExegesisTarget::createUopsBenchmarkRunner( const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, - Benchmark::ResultAggregationModeE /*unused*/) const { - return std::make_unique(State, BenchmarkPhaseSelector); + Benchmark::ResultAggregationModeE /*unused*/, + BenchmarkRunner::ExecutionModeE ExecutionMode) const { + return std::make_unique(State, BenchmarkPhaseSelector, + ExecutionMode); } static_assert(std::is_trivial_v, 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 @@ -22,9 +22,10 @@ class UopsBenchmarkRunner : public BenchmarkRunner { public: UopsBenchmarkRunner(const LLVMState &State, - BenchmarkPhaseSelectorE BenchmarkPhaseSelector) - : BenchmarkRunner(State, Benchmark::Uops, - BenchmarkPhaseSelector) {} + BenchmarkPhaseSelectorE BenchmarkPhaseSelector, + ExecutionModeE ExecutionMode) + : BenchmarkRunner(State, Benchmark::Uops, BenchmarkPhaseSelector, + ExecutionMode) {} ~UopsBenchmarkRunner() override; static constexpr const size_t kMinNumDifferentAddresses = 6; 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 @@ -248,6 +248,15 @@ "and prints a message to access it"), cl::ValueOptional, cl::cat(BenchmarkOptions)); +static cl::opt ExecutionMode( + "execution-mode", + cl::desc("Selects the execution mode to use for running snippets"), + cl::cat(BenchmarkOptions), + cl::values(clEnumValN(BenchmarkRunner::ExecutionModeE::InProcess, + "inprocess", + "Executes the snippets within the same process")), + cl::init(BenchmarkRunner::ExecutionModeE::InProcess)); + static ExitOnError ExitOnErr("llvm-exegesis error: "); // Helper function that logs the error(s) and exits. @@ -459,7 +468,8 @@ const std::unique_ptr Runner = ExitOnErr(State.getExegesisTarget().createBenchmarkRunner( - BenchmarkMode, State, BenchmarkPhaseSelector, ResultAggMode)); + BenchmarkMode, State, BenchmarkPhaseSelector, ExecutionMode, + ResultAggMode)); if (!Runner) { ExitWithError("cannot create benchmark runner"); }