summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
diff options
context:
space:
mode:
authorClement Courbet <courbet@google.com>2018-05-17 10:52:18 +0000
committerClement Courbet <courbet@google.com>2018-05-17 10:52:18 +0000
commit0e69e2d74739a119a78d131c29b92c25787ec2f3 (patch)
treec808110b4a710daf2bed231cc96e1e3af1558294 /llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
parentceb4933dc1dc4e769ea9e1752a8cb8425de09002 (diff)
downloadbcm5719-llvm-0e69e2d74739a119a78d131c29b92c25787ec2f3.tar.gz
bcm5719-llvm-0e69e2d74739a119a78d131c29b92c25787ec2f3.zip
reland r332579: [llvm-exegesis] Update to cover latency through another opcode.
Restructuring the code to measure latency and uops. The end goal is to have this program spawn another process to deal with SIGILL and other malformed programs. It is not yet the case in this redesign, it is still the main program that runs the code (and may crash). It now uses BitVector instead of Graph for performance reasons. https://reviews.llvm.org/D46821 (with fixed ARM tests) Authored by Guillaume Chatelet llvm-svn: 332592
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp')
-rw-r--r--llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp88
1 files changed, 59 insertions, 29 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 2615a829902..0e2052f82cc 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -7,23 +7,33 @@
//
//===----------------------------------------------------------------------===//
+#include <array>
+#include <string>
+
+#include "Assembler.h"
#include "BenchmarkRunner.h"
-#include "InMemoryAssembler.h"
+#include "MCInstrDescView.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
-#include <string>
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Program.h"
namespace exegesis {
BenchmarkRunner::InstructionFilter::~InstructionFilter() = default;
-
+BenchmarkRunner::BenchmarkRunner(const LLVMState &State)
+ : State(State), MCInstrInfo(State.getInstrInfo()),
+ MCRegisterInfo(State.getRegInfo()),
+ RATC(MCRegisterInfo,
+ getFunctionReservedRegs(*State.createTargetMachine())) {}
BenchmarkRunner::~BenchmarkRunner() = default;
-InstructionBenchmark
-BenchmarkRunner::run(const LLVMState &State, const unsigned Opcode,
- unsigned NumRepetitions,
- const InstructionFilter &Filter) const {
+InstructionBenchmark BenchmarkRunner::run(unsigned Opcode,
+ const InstructionFilter &Filter,
+ unsigned NumRepetitions) {
InstructionBenchmark InstrBenchmark;
InstrBenchmark.Key.OpcodeName = State.getInstrInfo().getName(Opcode);
@@ -41,36 +51,56 @@ BenchmarkRunner::run(const LLVMState &State, const unsigned Opcode,
InstrBenchmark.Error = llvm::toString(std::move(E));
return InstrBenchmark;
}
-
- JitFunctionContext Context(State.createTargetMachine());
- auto ExpectedInstructions =
- createCode(State, Opcode, NumRepetitions, Context);
- if (llvm::Error E = ExpectedInstructions.takeError()) {
+ llvm::raw_string_ostream InfoStream(InstrBenchmark.Info);
+ llvm::Expected<std::vector<llvm::MCInst>> SnippetOrError =
+ createSnippet(RATC, Opcode, InfoStream);
+ if (llvm::Error E = SnippetOrError.takeError()) {
InstrBenchmark.Error = llvm::toString(std::move(E));
return InstrBenchmark;
}
+ std::vector<llvm::MCInst> &Snippet = SnippetOrError.get();
+ if (Snippet.empty()) {
+ InstrBenchmark.Error = "Empty snippet";
+ return InstrBenchmark;
+ }
- const std::vector<llvm::MCInst> Instructions = *ExpectedInstructions;
- const JitFunction Function(std::move(Context), Instructions);
- const llvm::StringRef CodeBytes = Function.getFunctionBytes();
+ InfoStream << "Snippet:\n";
+ for (const auto &MCInst : Snippet) {
+ DumpMCInst(MCRegisterInfo, MCInstrInfo, MCInst, InfoStream);
+ InfoStream << "\n";
+ }
+
+ std::vector<llvm::MCInst> Code;
+ for (int I = 0; I < InstrBenchmark.NumRepetitions; ++I)
+ Code.push_back(Snippet[I % Snippet.size()]);
- std::string AsmExcerpt;
- constexpr const int ExcerptSize = 100;
- constexpr const int ExcerptTailSize = 10;
- if (CodeBytes.size() <= ExcerptSize) {
- AsmExcerpt = llvm::toHex(CodeBytes);
- } else {
- AsmExcerpt =
- llvm::toHex(CodeBytes.take_front(ExcerptSize - ExcerptTailSize + 3));
- AsmExcerpt += "...";
- AsmExcerpt += llvm::toHex(CodeBytes.take_back(ExcerptTailSize));
+ auto ExpectedObjectPath = writeObjectFile(Code);
+ if (llvm::Error E = ExpectedObjectPath.takeError()) {
+ InstrBenchmark.Error = llvm::toString(std::move(E));
+ return InstrBenchmark;
}
- llvm::outs() << "# Asm excerpt: " << AsmExcerpt << "\n";
- llvm::outs().flush(); // In case we crash.
- InstrBenchmark.Measurements =
- runMeasurements(State, Function, NumRepetitions);
+ // FIXME: Check if TargetMachine or ExecutionEngine can be reused instead of
+ // creating one everytime.
+ const ExecutableFunction EF(State.createTargetMachine(),
+ getObjectFromFile(*ExpectedObjectPath));
+ InstrBenchmark.Measurements = runMeasurements(EF, NumRepetitions);
+
return InstrBenchmark;
}
+llvm::Expected<std::string>
+BenchmarkRunner::writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const {
+ int ResultFD = 0;
+ llvm::SmallString<256> ResultPath;
+ if (llvm::Error E = llvm::errorCodeToError(llvm::sys::fs::createTemporaryFile(
+ "snippet", "o", ResultFD, ResultPath)))
+ return std::move(E);
+ llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
+ assembleToStream(State.createTargetMachine(), Code, OFS);
+ llvm::outs() << "Check generated assembly with: /usr/bin/objdump -d "
+ << ResultPath << "\n";
+ return ResultPath.str();
+}
+
} // namespace exegesis
OpenPOWER on IntegriCloud