• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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