summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
blob: 845755ce97d0e67047b0b104481a76985e3dbc6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//===-- BenchmarkRunner.h ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines the abstract BenchmarkRunner class for measuring a certain execution
/// property of instructions (e.g. latency).
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H
#define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H

#include "Assembler.h"
#include "BenchmarkResult.h"
#include "LlvmState.h"
#include "MCInstrDescView.h"
#include "RegisterAliasing.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/Error.h"
#include <cstdlib>
#include <memory>
#include <vector>

namespace exegesis {

// A class representing failures that happened during Benchmark, they are used
// to report informations to the user.
class BenchmarkFailure : public llvm::StringError {
public:
  BenchmarkFailure(const llvm::Twine &S);
};

// A collection of instructions that are to be assembled, executed and measured.
struct BenchmarkConfiguration {
  // This code is run before the Snippet is iterated. Since it is part of the
  // measurement it should be as short as possible. It is usually used to setup
  // the content of the Registers.
  struct Setup {
    std::vector<unsigned> LiveIns; // The registers that are live on entry.
    std::vector<unsigned> RegsToDef;
  };
  Setup SnippetSetup;

  // The sequence of instructions that are to be repeated.
  std::vector<llvm::MCInst> Snippet;

  // Informations about how this configuration was built.
  std::string Info;
};

// Common code for all benchmark modes.
class BenchmarkRunner {
public:
  explicit BenchmarkRunner(const LLVMState &State,
                           InstructionBenchmark::ModeE Mode);

  virtual ~BenchmarkRunner();

  llvm::Expected<std::vector<InstructionBenchmark>>
  run(unsigned Opcode, unsigned NumRepetitions);

  // Given a snippet, computes which registers the setup code needs to define.
  std::vector<unsigned>
  computeRegsToDef(const std::vector<InstructionInstance> &Snippet) const;

  // Scratch space to run instructions that touch memory.
  struct ScratchSpace {
    static constexpr const size_t kAlignment = 1024;
    static constexpr const size_t kSize = 1 << 20; // 1MB.
    ScratchSpace()
        : UnalignedPtr(llvm::make_unique<char[]>(kSize + kAlignment)),
          AlignedPtr(
              UnalignedPtr.get() + kAlignment -
              (reinterpret_cast<intptr_t>(UnalignedPtr.get()) % kAlignment)) {}
    char *ptr() const { return AlignedPtr; }
    void clear() { std::memset(ptr(), 0, kSize); }

  private:
    const std::unique_ptr<char[]> UnalignedPtr;
    char *const AlignedPtr;
  };

protected:
  const LLVMState &State;
  const RegisterAliasingTrackerCache RATC;

  // Generates a single instruction prototype that has a self-dependency.
  llvm::Expected<SnippetPrototype>
  generateSelfAliasingPrototype(const Instruction &Instr) const;
  // Generates a single instruction prototype without assignment constraints.
  llvm::Expected<SnippetPrototype>
  generateUnconstrainedPrototype(const Instruction &Instr,
                                 llvm::StringRef Msg) const;

private:
  // API to be implemented by subclasses.
  virtual llvm::Expected<SnippetPrototype>
  generatePrototype(unsigned Opcode) const = 0;

  virtual std::vector<BenchmarkMeasure>
  runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
                  const unsigned NumRepetitions) const = 0;

  // Internal helpers.
  InstructionBenchmark runOne(const BenchmarkConfiguration &Configuration,
                              unsigned Opcode, unsigned NumRepetitions) const;

  // Calls generatePrototype and expands the SnippetPrototype into one or more
  // BenchmarkConfiguration.
  llvm::Expected<std::vector<BenchmarkConfiguration>>
  generateConfigurations(unsigned Opcode) const;

  llvm::Expected<std::string>
  writeObjectFile(const BenchmarkConfiguration::Setup &Setup,
                  llvm::ArrayRef<llvm::MCInst> Code) const;

  const InstructionBenchmark::ModeE Mode;

  const std::unique_ptr<ScratchSpace> Scratch;
};

} // namespace exegesis

#endif // LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRUNNER_H
OpenPOWER on IntegriCloud