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) const; |
72 | |
73 | // Scratch space to run instructions that touch memory. |
74 | struct ScratchSpace { |
75 | static constexpr const size_t kAlignment = 1024; |
76 | static constexpr const size_t kSize = 1 << 20; // 1MB. |
77 | ScratchSpace() |
78 | : UnalignedPtr(std::make_unique<char[]>(num: kSize + kAlignment)), |
79 | AlignedPtr( |
80 | UnalignedPtr.get() + kAlignment - |
81 | (reinterpret_cast<intptr_t>(UnalignedPtr.get()) % kAlignment)) {} |
82 | char *ptr() const { return AlignedPtr; } |
83 | void clear() { std::memset(s: ptr(), c: 0, n: kSize); } |
84 | |
85 | private: |
86 | const std::unique_ptr<char[]> UnalignedPtr; |
87 | char *const AlignedPtr; |
88 | }; |
89 | |
90 | // A helper to measure counters while executing a function in a sandboxed |
91 | // context. |
92 | class FunctionExecutor { |
93 | public: |
94 | virtual ~FunctionExecutor(); |
95 | |
96 | Expected<SmallVector<int64_t, 4>> |
97 | runAndSample(const char *Counters, |
98 | ArrayRef<const char *> ValidationCounters, |
99 | SmallVectorImpl<int64_t> &ValidationCounterValues) const; |
100 | |
101 | protected: |
102 | static void |
103 | accumulateCounterValues(const SmallVectorImpl<int64_t> &NewValues, |
104 | SmallVectorImpl<int64_t> *Result); |
105 | virtual Expected<SmallVector<int64_t, 4>> |
106 | runWithCounter(StringRef CounterName, |
107 | ArrayRef<const char *> ValidationCounters, |
108 | SmallVectorImpl<int64_t> &ValidationCounterValues) const = 0; |
109 | }; |
110 | |
111 | protected: |
112 | const LLVMState &State; |
113 | const Benchmark::ModeE Mode; |
114 | const BenchmarkPhaseSelectorE BenchmarkPhaseSelector; |
115 | const ExecutionModeE ExecutionMode; |
116 | |
117 | SmallVector<ValidationEvent> ValidationCounters; |
118 | |
119 | Error |
120 | getValidationCountersToRun(SmallVector<const char *> &ValCountersToRun) const; |
121 | |
122 | private: |
123 | virtual Expected<std::vector<BenchmarkMeasure>> |
124 | runMeasurements(const FunctionExecutor &Executor) const = 0; |
125 | |
126 | Expected<SmallString<0>> |
127 | assembleSnippet(const BenchmarkCode &BC, const SnippetRepetitor &Repetitor, |
128 | unsigned MinInstructions, unsigned LoopBodySize, |
129 | bool GenerateMemoryInstructions) const; |
130 | |
131 | Expected<std::string> writeObjectFile(StringRef Buffer, |
132 | StringRef FileName) const; |
133 | |
134 | const std::unique_ptr<ScratchSpace> Scratch; |
135 | |
136 | Expected<std::unique_ptr<FunctionExecutor>> |
137 | createFunctionExecutor(object::OwningBinary<object::ObjectFile> Obj, |
138 | const BenchmarkKey &Key) const; |
139 | }; |
140 | |
141 | } // namespace exegesis |
142 | } // namespace llvm |
143 | |
144 | #endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H |
145 | |