blob: c9dfe840f4e8fba0331b39feb46867bd67e9d1e1 [file] [log] [blame]
Clement Courbetac74acd2018-04-04 11:37:06 +00001//===-- llvm-exegesis.cpp ---------------------------------------*- 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/// Measures execution properties (latencies/uops) of an instruction.
12///
13//===----------------------------------------------------------------------===//
14
15#include "lib/BenchmarkResult.h"
16#include "lib/BenchmarkRunner.h"
17#include "lib/Latency.h"
18#include "lib/LlvmState.h"
19#include "lib/PerfHelper.h"
20#include "lib/Uops.h"
21#include "lib/X86.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/ADT/Twine.h"
24#include "llvm/MC/MCInstBuilder.h"
25#include "llvm/MC/MCRegisterInfo.h"
26#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/Path.h"
28#include "llvm/Support/TargetSelect.h"
29#include <algorithm>
30#include <random>
31#include <string>
32#include <unordered_map>
33
34static llvm::cl::opt<unsigned>
35 OpcodeIndex("opcode-index", llvm::cl::desc("opcode to measure, by index"),
36 llvm::cl::init(0));
37
38static llvm::cl::opt<std::string>
39 OpcodeName("opcode-name", llvm::cl::desc("opcode to measure, by name"),
40 llvm::cl::init(""));
41
42enum class BenchmarkModeE { Latency, Uops };
43static llvm::cl::opt<BenchmarkModeE>
44 BenchmarkMode("benchmark-mode", llvm::cl::desc("the benchmark mode to run"),
45 llvm::cl::values(clEnumValN(BenchmarkModeE::Latency,
46 "latency", "Instruction Latency"),
47 clEnumValN(BenchmarkModeE::Uops, "uops",
48 "Uop Decomposition")));
49
50static llvm::cl::opt<unsigned>
51 NumRepetitions("num-repetitions",
52 llvm::cl::desc("number of time to repeat the asm snippet"),
53 llvm::cl::init(10000));
54
55namespace exegesis {
56
57void main() {
58 if (OpcodeName.empty() == (OpcodeIndex == 0)) {
59 llvm::report_fatal_error(
60 "please provide one and only one of 'opcode-index' or 'opcode-name' ");
61 }
62
63 llvm::InitializeNativeTarget();
64 llvm::InitializeNativeTargetAsmPrinter();
65
66 // FIXME: Target-specific filter.
67 X86Filter Filter;
68
69 const LLVMState State;
70
71 unsigned Opcode = OpcodeIndex;
72 if (Opcode == 0) {
73 // Resolve opcode name -> opcode.
74 for (unsigned I = 0, E = State.getInstrInfo().getNumOpcodes(); I < E; ++I) {
75 if (State.getInstrInfo().getName(I) == OpcodeName) {
76 Opcode = I;
77 break;
78 }
79 }
80 if (Opcode == 0) {
81 llvm::report_fatal_error(
82 llvm::Twine("unknown opcode ").concat(OpcodeName));
83 }
84 }
85
86 std::unique_ptr<BenchmarkRunner> Runner;
87 switch (BenchmarkMode) {
88 case BenchmarkModeE::Latency:
89 Runner = llvm::make_unique<LatencyBenchmarkRunner>();
90 break;
91 case BenchmarkModeE::Uops:
92 Runner = llvm::make_unique<UopsBenchmarkRunner>();
93 break;
94 }
95
96 Runner->run(State, Opcode, NumRepetitions > 0 ? NumRepetitions : 1, Filter)
97 .writeYamlOrDie("-");
98}
99
100} // namespace exegesis
101
102int main(int Argc, char **Argv) {
103 llvm::cl::ParseCommandLineOptions(Argc, Argv, "");
104
105 if (exegesis::pfm::pfmInitialize()) {
106 llvm::errs() << "cannot initialize libpfm\n";
107 return EXIT_FAILURE;
108 }
109
110 exegesis::main();
111
112 exegesis::pfm::pfmTerminate();
113 return EXIT_SUCCESS;
114}