blob: 1d8b34f10324123d61308f1486e317f7467992ba [file] [log] [blame]
Clement Courbetac74acd2018-04-04 11:37:06 +00001//===-- BenchmarkRunner.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
Clement Courbet0e69e2d2018-05-17 10:52:18 +000010#include <array>
11#include <string>
12
13#include "Assembler.h"
Clement Courbetac74acd2018-04-04 11:37:06 +000014#include "BenchmarkRunner.h"
Clement Courbet0e69e2d2018-05-17 10:52:18 +000015#include "MCInstrDescView.h"
Clement Courbetac74acd2018-04-04 11:37:06 +000016#include "llvm/ADT/StringExtras.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/Twine.h"
Clement Courbet0e69e2d2018-05-17 10:52:18 +000019#include "llvm/Support/FileSystem.h"
20#include "llvm/Support/FormatVariadic.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/Program.h"
Clement Courbetac74acd2018-04-04 11:37:06 +000023
24namespace exegesis {
25
26BenchmarkRunner::InstructionFilter::~InstructionFilter() = default;
Clement Courbet0e69e2d2018-05-17 10:52:18 +000027BenchmarkRunner::BenchmarkRunner(const LLVMState &State)
28 : State(State), MCInstrInfo(State.getInstrInfo()),
29 MCRegisterInfo(State.getRegInfo()),
30 RATC(MCRegisterInfo,
31 getFunctionReservedRegs(*State.createTargetMachine())) {}
Clement Courbetac74acd2018-04-04 11:37:06 +000032BenchmarkRunner::~BenchmarkRunner() = default;
33
Clement Courbet0e69e2d2018-05-17 10:52:18 +000034InstructionBenchmark BenchmarkRunner::run(unsigned Opcode,
35 const InstructionFilter &Filter,
36 unsigned NumRepetitions) {
Clement Courbetac74acd2018-04-04 11:37:06 +000037 InstructionBenchmark InstrBenchmark;
38
Clement Courbeta66bfaa42018-05-15 13:07:05 +000039 InstrBenchmark.Key.OpcodeName = State.getInstrInfo().getName(Opcode);
Clement Courbet62b34fa2018-06-06 09:42:36 +000040 InstrBenchmark.Mode = getMode();
Clement Courbetac74acd2018-04-04 11:37:06 +000041 InstrBenchmark.CpuName = State.getCpuName();
42 InstrBenchmark.LLVMTriple = State.getTriple();
43 InstrBenchmark.NumRepetitions = NumRepetitions;
44
45 // Ignore instructions that we cannot run.
46 if (State.getInstrInfo().get(Opcode).isPseudo()) {
47 InstrBenchmark.Error = "Unsupported opcode: isPseudo";
48 return InstrBenchmark;
49 }
50 if (llvm::Error E = Filter.shouldRun(State, Opcode)) {
51 InstrBenchmark.Error = llvm::toString(std::move(E));
52 return InstrBenchmark;
53 }
Clement Courbet0e69e2d2018-05-17 10:52:18 +000054 llvm::raw_string_ostream InfoStream(InstrBenchmark.Info);
55 llvm::Expected<std::vector<llvm::MCInst>> SnippetOrError =
56 createSnippet(RATC, Opcode, InfoStream);
57 if (llvm::Error E = SnippetOrError.takeError()) {
58 InstrBenchmark.Error = llvm::toString(std::move(E));
59 return InstrBenchmark;
60 }
61 std::vector<llvm::MCInst> &Snippet = SnippetOrError.get();
62 if (Snippet.empty()) {
63 InstrBenchmark.Error = "Empty snippet";
64 return InstrBenchmark;
65 }
Guillaume Chatelet083a0c162018-06-07 07:40:40 +000066 for (const auto &MCInst : Snippet) {
67 InstrBenchmark.Key.Instructions.push_back(MCInst);
68 }
Clement Courbet0e69e2d2018-05-17 10:52:18 +000069 InfoStream << "Snippet:\n";
70 for (const auto &MCInst : Snippet) {
71 DumpMCInst(MCRegisterInfo, MCInstrInfo, MCInst, InfoStream);
72 InfoStream << "\n";
73 }
74
75 std::vector<llvm::MCInst> Code;
76 for (int I = 0; I < InstrBenchmark.NumRepetitions; ++I)
77 Code.push_back(Snippet[I % Snippet.size()]);
78
79 auto ExpectedObjectPath = writeObjectFile(Code);
80 if (llvm::Error E = ExpectedObjectPath.takeError()) {
Clement Courbetac74acd2018-04-04 11:37:06 +000081 InstrBenchmark.Error = llvm::toString(std::move(E));
82 return InstrBenchmark;
83 }
84
Clement Courbet0e69e2d2018-05-17 10:52:18 +000085 // FIXME: Check if TargetMachine or ExecutionEngine can be reused instead of
86 // creating one everytime.
87 const ExecutableFunction EF(State.createTargetMachine(),
88 getObjectFromFile(*ExpectedObjectPath));
89 InstrBenchmark.Measurements = runMeasurements(EF, NumRepetitions);
Clement Courbetac74acd2018-04-04 11:37:06 +000090
Clement Courbetac74acd2018-04-04 11:37:06 +000091 return InstrBenchmark;
92}
93
Clement Courbet0e69e2d2018-05-17 10:52:18 +000094llvm::Expected<std::string>
95BenchmarkRunner::writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const {
96 int ResultFD = 0;
97 llvm::SmallString<256> ResultPath;
98 if (llvm::Error E = llvm::errorCodeToError(llvm::sys::fs::createTemporaryFile(
99 "snippet", "o", ResultFD, ResultPath)))
100 return std::move(E);
101 llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
102 assembleToStream(State.createTargetMachine(), Code, OFS);
103 llvm::outs() << "Check generated assembly with: /usr/bin/objdump -d "
104 << ResultPath << "\n";
105 return ResultPath.str();
106}
107
Clement Courbetac74acd2018-04-04 11:37:06 +0000108} // namespace exegesis