1 //===-- BenchmarkRunner.h ---------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// Defines the abstract BenchmarkRunner class for measuring a certain execution 11 /// property of instructions (e.g. latency). 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H 16 #define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H 17 18 #include "Assembler.h" 19 #include "BenchmarkCode.h" 20 #include "BenchmarkResult.h" 21 #include "LlvmState.h" 22 #include "MCInstrDescView.h" 23 #include "SnippetRepetitor.h" 24 #include "llvm/ADT/SmallVector.h" 25 #include "llvm/MC/MCInst.h" 26 #include "llvm/Support/Error.h" 27 #include <cstdlib> 28 #include <memory> 29 #include <vector> 30 31 namespace llvm { 32 namespace exegesis { 33 34 // Common code for all benchmark modes. 35 class BenchmarkRunner { 36 public: 37 enum ExecutionModeE { InProcess, SubProcess }; 38 39 explicit BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode, 40 BenchmarkPhaseSelectorE BenchmarkPhaseSelector, 41 ExecutionModeE ExecutionMode, 42 ArrayRef<ValidationEvent> ValCounters); 43 44 virtual ~BenchmarkRunner(); 45 46 class RunnableConfiguration { 47 friend class BenchmarkRunner; 48 49 public: 50 ~RunnableConfiguration() = default; 51 RunnableConfiguration(RunnableConfiguration &&) = default; 52 53 RunnableConfiguration(const RunnableConfiguration &) = delete; 54 RunnableConfiguration &operator=(RunnableConfiguration &&) = delete; 55 RunnableConfiguration &operator=(const RunnableConfiguration &) = delete; 56 57 private: 58 RunnableConfiguration() = default; 59 60 Benchmark BenchmarkResult; 61 object::OwningBinary<object::ObjectFile> ObjectFile; 62 }; 63 64 Expected<RunnableConfiguration> 65 getRunnableConfiguration(const BenchmarkCode &Configuration, 66 unsigned MinInstructions, unsigned LoopUnrollFactor, 67 const SnippetRepetitor &Repetitor) const; 68 69 std::pair<Error, Benchmark> 70 runConfiguration(RunnableConfiguration &&RC, 71 const std::optional<StringRef> &DumpFile, 72 std::optional<int> BenchmarkProcessCPU) const; 73 74 // Scratch space to run instructions that touch memory. 75 struct ScratchSpace { 76 static constexpr const size_t kAlignment = 1024; 77 static constexpr const size_t kSize = 1 << 20; // 1MB. 78 ScratchSpace() 79 : UnalignedPtr(std::make_unique<char[]>(kSize + kAlignment)), 80 AlignedPtr( 81 UnalignedPtr.get() + kAlignment - 82 (reinterpret_cast<intptr_t>(UnalignedPtr.get()) % kAlignment)) {} 83 char *ptr() const { return AlignedPtr; } 84 void clear() { std::memset(ptr(), 0, kSize); } 85 86 private: 87 const std::unique_ptr<char[]> UnalignedPtr; 88 char *const AlignedPtr; 89 }; 90 91 // A helper to measure counters while executing a function in a sandboxed 92 // context. 93 class FunctionExecutor { 94 public: 95 virtual ~FunctionExecutor(); 96 97 Expected<SmallVector<int64_t, 4>> 98 runAndSample(const char *Counters, 99 ArrayRef<const char *> ValidationCounters, 100 SmallVectorImpl<int64_t> &ValidationCounterValues) const; 101 102 protected: 103 static void 104 accumulateCounterValues(const SmallVectorImpl<int64_t> &NewValues, 105 SmallVectorImpl<int64_t> *Result); 106 virtual Expected<SmallVector<int64_t, 4>> 107 runWithCounter(StringRef CounterName, 108 ArrayRef<const char *> ValidationCounters, 109 SmallVectorImpl<int64_t> &ValidationCounterValues) const = 0; 110 }; 111 112 protected: 113 const LLVMState &State; 114 const Benchmark::ModeE Mode; 115 const BenchmarkPhaseSelectorE BenchmarkPhaseSelector; 116 const ExecutionModeE ExecutionMode; 117 118 SmallVector<ValidationEvent> ValidationCounters; 119 120 Error 121 getValidationCountersToRun(SmallVector<const char *> &ValCountersToRun) const; 122 123 private: 124 virtual Expected<std::vector<BenchmarkMeasure>> 125 runMeasurements(const FunctionExecutor &Executor) const = 0; 126 127 Expected<SmallString<0>> 128 assembleSnippet(const BenchmarkCode &BC, const SnippetRepetitor &Repetitor, 129 unsigned MinInstructions, unsigned LoopBodySize, 130 bool GenerateMemoryInstructions) const; 131 132 Expected<std::string> writeObjectFile(StringRef Buffer, 133 StringRef FileName) const; 134 135 const std::unique_ptr<ScratchSpace> Scratch; 136 137 Expected<std::unique_ptr<FunctionExecutor>> 138 createFunctionExecutor(object::OwningBinary<object::ObjectFile> Obj, 139 const BenchmarkKey &Key, 140 std::optional<int> BenchmarkProcessCPU) const; 141 }; 142 143 } // namespace exegesis 144 } // namespace llvm 145 146 #endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H 147