mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
arm64 universal binaries redux
Introduce the armv8-universal target. 🥴 The entry point is essentially the same as x86's, except we no longer have access to `__builtin_cpu_supports` so instead we need an OS-specific query for whether we support dotprod. The Makefile is modified to support both universal builds. If in the future we add more ARM targets, such as SVE, we'll need to add qemu to the RUN_PREFIX in CI, because currently we assume (for PGO purposes) that the CI host supports all the used ARM instructions. ### clang/Windows The painful part here is clang on Windows, which, until arm64 mingw is stabilized, is required for targeting arm64. This PR also gets it to work for x86. In the Makefile this setup corresponds to `use_lto_emit_asm=yes`. In particular, `--defsym` and `--save-temps` are not supported by `lld-link`, and objcopy `--rename-section` doesn't work on COFF binaries because of how section names work there. - `--defsym` is needed to define `main` for PGO purposes and assigns it to the namespaced, per-arch main function. Instead, we define `main` in `main.cpp` so that the compilation is successful, then delete it before the final link. - Instead of `--save-temps` to get the LTO intermediate object, we pass `--lto-emit-asm` to the linker, which outputs `stockfish.exe.lto.s`. - Finally, we have a small AWK script to find the `.ctors` section, neuter it, and put start/stop symbols around it with the same naming scheme as ELF (`__start_*_init`/`__stop_*_init`). I'm lowk a Windows programming noob so if there's simpler ways of going about this, I'd appreciate a pointer. @PikaCat-OuO + Codex used an approach that involved going in and modifying the LLVM bitcode, but that felt more complicated to me. closes https://github.com/official-stockfish/Stockfish/pull/6823 No functional change Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
committed by
Joost VandeVondele
co-authored by
coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
parent
91736f7b4f
commit
d6469b3980
@@ -0,0 +1,58 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/auxv.h>
|
||||
#ifndef HWCAP_ASIMDDP
|
||||
#define HWCAP_ASIMDDP (1 << 20)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFINE_BUILD(x) \
|
||||
namespace Stockfish_##x { \
|
||||
extern int main(int argc, char* argv[]); \
|
||||
} \
|
||||
extern "C" void (*__start_##x##_init[])(void); \
|
||||
extern "C" void (*__stop_##x##_init[])(void); \
|
||||
int entry_##x(int argc, char* argv[]) { \
|
||||
unsigned count = __stop_##x##_init - __start_##x##_init; \
|
||||
for (unsigned i = 0; i < count; i++) \
|
||||
__start_##x##_init[i](); \
|
||||
return Stockfish_##x::main(argc, argv); \
|
||||
}
|
||||
|
||||
DEFINE_BUILD(armv8)
|
||||
DEFINE_BUILD(armv8_dotprod)
|
||||
|
||||
struct CpuFeatures {
|
||||
bool dotprod;
|
||||
};
|
||||
|
||||
|
||||
static CpuFeatures query_cpu_features() {
|
||||
#if defined(_WIN32)
|
||||
return {
|
||||
.dotprod = (bool) IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE),
|
||||
};
|
||||
#else
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
return {
|
||||
.dotprod = (bool) (hwcap & HWCAP_ASIMDDP),
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Selects the most capable ISA variant supported by this CPU and OS
|
||||
static int dispatch(const CpuFeatures& f, int argc, char* argv[]) {
|
||||
if (!f.dotprod)
|
||||
return entry_armv8(argc, argv);
|
||||
|
||||
return entry_armv8_dotprod(argc, argv);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
CpuFeatures features = query_cpu_features();
|
||||
return dispatch(features, argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
# This is used if the universal binary is compiled on clang+Windows.
|
||||
# Usage (avx2 example):
|
||||
# awk -v MODNAME=x86_64_avx2 -f rewrite_asm_sections.awk stockfish.exe.lto.s > renamed.s
|
||||
#
|
||||
# The relevant output from --lto-emit-asm looks like:
|
||||
# ...
|
||||
# .section .ctors,"dw",associative,_ZN21Stockfish_x86_64_avx217SYSTEM_THREADS_NBE,unique,0
|
||||
# .p2align 3, 0x0
|
||||
# .quad __cxx_global_var_init
|
||||
# .section .ctors,"a",unique,0
|
||||
# .p2align 3, 0x0
|
||||
# .quad _GLOBAL__sub_I_benchmark.cpp
|
||||
# .quad _GLOBAL__sub_I_evaluate.cpp
|
||||
# ...
|
||||
# .quad _GLOBAL__sub_I_engine.cpp
|
||||
# .quad _GLOBAL__sub_I_score.cpp
|
||||
#
|
||||
# .section .bss$_ZN21Stockfish_x86_64_avx2L26STARTUP_PROCESSOR_AFFINITYE,"bw",one_only,_ZN21Stockfish_x86_64_avx2L26STARTUP_PROCESSOR_AFFINITYE,unique,570
|
||||
# ...
|
||||
#
|
||||
# We want to consolidate everything into a single section named x86_64_avx2_init, and insert
|
||||
# symbols __start_x86_64_avx2_init/__stop_x86_64_avx2_init for entry_x86.cpp to use.
|
||||
# (On ELF these symbols are implicitly defined, so naming it this way keeps the universal
|
||||
# entry point consistent.)
|
||||
|
||||
BEGIN {
|
||||
in_ctors = 0
|
||||
}
|
||||
|
||||
# Match any .section line containing .ctors
|
||||
/^[[:space:]]*\.section[[:space:]].*\.ctors/ {
|
||||
|
||||
# First .ctors section, emit start symbol
|
||||
if (!in_ctors) {
|
||||
in_ctors = 1
|
||||
section = MODNAME "_init"
|
||||
|
||||
printf "\t.section\t%s,\"a\"\n", section
|
||||
printf "\t.globl\t__start_%s\n", section
|
||||
printf "__start_%s:\n", section
|
||||
}
|
||||
|
||||
# Suppress all original .ctors section directives
|
||||
next
|
||||
}
|
||||
|
||||
# First non-.ctors .section after ctors block, emit stop symbol
|
||||
in_ctors && /^[[:space:]]*\.section/ {
|
||||
section = MODNAME "_init"
|
||||
|
||||
printf "\t.globl\t__stop_%s\n", section
|
||||
printf "__stop_%s:\n", section
|
||||
|
||||
in_ctors = 0
|
||||
}
|
||||
|
||||
{
|
||||
print
|
||||
}
|
||||
|
||||
END {
|
||||
if (in_ctors) {
|
||||
section = MODNAME "_init"
|
||||
printf "\t.globl\t__stop_%s\n", section
|
||||
printf "__stop_%s:\n", section
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user