blob: 0e2052f82cc2751cc8e818f77221b6dccca74485 [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 Courbetee110fb2018-05-17 07:38:21 +000010#include <array>
11#include <string>
12
13#include "Assembler.h"
Clement Courbetac74acd2018-04-04 11:37:06 +000014#include "BenchmarkRunner.h"
Clement Courbetee110fb2018-05-17 07:38:21 +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 Courbetee110fb2018-05-17 07:38:21 +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 Courbetee110fb2018-05-17 07:38:21 +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 Courbetee110fb2018-05-17 07:38:21 +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);
40 InstrBenchmark.Key.Mode = getDisplayName();
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 Courbetee110fb2018-05-17 07:38:21 +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 }
Clement Courbetac74acd2018-04-04 11:37:06 +000066
Clement Courbetee110fb2018-05-17 07:38:21 +000067 InfoStream << "Snippet:\n";
68 for (const auto &MCInst : Snippet) {
69 DumpMCInst(MCRegisterInfo, MCInstrInfo, MCInst, InfoStream);
70 InfoStream << "\n";
71 }
72
73 std::vector<llvm::MCInst> Code;
74 for (int I = 0; I < InstrBenchmark.NumRepetitions; ++I)
75 Code.push_back(Snippet[I % Snippet.size()]);
76
77 auto ExpectedObjectPath = writeObjectFile(Code);
78 if (llvm::Error E = ExpectedObjectPath.takeError()) {
Clement Courbetac74acd2018-04-04 11:37:06 +000079 InstrBenchmark.Error = llvm::toString(std::move(E));
80 return InstrBenchmark;
81 }
82
Clement Courbetee110fb2018-05-17 07:38:21 +000083 // FIXME: Check if TargetMachine or ExecutionEngine can be reused instead of
84 // creating one everytime.
85 const ExecutableFunction EF(State.createTargetMachine(),
86 getObjectFromFile(*ExpectedObjectPath));
87 InstrBenchmark.Measurements = runMeasurements(EF, NumRepetitions);
Clement Courbetac74acd2018-04-04 11:37:06 +000088
Clement Courbetac74acd2018-04-04 11:37:06 +000089 return InstrBenchmark;
90}
91
Clement Courbetee110fb2018-05-17 07:38:21 +000092llvm::Expected<std::string>
93BenchmarkRunner::writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const {
94 int ResultFD = 0;
95 llvm::SmallString<256> ResultPath;
96 if (llvm::Error E = llvm::errorCodeToError(llvm::sys::fs::createTemporaryFile(
97 "snippet", "o", ResultFD, ResultPath)))
98 return std::move(E);
99 llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
100 assembleToStream(State.createTargetMachine(), Code, OFS);
101 llvm::outs() << "Check generated assembly with: /usr/bin/objdump -d "
102 << ResultPath << "\n";
103 return ResultPath.str();
104}
105
Clement Courbetac74acd2018-04-04 11:37:06 +0000106} // namespace exegesis