1 //===-- BenchmarkResult.h ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// Defines classes to represent measurements and serialize/deserialize them to 12 // Yaml. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 17 #define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 18 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/MC/MCInstBuilder.h" 23 #include "llvm/Support/YAMLTraits.h" 24 #include <limits> 25 #include <string> 26 #include <unordered_map> 27 #include <vector> 28 29 namespace exegesis { 30 31 struct BenchmarkResultContext; // Forward declaration. 32 33 struct InstructionBenchmarkKey { 34 // The LLVM opcode name. 35 std::vector<llvm::MCInst> Instructions; 36 // An opaque configuration, that can be used to separate several benchmarks of 37 // the same instruction under different configurations. 38 std::string Config; 39 }; 40 41 struct BenchmarkMeasure { 42 std::string Key; 43 double Value; 44 std::string DebugString; 45 }; 46 47 // The result of an instruction benchmark. 48 struct InstructionBenchmark { 49 InstructionBenchmarkKey Key; 50 enum ModeE { Unknown, Latency, Uops }; 51 ModeE Mode; 52 std::string CpuName; 53 std::string LLVMTriple; 54 // The number of instructions inside the repeated snippet. For example, if a 55 // snippet of 3 instructions is repeated 4 times, this is 12. 56 int NumRepetitions = 0; 57 // Note that measurements are per instruction. 58 std::vector<BenchmarkMeasure> Measurements; 59 std::string Error; 60 std::string Info; 61 std::vector<uint8_t> AssembledSnippet; 62 63 // Read functions. 64 static llvm::Expected<InstructionBenchmark> 65 readYaml(const BenchmarkResultContext &Context, llvm::StringRef Filename); 66 67 static llvm::Expected<std::vector<InstructionBenchmark>> 68 readYamls(const BenchmarkResultContext &Context, llvm::StringRef Filename); 69 70 void readYamlFrom(const BenchmarkResultContext &Context, 71 llvm::StringRef InputContent); 72 73 // Write functions, non-const because of YAML traits. 74 void writeYamlTo(const BenchmarkResultContext &Context, llvm::raw_ostream &S); 75 76 llvm::Error writeYaml(const BenchmarkResultContext &Context, 77 const llvm::StringRef Filename); 78 }; 79 80 //------------------------------------------------------------------------------ 81 // Utilities to work with Benchmark measures. 82 83 // A class that measures stats over benchmark measures. 84 class BenchmarkMeasureStats { 85 public: 86 void push(const BenchmarkMeasure &BM); 87 avg()88 double avg() const { 89 assert(NumValues); 90 return SumValues / NumValues; 91 } min()92 double min() const { return MinValue; } max()93 double max() const { return MaxValue; } 94 key()95 const std::string &key() const { return Key; } 96 97 private: 98 std::string Key; 99 double SumValues = 0.0; 100 int NumValues = 0; 101 double MaxValue = std::numeric_limits<double>::min(); 102 double MinValue = std::numeric_limits<double>::max(); 103 }; 104 105 // This context is used when de/serializing InstructionBenchmark to guarantee 106 // that Registers and Instructions are human readable and preserved accross 107 // different versions of LLVM. 108 struct BenchmarkResultContext { 109 BenchmarkResultContext() = default; 110 BenchmarkResultContext(BenchmarkResultContext &&) = default; 111 BenchmarkResultContext &operator=(BenchmarkResultContext &&) = default; 112 BenchmarkResultContext(const BenchmarkResultContext &) = delete; 113 BenchmarkResultContext &operator=(const BenchmarkResultContext &) = delete; 114 115 // Populate Registers and Instruction mapping. 116 void addRegEntry(unsigned RegNo, llvm::StringRef Name); 117 void addInstrEntry(unsigned Opcode, llvm::StringRef Name); 118 119 // Register accessors. 120 llvm::StringRef getRegName(unsigned RegNo) const; 121 unsigned getRegNo(llvm::StringRef Name) const; // 0 is not found. 122 123 // Instruction accessors. 124 llvm::StringRef getInstrName(unsigned Opcode) const; 125 unsigned getInstrOpcode(llvm::StringRef Name) const; // 0 is not found. 126 127 private: 128 // Ideally we would like to use MCRegisterInfo and MCInstrInfo but doing so 129 // would make testing harder, instead we create a mapping that we can easily 130 // populate. 131 std::unordered_map<unsigned, llvm::StringRef> InstrOpcodeToName; 132 std::unordered_map<unsigned, llvm::StringRef> RegNoToName; 133 llvm::StringMap<unsigned> InstrNameToOpcode; 134 llvm::StringMap<unsigned> RegNameToNo; 135 }; 136 137 } // namespace exegesis 138 139 #endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H 140