summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
blob: 77683572da69abae83d452fde9d68466ff7f300b (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
//===-- llvm-exegesis.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Measures execution properties (latencies/uops) of an instruction.
///
//===----------------------------------------------------------------------===//

#include "lib/BenchmarkResult.h"
#include "lib/BenchmarkRunner.h"
#include "lib/Latency.h"
#include "lib/LlvmState.h"
#include "lib/PerfHelper.h"
#include "lib/Uops.h"
#include "lib/X86.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include <algorithm>
#include <random>
#include <string>
#include <unordered_map>

static llvm::cl::opt<unsigned>
    OpcodeIndex("opcode-index", llvm::cl::desc("opcode to measure, by index"),
                llvm::cl::init(0));

static llvm::cl::opt<std::string>
    OpcodeName("opcode-name", llvm::cl::desc("opcode to measure, by name"),
               llvm::cl::init(""));

enum class BenchmarkModeE { Latency, Uops };
static llvm::cl::opt<BenchmarkModeE>
    BenchmarkMode("benchmark-mode", llvm::cl::desc("the benchmark mode to run"),
                  llvm::cl::values(clEnumValN(BenchmarkModeE::Latency,
                                              "latency", "Instruction Latency"),
                                   clEnumValN(BenchmarkModeE::Uops, "uops",
                                              "Uop Decomposition")));

static llvm::cl::opt<unsigned>
    NumRepetitions("num-repetitions",
                   llvm::cl::desc("number of time to repeat the asm snippet"),
                   llvm::cl::init(10000));

namespace exegesis {

void main() {
  if (OpcodeName.empty() == (OpcodeIndex == 0)) {
    llvm::report_fatal_error(
        "please provide one and only one of 'opcode-index' or 'opcode-name'");
  }

  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();

  // FIXME: Target-specific filter.
  X86Filter Filter;

  const LLVMState State;

  if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo())
    llvm::report_fatal_error("sched model is missing extra processor info!");

  unsigned Opcode = OpcodeIndex;
  if (Opcode == 0) {
    // Resolve opcode name -> opcode.
    for (unsigned I = 0, E = State.getInstrInfo().getNumOpcodes(); I < E; ++I) {
      if (State.getInstrInfo().getName(I) == OpcodeName) {
        Opcode = I;
        break;
      }
    }
    if (Opcode == 0) {
      llvm::report_fatal_error(
          llvm::Twine("unknown opcode ").concat(OpcodeName));
    }
  }

  std::unique_ptr<BenchmarkRunner> Runner;
  switch (BenchmarkMode) {
  case BenchmarkModeE::Latency:
    Runner = llvm::make_unique<LatencyBenchmarkRunner>();
    break;
  case BenchmarkModeE::Uops:
    Runner = llvm::make_unique<UopsBenchmarkRunner>();
    break;
  }

  Runner->run(State, Opcode, NumRepetitions > 0 ? NumRepetitions : 1, Filter)
      .writeYamlOrDie("-");
}

} // namespace exegesis

int main(int Argc, char **Argv) {
  llvm::cl::ParseCommandLineOptions(Argc, Argv, "");

  if (exegesis::pfm::pfmInitialize()) {
    llvm::errs() << "cannot initialize libpfm\n";
    return EXIT_FAILURE;
  }

  exegesis::main();

  exegesis::pfm::pfmTerminate();
  return EXIT_SUCCESS;
}
OpenPOWER on IntegriCloud