Home | History | Annotate | Download | only in lib
      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 
     88   double avg() const {
     89     assert(NumValues);
     90     return SumValues / NumValues;
     91   }
     92   double min() const { return MinValue; }
     93   double max() const { return MaxValue; }
     94 
     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