1 //===-- BenchmarkResult.h ---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// Defines classes to represent measurements and serialize/deserialize them to
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
16 #define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
18 #include "LlvmState.h"
19 #include "RegisterValue.h"
20 #include "ValidationEvent.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstBuilder.h"
24 #include "llvm/Support/YAMLTraits.h"
28 #include <unordered_map>
36 enum class BenchmarkPhaseSelectorE
{
38 PrepareAndAssembleSnippet
,
43 enum class BenchmarkFilter
{ All
, RegOnly
, WithMem
};
46 // The arbitrary bit width constant that defines the value.
48 // The size of the value in bytes.
50 // The index of the memory value.
54 struct MemoryMapping
{
55 // The address to place the mapping at.
57 // The name of the value that should be mapped.
58 std::string MemoryValueName
;
62 // The LLVM opcode name.
63 std::vector
<MCInst
> Instructions
;
64 // The initial values of the registers.
65 std::vector
<RegisterValue
> RegisterInitialValues
;
66 // The memory values that can be mapped into the execution context of the
68 std::unordered_map
<std::string
, MemoryValue
> MemoryValues
;
69 // The memory mappings that the snippet can access.
70 std::vector
<MemoryMapping
> MemoryMappings
;
71 // An opaque configuration, that can be used to separate several benchmarks of
72 // the same instruction under different configurations.
74 // The address that the snippet should be loaded in at if the execution mode
75 // being used supports it.
76 uintptr_t SnippetAddress
= 0;
77 // The register that should be used to hold the loop counter.
78 unsigned LoopRegister
;
81 struct BenchmarkMeasure
{
82 // A helper to create an unscaled BenchmarkMeasure.
83 static BenchmarkMeasure
84 Create(std::string Key
, double Value
,
85 std::map
<ValidationEvent
, int64_t> ValCounters
) {
86 return {Key
, Value
, Value
, Value
, ValCounters
};
89 // This is the per-instruction value, i.e. measured quantity scaled per
91 double PerInstructionValue
;
92 // This is the per-snippet value, i.e. measured quantity for one repetition of
94 double PerSnippetValue
;
95 // This is the raw value collected from the full execution.
97 // These are the validation counter values.
98 std::map
<ValidationEvent
, int64_t> ValidationCounters
;
101 // The result of an instruction benchmark.
104 enum ModeE
{ Unknown
, Latency
, Uops
, InverseThroughput
};
107 std::string LLVMTriple
;
108 // Which instruction is being benchmarked here?
109 const MCInst
&keyInstruction() const { return Key
.Instructions
[0]; }
110 // The number of instructions inside the repeated snippet. For example, if a
111 // snippet of 3 instructions is repeated 4 times, this is 12.
112 unsigned MinInstructions
= 0;
113 enum RepetitionModeE
{
120 // Note that measurements are per instruction.
121 std::vector
<BenchmarkMeasure
> Measurements
;
124 std::vector
<uint8_t> AssembledSnippet
;
125 // How to aggregate measurements.
126 enum ResultAggregationModeE
{ Min
, Max
, Mean
, MinVariance
};
128 Benchmark() = default;
129 Benchmark(Benchmark
&&) = default;
131 Benchmark(const Benchmark
&) = delete;
132 Benchmark
&operator=(const Benchmark
&) = delete;
133 Benchmark
&operator=(Benchmark
&&) = delete;
136 static Expected
<Benchmark
> readYaml(const LLVMState
&State
,
137 MemoryBufferRef Buffer
);
139 static Expected
<std::vector
<Benchmark
>>
140 readYamls(const LLVMState
&State
, MemoryBufferRef Buffer
);
142 // Given a set of serialized instruction benchmarks, returns the set of
143 // triples and CPUs that appear in the list of benchmarks.
144 struct TripleAndCpu
{
145 std::string LLVMTriple
;
147 bool operator<(const TripleAndCpu
&O
) const {
148 return std::tie(LLVMTriple
, CpuName
) < std::tie(O
.LLVMTriple
, O
.CpuName
);
151 static Expected
<std::set
<TripleAndCpu
>>
152 readTriplesAndCpusFromYamls(MemoryBufferRef Buffer
);
154 class Error
readYamlFrom(const LLVMState
&State
, StringRef InputContent
);
156 // Write functions, non-const because of YAML traits.
157 // NOTE: we intentionally do *NOT* have a variant of this function taking
158 // filename, because it's behaviour is bugprone with regards to
159 // accidentally using it more than once and overriding previous YAML.
160 class Error
writeYamlTo(const LLVMState
&State
, raw_ostream
&S
);
163 bool operator==(const BenchmarkMeasure
&A
, const BenchmarkMeasure
&B
);
165 //------------------------------------------------------------------------------
166 // Utilities to work with Benchmark measures.
168 // A class that measures stats over benchmark measures.
169 class PerInstructionStats
{
171 void push(const BenchmarkMeasure
&BM
);
175 return SumValues
/ NumValues
;
177 double min() const { return MinValue
; }
178 double max() const { return MaxValue
; }
180 const std::string
&key() const { return Key
; }
184 double SumValues
= 0.0;
186 double MaxValue
= std::numeric_limits
<double>::min();
187 double MinValue
= std::numeric_limits
<double>::max();
190 } // namespace exegesis
193 #endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H