diff --git a/llvm/test/tools/llvm-exegesis/AArch64/print-assembled-snippet.s b/llvm/test/tools/llvm-exegesis/AArch64/print-assembled-snippet.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/AArch64/print-assembled-snippet.s @@ -0,0 +1,31 @@ +# Check that "assembled_snippet" is fetched correctly from object file. +# Feel free to update the snippet in this test if the code generated by the +# snippet repetitor was changed intentionally and it is still fetched correctly. + +# RUN: llvm-exegesis --mtriple=aarch64-linux-gnu --mcpu=generic --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-LINUX + +# RUN: llvm-exegesis --mtriple=aarch64-windows-gnu --mcpu=generic --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-WINDOWS-GNU + +# RUN: llvm-exegesis --mtriple=aarch64-windows-msvc --mcpu=generic --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-WINDOWS-MSVC + +# LLVM-EXEGESIS-DEFREG X0 0 +# LLVM-EXEGESIS-DEFREG X1 0 +add x0, x0, x1 + +# CHECK-LINUX: cpu_name: generic +# CHECK-LINUX: llvm_triple: aarch64-unknown-linux-gnu +# CHECK-LINUX: assembled_snippet: 000080D2010080D20000018B0000018B0000018B0000018BC0035FD6{{$}} + +# CHECK-WINDOWS-GNU: cpu_name: generic +# CHECK-WINDOWS-GNU: llvm_triple: aarch64-unknown-windows-gnu +# CHECK-WINDOWS-GNU: assembled_snippet: 000080D2010080D20000018B0000018B0000018B0000018BC0035FD6{{$}} + +# CHECK-WINDOWS-MSVC: cpu_name: generic +# CHECK-WINDOWS-MSVC: llvm_triple: aarch64-unknown-windows-msvc +# CHECK-WINDOWS-MSVC: assembled_snippet: 000080D2010080D20000018B0000018B0000018B0000018BC0035FD6{{$}} diff --git a/llvm/test/tools/llvm-exegesis/Mips/print-assembled-snippet.s b/llvm/test/tools/llvm-exegesis/Mips/print-assembled-snippet.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/Mips/print-assembled-snippet.s @@ -0,0 +1,23 @@ +# Check that "assembled_snippet" is fetched correctly from object file. +# Feel free to update the snippet in this test if the code generated by the +# snippet repetitor was changed intentionally and it is still fetched correctly. + +# RUN: llvm-exegesis --mtriple=mips-linux-gnu --mcpu=generic --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-LINUX + +# RUN: llvm-exegesis --mtriple=mips64-linux-gnu --mcpu=generic --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-LINUX-64 + +# LLVM-EXEGESIS-DEFREG A0 0 +# LLVM-EXEGESIS-DEFREG A1 0 +add $2, $5, $4 + +# CHECK-LINUX: cpu_name: generic +# CHECK-LINUX: llvm_triple: mips-unknown-linux-gnu +# CHECK-LINUX: assembled_snippet: 340400003405000000A4102000A4102000A4102000A4102003E00008{{$}} + +# CHECK-LINUX-64: cpu_name: generic +# CHECK-LINUX-64: llvm_triple: mips64-unknown-linux-gnu +# CHECK-LINUX-64: assembled_snippet: 340400003405000000A4102000A4102000A4102000A4102003E00008{{$}} diff --git a/llvm/test/tools/llvm-exegesis/PowerPC/print-assembled-snippet.s b/llvm/test/tools/llvm-exegesis/PowerPC/print-assembled-snippet.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/PowerPC/print-assembled-snippet.s @@ -0,0 +1,15 @@ +# Check that "assembled_snippet" is fetched correctly from object file. +# Feel free to update the snippet in this test if the code generated by the +# snippet repetitor was changed intentionally and it is still fetched correctly. + +# RUN: llvm-exegesis --mtriple=powerpc64le-linux-gnu --mcpu=pwr8 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-LINUX-64-LE + +# LLVM-EXEGESIS-DEFREG R3 0 +# LLVM-EXEGESIS-DEFREG R4 0 +add 3, 4, 3 + +# CHECK-LINUX-64-LE: cpu_name: pwr8 +# CHECK-LINUX-64-LE: llvm_triple: powerpc64le-unknown-linux-gnu +# CHECK-LINUX-64-LE: assembled_snippet: 0000603800008038141A647C141A647C141A647C141A647C2000804E000000000000000000000000{{$}} diff --git a/llvm/test/tools/llvm-exegesis/X86/print-assembled-snippet.s b/llvm/test/tools/llvm-exegesis/X86/print-assembled-snippet.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/X86/print-assembled-snippet.s @@ -0,0 +1,32 @@ +# Check that "assembled_snippet" is fetched correctly from object file. +# Feel free to update the snippet in this test if the code generated by the +# snippet repetitor was changed intentionally and it is still fetched correctly. + +# RUN: llvm-exegesis --mtriple=x86_64-linux-gnu --mcpu=x86-64 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-LINUX + +# RUN: llvm-exegesis --mtriple=x86_64-windows-gnu --mcpu=x86-64 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-WINDOWS-GNU + +# RUN: llvm-exegesis --mtriple=x86_64-windows-msvc --mcpu=x86-64 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: --snippets-file=%s --mode=latency --repetition-mode=duplicate \ +# RUN: | FileCheck %s --check-prefix=CHECK-WINDOWS-MSVC + +# LLVM-EXEGESIS-DEFREG RDI 0 +# LLVM-EXEGESIS-DEFREG RSI 0 +# LLVM-EXEGESIS-DEFREG RAX 0 +leaq (%rdi,%rsi), %rax + +# CHECK-LINUX: cpu_name: x86-64 +# CHECK-LINUX: llvm_triple: x86_64-unknown-linux-gnu +# CHECK-LINUX: assembled_snippet: 48BF000000000000000048BE000000000000000048B80000000000000000488D0437488D0437488D0437488D0437C3{{$}} + +# CHECK-WINDOWS-GNU: cpu_name: x86-64 +# CHECK-WINDOWS-GNU: llvm_triple: x86_64-unknown-windows-gnu +# CHECK-WINDOWS-GNU: assembled_snippet: 565748BF000000000000000048BE000000000000000048B80000000000000000488D0437488D0437488D0437488D04375F5EC3{{$}} + +# CHECK-WINDOWS-MSVC: cpu_name: x86-64 +# CHECK-WINDOWS-MSVC: llvm_triple: x86_64-unknown-windows-msvc +# CHECK-WINDOWS-MSVC: assembled_snippet: 565748BF000000000000000048BE000000000000000048B80000000000000000488D0437488D0437488D0437488D04375F5EC3{{$}} diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.h b/llvm/tools/llvm-exegesis/lib/Assembler.h --- a/llvm/tools/llvm-exegesis/lib/Assembler.h +++ b/llvm/tools/llvm-exegesis/lib/Assembler.h @@ -121,6 +121,10 @@ StringRef FunctionBytes; }; +// Copies benchmark function's bytes from benchmark object. +Error getBenchmarkFunctionBytes(const StringRef InputData, + std::vector &Bytes); + // Creates a void(int8*) MachineFunction. MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionID, Module *Module, diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { namespace exegesis { @@ -323,5 +324,38 @@ StringRef(reinterpret_cast(FunctionAddress), CodeSize); } +Error getBenchmarkFunctionBytes(const StringRef InputData, + std::vector &Bytes) { + const auto Holder = getObjectFromBuffer(InputData); + const auto *Obj = Holder.getBinary(); + // See RuntimeDyldImpl::loadObjectImpl(Obj) for much more complete + // implementation. + + // Find the only function in the object file. + SmallVector Functions; + for (auto &Sym : Obj->symbols()) { + auto SymType = Sym.getType(); + if (SymType && *SymType == object::SymbolRef::Type::ST_Function) + Functions.push_back(Sym); + } + if (Functions.size() != 1) + return make_error("Exactly one function expected"); + + // Find the containing section - it is assumed to contain only this function. + auto SectionOrErr = Functions.front().getSection(); + if (!SectionOrErr || *SectionOrErr == Obj->section_end()) + return make_error("Section not found"); + + auto Address = Functions.front().getAddress(); + if (!Address || *Address != SectionOrErr.get()->getAddress()) + return make_error("Unexpected layout"); + + auto ContentsOrErr = SectionOrErr.get()->getContents(); + if (!ContentsOrErr) + return ContentsOrErr.takeError(); + Bytes.assign(ContentsOrErr->begin(), ContentsOrErr->end()); + return Error::success(); +} + } // namespace exegesis } // namespace llvm diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -174,10 +174,10 @@ LoopBodySizeForSnippet); if (Error E = Snippet.takeError()) return std::move(E); - const ExecutableFunction EF(State.createTargetMachine(), - getObjectFromBuffer(*Snippet)); - const auto FnBytes = EF.getFunctionBytes(); - llvm::append_range(InstrBenchmark.AssembledSnippet, FnBytes); + + if (auto Err = getBenchmarkFunctionBytes(*Snippet, + InstrBenchmark.AssembledSnippet)) + return std::move(Err); } // Assemble NumRepetitions instructions repetitions of the snippet for