1975 Commits
Author SHA1 Message Date
Konstantin Bogdanov 0ad0b0ca07 Merge pull request #127256 from ClickHouse/musl-pack-relative-relocs
Link the `musl` binary with packed relative relocations
2026-10-22 15:17:14 +00:00
Konstantin BogdanovandClaude Opus 5.5 b66903d180 Link the musl binary with packed relative relocations
The `-static-pie` binary relocates itself at startup: about 1.4M
`R_X86_64_RELATIVE` entries, 34 MB of `.rela.dyn`. `-z pack-relative-relocs`
describes the same relocations as DT_RELR in 254 KB, which musl's
`ldso/dlstart.c` already applies. The binary keeps its ASLR and every
pointer is still patched, so a start with a warm page cache costs the same,
but the binary is 33.7 MB smaller and a cold start reads that much less.

Same objects linked both ways (x86_64, `clickhouse local -q "SELECT 1"`):
binary 897.6 MB -> 863.9 MB; warm start 26.8 ms -> 26.8 ms (50 runs);
cold start after evicting the binary from the page cache 222 ms -> 204 ms
(8 runs, repeated with the same result); page faults 7,800 -> 7,480.

Related: https://github.com/ClickHouse/ClickHouse/pull/109239

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:46:37 +02:00
Konstantin BogdanovandClaude Fable 5.1 9801c9138d Make sanitizers work with statically linked musl
In a static binary there is no `dlsym` for the sanitizer runtime to find
the real libc functions behind its interceptors. The compiler-rt
runtimes are built with `SANITIZER_STATIC_LIBC_INTERCEPTION` (see the
`static-musl-interception` branch of `contrib/llvm-project`): `REAL(f)`
binds to `__real_f` at link time, and the runtime defines the bare
intercepted names itself. `contrib/compiler-rt-cmake` produces a copy of
the musl archive with those names renamed to `__real_*`, and
`cmake/linux/default_libs.cmake` links that copy (`musl_intercepted`)
for every sanitizer except standalone UBSan, which has no interceptors.
The plain allocation functions are left unrenamed so that memory musl
hands out internally (`getdelim`, `strdup`, ...) is freed through the
same interposed allocator.

The `llvm-project` bump also carries the TSan `setjmp`/`longjmp` fixes
for static musl, the raw-syscall `MonotonicNanoTime`, the `posix_close`
interceptor, and `GetTls` covering musl's `struct pthread` on
`TLS_ABOVE_TP` targets; the `musl` bump exports
`__pthread_current_thread_range` for the latter.

`ThreadFuzzer` uses the internal `__pthread_mutex_*` symbols under musl
even with ASan (they are plain strong symbols there, and `dlsym` cannot
look anything up in a static binary); the `harmful` traps that collide
with musl's own definitions once the interceptors pull them in move
under `#ifndef USE_MUSL`; Rust drops `crt-static` under a sanitizer,
which rustc otherwise refuses to combine with one.

Split out of https://github.com/ClickHouse/ClickHouse/pull/109239.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-21 17:17:28 +02:00
Konstantin Bogdanov 023b5a8fc2 Merge pull request #118916 from ClickHouse/aarch64-arm-optimized-routines
Use ARM optimized-routines for aarch64 string functions
2026-10-19 18:00:28 +00:00
robot-clickhouse ad4d4e348f Update autogenerated version to 26.11.1.1 and contributors 2026-10-15 20:30:15 +00:00
Raúl Marín 17a0ca3094 Merge pull request #125488 from groeneai/runtime-libs-fpie
Compile with -fPIE instead of -fPIC
2026-10-15 09:17:56 +00:00
Alexey Milovidov f2eb71d2f3 Merge pull request #125073 from ClickHouse/continue-pr-124465-illumos-ci
Cross-compile for illumos
2026-10-15 02:30:59 +00:00
Alexey Milovidov 11ba8b1129 Merge pull request #115322 from ei-grad/symbols-gnu-debugdata
Add `SYMBOL_SECTIONS=gnu_debugdata` packaging mode with MiniDebugInfo
2026-10-15 01:58:40 +00:00
Groene AIandClaude Opus 5.5 9415dcba9b Compile everything with -fPIE instead of -fPIC
Everything we build is linked into the position-independent executable, so
-fPIE is the right code model: -fPIC only adds symbol interposition (GOT
loads, TLS descriptor sequences) that an executable never uses. Instead of
putting -fPIE back on the three C++ runtime targets, the global flag is now
-fPIE, set where #125094 put it, before the default_libs include. The
objects stay relocatable, so builds with compilers that do not default to
PIE keep working.

Also drop the per-target PIC that would override it: POSITION_INDEPENDENT_CODE
on _cld2, the cuDF fragments and the GPU island targets, -Xcompiler -fPIC in
CMAKE_CUDA_FLAGS (now -Xcompiler -fPIE), -fPIC on xgboost and dmlc-core, and
the MSan "-fPIC -fpie" (now -fPIE).

-fPIC stays where it is needed or mirrors upstream: compiler-rt (builtins,
and the sanitizer and XRay runtimes through SANITIZER_COMMON_FLAGS),
glibc-compatibility with ENABLE_OPENSSL_DYNAMIC, and the shared crypto/ssl
libraries of that option, which CMake compiles as PIC by itself. musl's
rcrt1.c keeps -fPIC on master.

Measured locally (compile_commands.json, effective last PIC/PIE flag per TU):
- amd64 debug, release; aarch64 binary, release; asan, msan, tsan: every
  C/C++ TU is -fPIE except clang_rt_builtins and the compiler-rt sanitizer /
  XRay runtimes; with ENABLE_OPENSSL_DYNAMIC also crypto, ssl and
  glibc-compatibility.
- amd64 debug clickhouse: ELF type DYN, FLAGS_1 NOW PIE; clickhouse local
  queries with threads and exceptions work.
- aarch64 flatc, msan and asan llvm-min-tblgen: DYN + PIE, the sanitizer
  builds run.
- With a clang wrapper defaulting to -fno-pic, llvm-min-tblgen still links
  as PIE.

The GPU island (ENABLE_GPU) is not built by CI and I have no CUDA toolkit,
so the cmake/cuda.cmake and contrib/cudf-cmake changes are not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:01:16 +00:00
Alexey MilovidovandClaude Opus 5.5 c400d846c1 Merge remote-tracking branch 'origin/master' into continue-pr-124465-illumos-ci
Resolve conflicts in the generated `.github/workflows/master.yml` and
`.github/workflows/pull_request.yml` by regenerating them with
`python3 -m ci.praktika yaml`. `contrib/llvm-project` fast-forwards to the
PR's pointer, which already contains master's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:06:52 +00:00
Konstantin Bogdanov 9269fc49fc Merge remote-tracking branch 'upstream/master' into aarch64-arm-optimized-routines 2026-10-14 15:10:40 +02:00
Alexey MilovidovandClaude Opus 5.5 5347a60310 Address review: strip symbols explicitly when adding .gnu_debugdata
GNU `objcopy` regenerates `.symtab` and `.strtab` when they are removed with
`--remove-section` while symbols are still present, so with GNU binutils the
packaged binary kept the full symbol table next to `.gnu_debugdata`. Add
`--strip-unneeded`, which drops the symbols with both GNU and LLVM `objcopy`.
`--strip-all` is not used because `llvm-objcopy` also removes non-allocated
sections such as `.clickhouse.hash` and `.gnu_debuglink` with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:34:20 +00:00
Raúl MarínandClaude Opus 5.5 37ae3214da Build the musl binary as a static PIE
The glibc binary has been a PIE since the release binary was made position
independent, but musl builds kept linking with `-static` because
`contrib/musl-cmake` only built `crt1.o`. Build musl's `rcrt1.o` instead, whose
`ldso/dlstart.c` applies the executable's own relocations at startup, and link
with `-static-pie`, so the musl binary gets ASLR too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:00:47 +02:00
Alexey Milovidov 2c368049a6 Merge remote-tracking branch 'origin/master' into HEAD 2026-10-13 11:53:10 +00:00
Alexey Milovidov be0dbf7eab Merge remote-tracking branch 'origin/master' into HEAD 2026-10-13 10:13:42 +00:00
Alexey MilovidovandClaude Opus 5.5 8c17c4c926 Address review: force the illumos feature disables in the CMake cache
Use `CACHE INTERNAL` like the Emscripten block, so the disables also apply
when reconfiguring an existing build directory or when the options are
passed explicitly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:30:24 +00:00
Alexey Milovidov 0e10f6b3e3 Merge remote-tracking branch 'origin/master' into HEAD
# Conflicts:
#	.github/workflows/master.yml
#	.github/workflows/pull_request.yml
#	.github/workflows/release_branches.yml
2026-10-12 14:30:09 +00:00
Groene AIandClaude Opus 5.5 cdd1d2ac96 Serialize calls into the macOS libc time zone lock
macOS libc guards its time zone state with a private pthread_rwlock
(`lcl_rwlock` in Libc stdtime/FreeBSD/localtime.c), taken by strftime(_l),
wcsftime(_l), strptime(_l), localtime(_r), ctime(_r), mktime, timelocal,
time2posix, posix2time, tzset and tzsetwall. It is the psynch rwlock that
loses wakeups when its waiters are interrupted by signals (FB24027930), and
the macOS query profiler signals every registered thread. The pthread_rwlock
shim from #112267 does not reach it, because libsystem_c binds to libpthread
through the two-level namespace.

Seen in Fast test (arm_darwin) on #117253: S3 request signing
(Aws::Utils::DateTime::ToGmtString), EnabledQuota::Impl::throwQuotaExceed and
ExternalLoader::LoadingDispatcher::calculateNextUpdateTime (holding the
ExternalLoader mutex) all wait in strftime_l -> _st_tzset_basic with no holder.

Define these 16 functions in the force-loaded darwin-compatibility archive.
Each resolves the libc function with dlsym(RTLD_NEXT) and calls it under one
recursive mutex, so at most one thread of the binary is inside libc's time
zone code and none waits on its rwlock. errno is preserved across the mutex,
because a contended Darwin mutex retries an interrupted __psynch_mutexwait /
__psynch_mutexdrop and can leave EINTR behind on success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:22:02 +00:00
Alexey Milovidov 76b69d2c1d Merge pull request #107440 from Tiaonmmn/fix-arm-build-cpuflag
Fix build flag with new detection mode.
2026-10-12 02:30:53 +00:00
Alexey Milovidov a5a9fc20dd Merge remote-tracking branch 'origin/master' into HEAD
# Conflicts:
#	.github/workflows/master.yml
#	.github/workflows/pull_request.yml
#	.github/workflows/release_branches.yml
2026-10-11 11:41:43 +00:00
Josh Carp 22d859798a Cross-compile for illumos.
Add toolchain and ci job to build for illumos, modeled after freebsd
cross-compilation.

Note: we disable a number of features that don't currently build on
illumos. These can be reenabled in the future if desired.

Resolves #23777.
2026-10-09 21:22:19 +00:00
Andrew Grigorev f916703b81 Merge remote-tracking branch 'origin/master' into maintenance/pr-115322-20261006
# Conflicts:
#	src/Common/SymbolIndex.cpp
2026-10-06 14:17:23 +03:00
Groene AIandClaude Opus 5.5 bacf245cf2 Start the wasm64 clickhouse local without growing its shared memory
`Build (wasm64)` / `Run clickhouse local under Node.js` fails rarely with
`RuntimeError: memory access out of bounds` in a pool worker before any
output (PRs #113726 and #116898, both unrelated diffs).

V8 checks some wasm accesses explicitly against the instance's copy of the
memory size, which another thread's `memory.grow` updates on this thread only
at its next interrupt (https://issues.chromium.org/issues/529880019, not
fixed in any Node release). On arm64 Linux that covers every plain store; on
x64 it covers `memory.fill` and atomics. `clickhouse local` started at
256 MiB and grew 7-8 times to ~930 MiB during startup (every pthread mallocs
an 8 MiB stack), while new pool workers made their first allocations, so a
worker writing a just-grown chunk trapped. The CI frames are dlmalloc
`malloc` (`wasm-function[575]`) under `__cxa_thread_atexit` in the first
statement of `ThreadFromThreadPool::worker()`.

Start at 2 GiB so that startup and small workloads never grow; untouched
pages cost no RSS and growth stays enabled. The binary-builder prewarm line
mirrors the link flags, so it changes too.

Measured on x64 with Node v24.19.0 from the builder image, 2000 runs of the CI
smoke query per arm on the master CI artifact: 8 traps (CI's exact frames)
with `--wasm-enforce-bounds-checks` and 12 with default flags at 256 MiB;
0 and 0 at 2 GiB, with no grow at all. A build of this tree: 0 traps in 2000
runs per flag set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:15:41 +00:00
Alexey Milovidov 14fdb5d5c6 Merge remote-tracking branch 'origin/master' into HEAD 2026-10-04 09:56:52 +00:00
Konstantin Bogdanov 44fec20b99 Merge branch 'master' into aarch64-arm-optimized-routines 2026-10-01 18:53:15 +02:00
Konstantin BogdanovandClaude Opus 5.5 d463f6aac4 Do not build or link optimized-routines under sanitizers
The `aor` definitions are strong. Under sanitizers the interceptors stay in
effect only because every routine in the archive happens to be intercepted
and the sanitizer runtimes are `--whole-archive`d ahead of the lazy `-laor`,
so no member is ever extracted. Adding a routine or reordering the link would
silently bypass the interceptors. Sanitized builds gain nothing from AOR, so
leave these functions with the libc there.

The target is also not defined when it is not linked (sanitizers, or
`ENABLE_LLVM_LIBC_MATH` off), so the Rust symbol localization in
`contrib/corrosion-cmake` does not use it as a reference archive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:39:25 +02:00
Raúl MarínandClaude Opus 5.5 ab24765c86 Drop .llvm_addrsig from the stripped Rust libraries
`strip_rust_symbols.sh` runs `ld -r` and `llvm-objcopy`, which leave the
address-significance table with `sh_link=0`. Since the link switched to
`--icf=safe`, lld ignores such tables and warns for every link:

ld.lld: warning: rust/workspace/lib_ch_rust_prql.a(stripped.o): --icf=safe
conservatively ignores SHT_LLVM_ADDRSIG [index 6] with sh_link=0

Removing the section keeps the same conservative folding without the warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:23:14 +02:00
Alexey Milovidov 40dad192c8 Merge branch 'master' into fix-arm-build-cpuflag 2026-09-19 17:59:35 +02:00
scanhex12andClaude Opus 5 da89a1b33e Merge branch 'master' into gpu-build-island
`Build (arm_tidy)` was failing on a duplicate `#include <IO/VarInt.h>` in
`src/Core/tests/gtest_settings.cpp`, a file this branch does not touch. Master
carried that duplicate for a few hours - every PR built in that window failed
the same way, and so did master itself - and has since reverted it. Re-running
the job replays the same merge commit, so it needs a fresh one.

No conflicts. `cmake/ccache.cmake` drops out of the diff: master has that change
already.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 00:31:51 +00:00
scanhex12andClaude Opus 5 cbfe64674d Cut the comment walls down
Only comments change here; every line of cmake and C is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 22:28:52 +00:00
scanhex12andClaude Opus 5 263bcb9bca [GPU] Build the CUDA island: cmake, contrib and the dlopen/glibc plumbing
Splits the build-system half of #119502 out of it, so that the pull request
there is the aggregation code and its tests alone.

What is here:

- `cmake/cuda.cmake`: the include half of `ch_gpu::cudart`, which every consumer
  of `ch_contrib::rmm` needs; `gpu_island_executable`, for the build-time tools
  on the island; and the shared `libstdc++` the island's host code is compiled
  against.
- `cmake/linux/default_libs.cmake`: where that `libstdc++` is appended, and why
  the order matters for the Itanium ABI runtime.
- `cmake/ccache.cmake`: a compiler launcher for `.cu` as well.
- `contrib/cudf-cmake`, `contrib/nvcomp-cmake`, `contrib/CMakeLists.txt`: cuDF
  and nvcomp as `ch_contrib::` targets.
- `contrib/cucascade`, and the `cuCollections` bump it needs.
- `base/glibc-compatibility`: the `__isoc23_strto*` aliases and
  `__libc_single_threaded`, which the island needs because it compiles against
  the host's headers and links against the sysroot's glibc.
- `programs/main.cpp`, `programs/keeper/keeper_main.cpp`: the `dlopen` override
  lifted in a GPU build, because the CUDA runtime reaches a device no other way.
- `.gitignore`: nvcomp is unpacked into `contrib/nvcomp` rather than vendored.

`contrib/cucascade` was a gitlink with no `.gitmodules` entry, so
`git submodule update --init` could not fetch it. Added it here.

`ENABLE_GPU` stays `OFF`, so nothing in a default build changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 12:01:24 +00:00
Konstantin Vedernikov 011c0ba199 Merge pull request #120421 from ClickHouse/speed-up-the-cuda-build
[GPU] speedup build
2026-09-17 15:23:28 +00:00
robot-clickhouse c9ae3d3463 Update autogenerated version to 26.10.1.1 and contributors 2026-09-16 16:53:10 +00:00
scanhex12andClaude Opus 5 14a2b58b4a Drop the comments
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 16:46:32 +00:00
scanhex12andClaude Opus 5 bacec79cd0 Cache nvcc's output, and stop asking it for PTX
Two settings of the CUDA toolchain that only ever cost time.

`cmake/ccache.cmake` never set `CMAKE_CUDA_COMPILER_LAUNCHER` - only the C and
C++ launchers - so nothing nvcc compiles was ever cached, and every new build
directory recompiled all of it. Measured on one translation unit of cuDF,
which is what the GPU island exists to compile: 129 s cold against 0.08 s on
a hit. Over that library it is the difference between paying 11 CPU-hours once
and paying it per build directory.

Not in depend mode, unlike C and C++. That mode reads the compiler's
dependency file rather than parsing includes, CMake drives nvcc with no
dependency flags at all, and without such a file ccache does not merely lose
its edge - it stops caching. On the same unit it reports an error, takes no
hit, and the second compilation costs the full 132 s.

`CMAKE_CUDA_ARCHITECTURES` becomes `75-real`, so nvcc emits the cubin for
`sm_75` and not also the PTX for `compute_75`. PTX is what the driver JITs when
it meets a card newer than anything the binary was built for, which a build
pinned to a single architecture of an experimental engine is not asking for,
and plain `75` made CMake pass `code=[compute_75,sm_75]` - the whole
translation unit compiled twice over.

`-lineinfo` moves behind `ENABLE_GPU_KERNEL_LINEINFO`, off by default. It maps
device instructions back to source lines, which Nsight Compute needs to
attribute a kernel's time and nothing else does - it says nothing about the
host code a debugger walks, which gets its `-g` elsewhere. On cuDF it was the
entire difference between a `RelWithDebInfo` island and a `Release` one, 60393
CPU-seconds against 39658, so a build that is never opened in a profiler paid
half again for nothing.

The measurements come from a tree with `contrib/cudf-cmake/CMakeLists.txt` and
`src/GPU` wired up. Neither is in master yet, so master compiles no CUDA at
all today and none of this changes a build here until they land - which is why
it is worth having in place before they do, rather than after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 15:31:56 +00:00
Alexey MilovidovandClaude Fable 5.1 0aba3edc74 Address review: restore the native AArch64 build-host preflight check
The AI review and a reviewer question on the deleted block pointed out that
removing the best-effort `/proc/cpuinfo` check for the modern AArch64 profile
does not remove the host dependency of a native build: intermediate tools such
as `protoc` and `llvm-tblgen` are still compiled with the target flags and
executed on the build host, so the failure only moved from an actionable
configure-time error to a later `SIGILL`. The check does not select the target
(that is done by `NO_ARMV81_OR_HIGHER` alone) and mirrors the preflight that
master has for `X86_ARCH_LEVEL`, so it is restored verbatim from master.

`cmake/cpu_features.cmake` now differs from master only in the compatibility
profile: `-march=armv8-a+crc` and Rust `target_feature=+crc` without `-neon`,
which is the actual fix for the `ring` build failure.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 09:53:19 +00:00
Alexey Milovidov 0abbb545f3 Merge remote-tracking branch 'origin/master' into fix-arm-build-cpuflag 2026-09-16 09:52:45 +00:00
Alexey Milovidov 64bddd3332 Merge pull request #118005 from navneet83/fix-lifetime-safety-warning-gate-clang23
Suppress `lifetime-safety-return-stack-addr-moved` from clang 23, not 24
2026-09-13 00:31:29 +00:00
Alexey Milovidov 98d3af8779 Merge pull request #118370 from groeneai/impl/coverage-drop-orphaned-finstrument-functions
Remove dead call-depth instrumentation from the per-test coverage build
2026-09-12 21:34:47 +00:00
Alexey Milovidov 43cd9eb7cd Merge pull request #119049 from ClickHouse/update-sysroots
Update contrib/sysroot: FreeBSD 14.5, Debian-based riscv64/loongarch64, drop unused files
2026-09-12 09:32:41 +00:00
Konstantin Bogdanov bcb9876d34 Update contrib/sysroot: FreeBSD 14.5, Debian-based riscv64/loongarch64, drop unused files
Sysroot changes (https://github.com/ClickHouse/sysroot, branch update-sysroots-2026-09):
- FreeBSD sysroots refreshed from 14.5-RELEASE (13.x is end-of-life); static
  archives and the target OS C++ headers are no longer checked in.
- linux-riscv64 rebuilt from Debian 13 packages (glibc 2.41, kernel headers 6.12,
  gcc 14) and linux-loongarch64 from Debian sid (glibc 2.43, kernel headers 7.1,
  gcc 16) with a reproducible refresh script.
- linux-s390x: OpenSSL blobs, duplicate gcc tree and libgcc_eh/libgcc_s removed.
- linux-aarch64: debug info stripped from the shared objects.
- README with provenance and update instructions for every sysroot.
- linux-x86_64, linux-aarch64, linux-s390x and linux-powerpc64le glibc versions
  are unchanged; they define the glibc floor of the release binaries.

Main repository:
- cmake/freebsd/toolchain-*.cmake, ci/jobs/build_toolchain.py: target triples
  *-freebsd14 to match the sysroot.
- cmake/linux/toolchain-riscv64.cmake: the sysroot has the Debian layout, GCC
  startup objects live under usr/, so --gcc-toolchain points there.
- contrib/liburing-cmake: glibc >= 2.43 includes <linux/openat2.h> from
  <fcntl.h>, which made the fallback definition of struct open_how in compat.h
  a redefinition on loongarch64. LIBURING_CONFIG_HAS_OPEN_HOW is now derived
  from the presence of linux/openat2.h in the sysroot.

Verified by building programs/clickhouse for s390x, riscv64, loongarch64,
FreeBSD x86_64 and aarch64.
2026-09-09 17:04:20 +02:00
Konstantin Bogdanov 99c1e5302b Merge branch 'master' into aarch64-arm-optimized-routines 2026-09-09 16:43:52 +02:00
Konstantin Bogdanov 444ffe1cd7 Merge pull request #118910 from ClickHouse/llvmlibc-whole-archive-thinlto
Fix Rust symbols shadowing llvm-libc under ThinLTO
2026-09-09 13:31:22 +00:00
Konstantin Bogdanov 4ccf76a433 Keep llvm-libc math on aarch64, take only string routines from AOR
The AOR scalar math (exp, exp2, log, log10, atan, atan2) added in
e687278fb9 is 0.5-2.5 ULP instead of correctly rounded. x86_64 keeps
llvm-libc's correctly-rounded implementations, so the same query started
printing different last digits per architecture, which the stateless
tests caught on arm: 02224_s2_test_const_columns, 01849_geoToS2 and
01851_s2_to_geo (s2 calls atan2 internally), 04092_kql_conformance_baby_kusto
(log10(0.1) returned -0.9999999999999999 instead of -1) and
03233_dynamic_in_functions:
https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?PR=109239&sha=e687278fb9fc24b2a96e90201410f3c5b7758f29&name_0=PR

Correct rounding is what makes results architecture-independent, so the
math goes back to llvm-libc everywhere; the h3 trig cost on aarch64
(~10-16% on three h3 perf queries) is the accepted price. The AOR
AdvSIMD/MTE string routines stay - byte semantics have no rounding, and
they are the larger win (memcpy +26-37%, memcmp +50-80%, strlen 2.9x).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit bf8c209ff4)
2026-09-09 00:52:42 +02:00
Konstantin Bogdanov 11b232cfc4 Add ARM optimized-routines for aarch64 scalar math and string functions
New contrib optimized-routines (upstream ARM-software/optimized-routines,
no fork needed - built as-is): on aarch64, scalar exp, exp2, log, log10,
atan, atan2 replace the llvm-libc generic implementations (excluded from
libllvmlibc there), and the AdvSIMD/MTE string routines - memcpy,
memmove, memcmp, memchr, strlen, strcmp, strchr, strnlen - replace the
mix of musl generic C, musl's vendored 2020 AOR asm, and llvm-libc weak
definitions. Both archives are linked with --whole-archive, so the
definitions win the link structurally.

Measured on Graviton4 (Neoverse-V2) against the previous static-binary
state: exp 2.1x, exp2 2.2x, atan 1.7x, atan2 1.6x, memcpy +26-37%,
memmove ~2x on small sizes, memcmp +50-80%, strlen 2.9x, memchr 3x.
This closes the gap to glibc, whose aarch64 libm and ifunc-selected
string routines derive from the same upstream. The SVE string variants
are deliberately not used: on 128-bit-SVE cores they measure up to 3x
slower than the NEON/MTE ones. AOR math scalars are 0.5-2.5 ULP instead
of llvm-libc's correct rounding, matching glibc's accuracy class.

Motivated by the h3ToGeoBoundary regression in the perf comparison:
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109239

Verified under qemu-aarch64 with a static test binary: exp/exp2/log/
log10/atan/atan2 exact on reference points; strlen/memcmp/memchr/strcmp
correct incl. the MTE variants. x86_64 builds are unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit e687278fb9)
2026-09-09 00:52:42 +02:00
Konstantin Bogdanov 3908c1fae4 Link llvm-libc with --whole-archive so later archives cannot shadow it
Archive symbol resolution is first-definition-wins in command-line
order, and the Rust static libraries precede liblibllvmlibc.a on the
link line. Whenever symbol localization is bypassed (as happened under
ThinLTO due to the llvm-nm bitcode output format), the libm functions
Rust's compiler_builtins exports (cbrt, fmod, fma - built for baseline
x86-64) silently win over the llvm-libc ones. Loading every llvm-libc
member ahead of all objects and archives makes the resolution
structural instead of order-dependent: a later archive can never supply
an already-defined symbol. compiler_builtins keeps each function in its
own archive member, so no duplicate definitions arise.

This also covers the mem functions, previously forced per-symbol with
-u; those flags are kept as a backstop.

Confirmed by the perf report for the static-binary PR (1.5x cbrt
regression on amd):
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109239

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 2e3f2f1df6)
(cherry picked from commit 5fc022dc2e)
2026-09-09 00:52:25 +02:00
Konstantin Bogdanov ed5e6fdadb Accept bitcode members in localize_rust_c_symbols reference archives
Under ThinLTO (enabled in CI release builds via ENABLE_THINLTO=1) the
reference archives liblibllvmlibc.a and libmusl.a contain LLVM bitcode
members, for which llvm-nm prints dashes instead of a hex address. The
defined-globals regex required a hex address, so the reference symbol
set came out empty, nothing was localized in the Rust archives, and the
cbrt from Rust compiler_builtins (baseline x86-64, musl-ported soft
implementation) shadowed the llvm-libc one in the linked binary. This
showed up as a 1.5x cbrt regression in the perf comparison of the
static-binary PR:
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109239

Local non-LTO builds were unaffected, which is why the problem only
reproduced in CI artifacts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 0b7bbbf8e0)
(cherry picked from commit 96780624ca)
2026-09-09 00:52:25 +02:00
Konstantin Bogdanov 5fc022dc2e Link llvm-libc with --whole-archive so later archives cannot shadow it
Archive symbol resolution is first-definition-wins in command-line
order, and the Rust static libraries precede liblibllvmlibc.a on the
link line. Whenever symbol localization is bypassed (as happened under
ThinLTO due to the llvm-nm bitcode output format), the libm functions
Rust's compiler_builtins exports (cbrt, fmod, fma - built for baseline
x86-64) silently win over the llvm-libc ones. Loading every llvm-libc
member ahead of all objects and archives makes the resolution
structural instead of order-dependent: a later archive can never supply
an already-defined symbol. compiler_builtins keeps each function in its
own archive member, so no duplicate definitions arise.

This also covers the mem functions, previously forced per-symbol with
-u; those flags are kept as a backstop.

Confirmed by the perf report for the static-binary PR (1.5x cbrt
regression on amd):
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109239

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 2e3f2f1df6)
2026-09-09 00:34:28 +02:00
Konstantin Bogdanov 96780624ca Accept bitcode members in localize_rust_c_symbols reference archives
Under ThinLTO (enabled in CI release builds via ENABLE_THINLTO=1) the
reference archives liblibllvmlibc.a and libmusl.a contain LLVM bitcode
members, for which llvm-nm prints dashes instead of a hex address. The
defined-globals regex required a hex address, so the reference symbol
set came out empty, nothing was localized in the Rust archives, and the
cbrt from Rust compiler_builtins (baseline x86-64, musl-ported soft
implementation) shadowed the llvm-libc one in the linked binary. This
showed up as a 1.5x cbrt regression in the perf comparison of the
static-binary PR:
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109239

Local non-LTO builds were unaffected, which is why the problem only
reproduced in CI artifacts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 0b7bbbf8e0)
2026-09-09 00:34:27 +02:00
Groene AI 1717a0eb5d Coverage: drop the orphaned -finstrument-functions-after-inlining instrumentation
0599d405a0 replaced the -finstrument-functions shadow stack with an entry
call count read from the LLVM profile counters, but WITH_COVERAGE_DEPTH kept
injecting -finstrument-functions-after-inlining into the global C and C++ flags.
Every function entry and exit in the whole binary, contrib included, therefore
still calls two empty stubs in base/base/coverage.cpp that nothing consumes.

base/base/CMakeLists.txt compiles base/base with ${COVERAGE_FLAGS}, so the stubs
carry their own profile counters: no_instrument_function stops them recursing, it
does not stop them being profiled. Their entry counters are incremented once per
function entry and once per function exit program-wide, which makes them the two
hottest function counters in the process: on a SELECT count() FROM
numbers(10000000) they reach 6213755 and 6212763, 5.3x the next hottest function
counter and together 23.5% of all counter increments.
With -mllvm -runtime-counter-relocation and
the %c pattern both effective, those counters live in a MAP_SHARED mapping of the
profile pool file, so processes that run concurrently store into the same
file-backed words at function-call frequency.

The removal cannot change what per-test coverage measures: the hooks are empty,
min_depth comes from the entry counter (or from XRay where
CLICKHOUSE_XRAY_INSTRUMENT_COVERAGE is defined), and the WITH_COVERAGE_DEPTH
macro that compiles in CoverageCollection.cpp, LLVMCoverageMapping.cpp and
SYSTEM SET COVERAGE TEST comes from the CMake option, not from this flag.

Also correct the option description, the coverage.h min_depth doc and the two
build-flag lines in .claude/docs/relevant_tests.md, which all still described the
deleted shadow stack.
2026-09-06 02:50:37 +00:00