diff options
Diffstat (limited to 'bootstrap/llvm16/exegesis-mcjit.patch')
-rw-r--r-- | bootstrap/llvm16/exegesis-mcjit.patch | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/bootstrap/llvm16/exegesis-mcjit.patch b/bootstrap/llvm16/exegesis-mcjit.patch new file mode 100644 index 000000000..7363965c2 --- /dev/null +++ b/bootstrap/llvm16/exegesis-mcjit.patch @@ -0,0 +1,348 @@ +This is a backport from LLVM 17 that fixes a test failure observed on +ppc64: + +******************** +FAIL: LLVM :: tools/llvm-exegesis/PowerPC/latency-by-opcode-name.s (216 of 47688) +******************** TEST 'LLVM :: tools/llvm-exegesis/PowerPC/latency-by-opcode-name.s' FAILED ******************** +PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. +Stack dump: +0. Program arguments: /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/build/bin/llvm-exegesis -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 --benchmark-phase=assemble-measured-code -mode=latency -opcode-name=ADD8 + #0 0x0000000141a994d0 llvm::sys::RunSignalHandlers() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/Support/Signals.cpp:103:22 + #1 0x0000000141a994d0 SignalHandler(int) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/Support/Unix/Signals.inc:402:31 + #2 0x00003fff89552444 0x444 __register_frame_info_bases + #3 0x00003fff89552444 + #4 0x00003fff89552444 __register_frame_info (+0x444) + #5 0xaaaaaaaaaaaaaaab + #6 0x00003fff8907b700 __register_frame (/usr/lib/libgcc_s.so.1+0x12700) + #7 0x00003fff8907b760 llvm::RTDyldMemoryManager::registerEHFramesInProcess(unsigned char*, unsigned long) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp:119:19 + #8 0x00003fff8907b760 llvm::RTDyldMemoryManager::registerEHFrames(unsigned char*, unsigned long, unsigned long) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp:131:28 + #9 0x00003fff8907b7c0 llvm::RuntimeDyldELF::registerEHFrames() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp:227:28 +#10 0x0000000142e9d1b0 llvm::RuntimeDyld::registerEHFrames() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp:1435:27 +#11 0x0000000142eb4258 llvm::MCJIT::finalizeLoadedModules() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:251:24 +#12 0x0000000142ea2154 __gthread_mutex_unlock /usr/include/c++/13.3.0/powerpc64-foxkit-linux-musl/bits/gthr-default.h:779:43 +#13 0x0000000142ea2154 __gthread_recursive_mutex_unlock /usr/include/c++/13.3.0/powerpc64-foxkit-linux-musl/bits/gthr-default.h:832:33 +#14 0x0000000142ea2154 std::recursive_mutex::unlock() /usr/include/c++/13.3.0/mutex:139:39 +#15 0x0000000142ea2154 llvm::sys::SmartMutex<false>::unlock() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/include/llvm/Support/Mutex.h:47:22 +#16 0x0000000142ea2154 std::lock_guard<llvm::sys::SmartMutex<false>>::~lock_guard() /usr/include/c++/13.3.0/bits/std_mutex.h:255:25 +#17 0x0000000142ea2154 llvm::MCJIT::getFunctionAddress(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:410:1 +#18 0x0000000142b6f948 llvm::exegesis::ExecutableFunction::ExecutableFunction(std::unique_ptr<llvm::LLVMTargetMachine, std::default_delete<llvm::LLVMTargetMachine>>, llvm::object::OwningBinary<llvm::object::ObjectFile>&&) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/tools/llvm-exegesis/lib/Assembler.cpp:319:66 +#19 0x0000000142b73a18 llvm::exegesis::BenchmarkRunner::getRunnableConfiguration(llvm::exegesis::BenchmarkCode const&, unsigned int, unsigned int, llvm::exegesis::SnippetRepetitor const&) const /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp:181:62 +#20 0x0000000141af099c llvm::exegesis::runBenchmarkConfigurations(llvm::exegesis::LLVMState const&, llvm::ArrayRef<llvm::exegesis::BenchmarkCode>, llvm::ArrayRef<std::unique_ptr<llvm::exegesis::SnippetRepetitor const, std::default_delete<llvm::exegesis::SnippetRepetitor const>>>, llvm::exegesis::BenchmarkRunner const&) /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/tools/llvm-exegesis/llvm-exegesis.cpp:376:58 +#21 0x0000000141aca060 llvm::exegesis::benchmarkMain() /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/tools/llvm-exegesis/llvm-exegesis.cpp:506:30 +#22 0x000000013fbe7144 main /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/tools/llvm-exegesis/llvm-exegesis.cpp:660:1 +#23 0x000000013fbea0a8 libc_start_main_stage2 /usr/src/packages/system/musl/src/musl-1.2.3/src/env/__libc_start_main.c:95:2 +#24 0x000000013fb105ac __libc_start_main /usr/src/packages/system/musl/src/musl-1.2.3/src/env/__libc_start_main.c:86:9 +#25 0x00003fff89494038 _start_c /usr/src/packages/system/musl/src/musl-1.2.3/crt/crt1.c:18:2 +#26 0x00003fff894940b4 _start (/lib/ld-musl-powerpc64.so.1+0x220b4) +Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): +0 llvm-exegesis 0x0000000141a994d0 +1 0x00003fff89552444 __kernel_sigtramp_rt64 + 0 +2 0xaaaaaaaaaaaaaaab __kernel_sigtramp_rt64 + 12297759015719765607 +3 libgcc_s.so.1 0x00003fff8907b700 __register_frame_info_bases + 128 +4 libgcc_s.so.1 0x00003fff8907b760 __register_frame_info + 32 +5 libgcc_s.so.1 0x00003fff8907b7c0 __register_frame + 64 +6 llvm-exegesis 0x0000000142e9d1b0 +7 llvm-exegesis 0x0000000142eb4258 +8 llvm-exegesis 0x0000000142ea2154 +9 llvm-exegesis 0x0000000142b6f948 +10 llvm-exegesis 0x0000000142b73a18 +11 llvm-exegesis 0x0000000141af099c +12 llvm-exegesis 0x0000000141aca060 +13 llvm-exegesis 0x000000013fbe7144 +14 llvm-exegesis 0x000000013fbea0a8 +15 llvm-exegesis 0x000000013fb105ac +16 ld-musl-powerpc64.so.1 0x00003fff89494038 +17 ld-musl-powerpc64.so.1 0x00003fff894940b4 __libc_start_main + 100 +18 llvm-exegesis 0x000000013fbdcf78 +19 llvm-exegesis 0x000000013fbdcf20 +FileCheck error: '<stdin>' is empty. +FileCheck command line: /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/build/bin/FileCheck /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/test/tools/llvm-exegesis/PowerPC/latency-by-opcode-name.s + +Tracing with a debug-build libgcc_s yields: + +Program received signal SIGSEGV, Segmentation fault. +classify_object_over_fdes (ob=0x3ffff7904700, this_fde=0x400007ae4004, range=0x3fffffffd700) at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:732 +732 for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde)) +(gdb) bt +#0 classify_object_over_fdes (ob=0x3ffff7904700, this_fde=0x400007ae4004, range=0x3fffffffd700) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:732 +#1 0x00003ffff7b47700 in register_pc_range_for_object (ob=0x3ffff7904700, begin=<optimized out>) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:118 +#2 __register_frame_info_bases (dbase=<optimized out>, tbase=<optimized out>, ob=0x3ffff7904700, begin=<optimized out>) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:144 +#3 __register_frame_info_bases (begin=<optimized out>, ob=0x3ffff7904700, tbase=<optimized out>, dbase=<optimized out>) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:126 +#4 0x00003ffff7b47760 in __register_frame_info (begin=<optimized out>, ob=<optimized out>) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:159 +#5 0x00003ffff7b477c0 in __register_frame (begin=0x3ffff7ae4000) + at /home/awilcox/Code/awilfox/gcc-next/system/gcc/src/gcc-13.3.0/libgcc/unwind-dw2-fde.c:172 +#6 0x00000001038da4f0 in llvm::RTDyldMemoryManager::registerEHFramesInProcess (Size=<optimized out>, Addr=<optimized out>) + at /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp:119 +#7 llvm::RTDyldMemoryManager::registerEHFrames (this=0x3ffff78b1700, Addr=<optimized out>, LoadAddr=<optimized out>, + Size=<optimized out>) + at /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp:131 +#8 0x00000001038f1598 in llvm::RuntimeDyldELF::registerEHFrames (this=0x3ffff7b0e550) + at /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp:227 +#9 0x00000001038df494 in llvm::RuntimeDyld::registerEHFrames (this=<optimized out>) + at /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp:1435 +#10 0x00000001035acc88 in llvm::MCJIT::finalizeLoadedModules (this=0x3ffff7aef0b0) + at /home/awilcox/Code/awilfox/rust-next/bootstrap/llvm16/src/llvm-project-16.0.6.src/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:251 + +The reason is because it is trying to interpret a little-endian FDE as a +native (big-endian) one and failing. This was noted upstream and fixed +in the LLVM 17 branch but it was never backported to a 16 release. + +From 27f37db76a79e746561ad2545ff6ccf0d50cc38c Mon Sep 17 00:00:00 2001 +From: Pavel Kosov <kpdev42@gmail.com> +Date: Thu, 8 Jun 2023 19:14:00 +0300 +Subject: [PATCH] [llvm-exegesis] Use MCJIT only for execution + +Initially, llvm-exegesis was generating the benchmark code for the +host CPU to execute it inside its own process. Thus, MCJIT was reused +for fetching function's bytes to fill the assembled_snippet field in +the benchmark report. + +Later, the --mtriple and --benchmark-phase command line options were +introduced that are handy for testing snippet generation even if +snippet execution is not possible. In that setup, MCJIT is asked to +parse an object file for a foreign CPU or operating system that is +probably not guaranteed to succeed and was actually observed to fail +in https://reviews.llvm.org/D145763. + +This commit implements a much simplified function's code fetching, +assuming the benchmark function is the only function in the object file +and it spans across the entire text section (note that MCJIT-based code +has more or less the same assumption - see TrackingSectionMemoryManager +class). + +~~~ + +Huawei RRI, OS Lab + +Reviewed By: courbet + +Differential Revision: https://reviews.llvm.org/D148921 +--- + .../AArch64/print-assembled-snippet.s | 31 +++++++++++++++++ + .../Mips/print-assembled-snippet.s | 23 +++++++++++++ + .../PowerPC/print-assembled-snippet.s | 15 ++++++++ + .../X86/print-assembled-snippet.s | 32 +++++++++++++++++ + llvm/tools/llvm-exegesis/lib/Assembler.cpp | 34 +++++++++++++++++++ + llvm/tools/llvm-exegesis/lib/Assembler.h | 4 +++ + .../llvm-exegesis/lib/BenchmarkRunner.cpp | 8 ++--- + 7 files changed, 143 insertions(+), 4 deletions(-) + create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/print-assembled-snippet.s + create mode 100644 llvm/test/tools/llvm-exegesis/Mips/print-assembled-snippet.s + create mode 100644 llvm/test/tools/llvm-exegesis/PowerPC/print-assembled-snippet.s + create mode 100644 llvm/test/tools/llvm-exegesis/X86/print-assembled-snippet.s + +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 +index 0000000000000..e8b312d7a6ae9 +--- /dev/null ++++ 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 +index 0000000000000..f0844c4145a2b +--- /dev/null ++++ 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 +index 0000000000000..75cad37a768eb +--- /dev/null ++++ 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 +index 0000000000000..532901d0e0430 +--- /dev/null ++++ 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.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp +index 07465c71afc70..8e561f587cc2a 100644 +--- llvm/tools/llvm-exegesis/lib/Assembler.cpp ++++ llvm/tools/llvm-exegesis/lib/Assembler.cpp +@@ -25,6 +25,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 @@ ExecutableFunction::ExecutableFunction( + StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize); + } + ++Error getBenchmarkFunctionBytes(const StringRef InputData, ++ std::vector<uint8_t> &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<object::SymbolRef, 1> 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<Failure>("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<Failure>("Section not found"); ++ ++ auto Address = Functions.front().getAddress(); ++ if (!Address || *Address != SectionOrErr.get()->getAddress()) ++ return make_error<Failure>("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/Assembler.h b/llvm/tools/llvm-exegesis/lib/Assembler.h +index 2a83344b751e5..cd1e398e4a564 100644 +--- llvm/tools/llvm-exegesis/lib/Assembler.h ++++ llvm/tools/llvm-exegesis/lib/Assembler.h +@@ -121,6 +121,10 @@ struct ExecutableFunction { + StringRef FunctionBytes; + }; + ++// Copies benchmark function's bytes from benchmark object. ++Error getBenchmarkFunctionBytes(const StringRef InputData, ++ std::vector<uint8_t> &Bytes); ++ + // Creates a void(int8*) MachineFunction. + MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionID, + Module *Module, +diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +index e1df2940a9b7e..f934b8ec4c6cc 100644 +--- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp ++++ llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +@@ -177,10 +177,10 @@ BenchmarkRunner::getRunnableConfiguration( + 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 |