1 //===-- BenchmarkResult.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 classes to represent measurements and serialize/deserialize them to 11 // Yaml. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 16 #define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 17 18 #include "LlvmState.h" 19 #include "RegisterValue.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/StringSet.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstBuilder.h" 25 #include "llvm/Support/YAMLTraits.h" 26 #include <limits> 27 #include <set> 28 #include <string> 29 #include <unordered_map> 30 #include <vector> 31 32 namespace llvm { 33 class Error; 34 35 namespace exegesis { 36 37 enum class BenchmarkPhaseSelectorE { 38 PrepareSnippet, 39 PrepareAndAssembleSnippet, 40 AssembleMeasuredCode, 41 Measure, 42 }; 43 44 enum class InstructionBenchmarkFilter { All, RegOnly, WithMem }; 45 46 struct InstructionBenchmarkKey { 47 // The LLVM opcode name. 48 std::vector<MCInst> Instructions; 49 // The initial values of the registers. 50 std::vector<RegisterValue> RegisterInitialValues; 51 // An opaque configuration, that can be used to separate several benchmarks of 52 // the same instruction under different configurations. 53 std::string Config; 54 }; 55 56 struct BenchmarkMeasure { 57 // A helper to create an unscaled BenchmarkMeasure. CreateBenchmarkMeasure58 static BenchmarkMeasure Create(std::string Key, double Value) { 59 return {Key, Value, Value}; 60 } 61 std::string Key; 62 // This is the per-instruction value, i.e. measured quantity scaled per 63 // instruction. 64 double PerInstructionValue; 65 // This is the per-snippet value, i.e. measured quantity for one repetition of 66 // the whole snippet. 67 double PerSnippetValue; 68 }; 69 70 // The result of an instruction benchmark. 71 struct InstructionBenchmark { 72 InstructionBenchmarkKey Key; 73 enum ModeE { Unknown, Latency, Uops, InverseThroughput }; 74 ModeE Mode; 75 std::string CpuName; 76 std::string LLVMTriple; 77 // Which instruction is being benchmarked here? keyInstructionInstructionBenchmark78 const MCInst &keyInstruction() const { return Key.Instructions[0]; } 79 // The number of instructions inside the repeated snippet. For example, if a 80 // snippet of 3 instructions is repeated 4 times, this is 12. 81 unsigned NumRepetitions = 0; 82 enum RepetitionModeE { Duplicate, Loop, AggregateMin }; 83 // Note that measurements are per instruction. 84 std::vector<BenchmarkMeasure> Measurements; 85 std::string Error; 86 std::string Info; 87 std::vector<uint8_t> AssembledSnippet; 88 // How to aggregate measurements. 89 enum ResultAggregationModeE { Min, Max, Mean, MinVariance }; 90 91 InstructionBenchmark() = default; 92 InstructionBenchmark(InstructionBenchmark &&) = default; 93 94 InstructionBenchmark(const InstructionBenchmark &) = delete; 95 InstructionBenchmark &operator=(const InstructionBenchmark &) = delete; 96 InstructionBenchmark &operator=(InstructionBenchmark &&) = delete; 97 98 // Read functions. 99 static Expected<InstructionBenchmark> readYaml(const LLVMState &State, 100 MemoryBufferRef Buffer); 101 102 static Expected<std::vector<InstructionBenchmark>> 103 readYamls(const LLVMState &State, MemoryBufferRef Buffer); 104 105 // Given a set of serialized instruction benchmarks, returns the set of 106 // triples and CPUs that appear in the list of benchmarks. 107 struct TripleAndCpu { 108 std::string LLVMTriple; 109 std::string CpuName; 110 bool operator<(const TripleAndCpu &O) const { 111 return std::tie(LLVMTriple, CpuName) < std::tie(O.LLVMTriple, O.CpuName); 112 } 113 }; 114 static Expected<std::set<TripleAndCpu>> 115 readTriplesAndCpusFromYamls(MemoryBufferRef Buffer); 116 117 class Error readYamlFrom(const LLVMState &State, StringRef InputContent); 118 119 // Write functions, non-const because of YAML traits. 120 // NOTE: we intentionally do *NOT* have a variant of this function taking 121 // filename, because it's behaviour is bugprone with regards to 122 // accidentally using it more than once and overriding previous YAML. 123 class Error writeYamlTo(const LLVMState &State, raw_ostream &S); 124 }; 125 126 bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B); 127 128 //------------------------------------------------------------------------------ 129 // Utilities to work with Benchmark measures. 130 131 // A class that measures stats over benchmark measures. 132 class PerInstructionStats { 133 public: 134 void push(const BenchmarkMeasure &BM); 135 avg()136 double avg() const { 137 assert(NumValues); 138 return SumValues / NumValues; 139 } min()140 double min() const { return MinValue; } max()141 double max() const { return MaxValue; } 142 key()143 const std::string &key() const { return Key; } 144 145 private: 146 std::string Key; 147 double SumValues = 0.0; 148 int NumValues = 0; 149 double MaxValue = std::numeric_limits<double>::min(); 150 double MinValue = std::numeric_limits<double>::max(); 151 }; 152 153 } // namespace exegesis 154 } // namespace llvm 155 156 #endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 157