Change default x86 build target from x86-64-v2 (SSE4.2) to x86-64-v3 (AVX2) by Algunenano · Pull Request #90043 · ClickHouse/ClickHouse · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
1e1dd89
Check performance with x86-64-v3
Algunenano Feb 20, 2026
7bb9509
Remove unnecessary dispatch
Algunenano Feb 20, 2026
5d8117b
And adjust ENABLE_MULTITARGET_CODE
Algunenano Feb 20, 2026
edf135f
Fix
Algunenano Feb 20, 2026
4046d2e
Restore removed implementation for Int8
Algunenano Feb 22, 2026
e099c61
Replace multiply-based fill loops with accumulator pattern
Algunenano Feb 22, 2026
13f226d
Prevent bad auto-vectorization of UInt64->Float32 conversion on x86
Algunenano Feb 23, 2026
8ba3244
Use compat build for non-AVX2 systems in install script
Algunenano Feb 23, 2026
9bc173a
Merge blessed/master
Algunenano Feb 24, 2026
bddd90b
Remove llvm-libc v2/v3 runtime dispatch on x86-64
Algunenano Feb 24, 2026
b0081f2
Restore early return for empty input in `mortonEncode`
Algunenano Feb 24, 2026
c064194
Update QEMU-based tests for x86-64-v3 default
Algunenano Feb 25, 2026
0de5c24
Skip QEMU-based instruction tests for x86-64-v3 builds
Algunenano Feb 25, 2026
101d417
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Feb 25, 2026
a70f393
Undo bad merge conflict
Algunenano Feb 25, 2026
bd58bf5
Remove unnecessary llvmlibc_dispatch
Algunenano Feb 25, 2026
601340d
Remove `checkRequiredInstructions` and its test
Algunenano Feb 25, 2026
b32d9fc
Let simdjson use AVX2 directly on x86-64-v3 builds
Algunenano Feb 25, 2026
43a4590
Fix libdivide SIMD selection and ensure consistent inclusion
Algunenano Feb 25, 2026
4dc97a0
Remove unnecessary dispatch
Algunenano Feb 25, 2026
16fd39e
Update default_libs.cmake
Algunenano Feb 25, 2026
72d4d1b
Disable auto-vectorization for integer division and modulo loops
Algunenano Feb 26, 2026
1bbcb27
Prevent LTO from inlining `iota` and `iotaWithStep`
Algunenano Feb 26, 2026
6bdabce
Force x86-64-v2 for musl scalar math functions on v3+ builds
Algunenano Feb 27, 2026
16485cd
Disable loop unrolling for scalar math function calls
Algunenano Feb 27, 2026
29da5dc
Remove FastOps runtime dispatch on x86-64-v3+ builds
Algunenano Feb 27, 2026
b42f8a1
Merge branch 'analyze-assembly' into x86v3
antonio2368 Mar 4, 2026
e886ebf
Fix x86-64-v3 performance regressions in aggregate functions and arra…
antonio2368 Mar 4, 2026
2187b14
Merge remote-tracking branch 'origin/master' into x86v3
antonio2368 Mar 4, 2026
28afd1f
Remove musl math v2 override; disable `vzeroupper` on v3+ builds
Algunenano Mar 5, 2026
6df0283
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Mar 6, 2026
e1cb44f
Fix indentation of `BEGIN_X86_64_V3_SPECIFIC_CODE` macro
Algunenano Mar 10, 2026
b035278
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Mar 10, 2026
dde7b80
Fix simdjson fallback for non-x86 platforms
Algunenano Mar 10, 2026
1933f2f
Limit vectorization width in `ColumnString::replicate` prefix-sum loop
Algunenano Mar 10, 2026
cbd6e0e
Pass `COMPILER_FLAGS` to compiler-rt sanitizer runtime build
Algunenano Mar 10, 2026
d14b0de
Apply `no_vectorize` to `RightConstant` division/modulo path
Algunenano Mar 11, 2026
11f2925
Use vectorize(disable) instead of vectorize_width(2) in prefix-sum loop
Algunenano Mar 11, 2026
b7f1342
Fix preprocessor guard: `__AVX__` -> `__AVX2__` in `isAllASCII`
Algunenano Mar 11, 2026
ac912b4
Remove dead SSE2 include from ColumnsCommon.h
Algunenano Mar 11, 2026
16b55b9
Remove redundant runtime arch check in `sliceHasImplAnyAll`
Algunenano Mar 11, 2026
28d1a82
Validate host CPU flags for the requested x86 microarchitecture level
Algunenano Mar 11, 2026
4ba769d
Update Docker image ISA requirement from SSE3 to x86-64-v3
Algunenano Mar 12, 2026
0d4c65c
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Mar 16, 2026
18cbe01
Localize C math symbols from Rust static libraries
Algunenano Mar 16, 2026
895543a
Handle non-ELF members in Rust archives during symbol localization
Algunenano Mar 16, 2026
925d7f6
Fix localize_rust_c_symbols exit code and PRQL race
Algunenano Mar 16, 2026
d7f97a3
Allow vectorization of float modulo operations
Algunenano Mar 17, 2026
c51546c
Disable unrolling of scalar UInt64->Float32 conversion on x86
Algunenano Mar 17, 2026
f0abed3
Disable vectorization of libdivide modulo-by-constant loop
Algunenano Mar 17, 2026
ef38741
Restrict vectorize(disable) on libdivide modulo loop to x86 only
Algunenano Mar 18, 2026
68e6c80
Support fetching all log files in claude tool
Algunenano Mar 18, 2026
0aa821e
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Mar 31, 2026
8b58b78
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 1, 2026
775886c
Fix Base58 build: remove TargetSpecific multitarget dispatch
Algunenano Apr 1, 2026
e6d0787
Fix unused variable warning: move base58_chars into non-AVX2 guard
Algunenano Apr 1, 2026
5efb7ac
Fix Rust symbol localization build ordering
Algunenano Apr 1, 2026
714c3b0
Fix fastops ARM build: guard x86 dispatch with `ARCH_AMD64`
Algunenano Apr 1, 2026
67ade8e
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 7, 2026
1c031cf
Intel is the sole responsible of the bad state of x86
Algunenano Apr 7, 2026
d33bf30
Switch libdivide to `BRANCHFREE` and optimize div/mod SIMD paths
Algunenano Apr 7, 2026
f5f855c
Clean up stale comments in modulo pow2 path
Algunenano Apr 7, 2026
1635a0f
Remove ALWAYS_INLINE from `findExtremeImpl` to reduce i-cache pressure
Algunenano Apr 7, 2026
0977b4d
Use BRANCHFULL libdivide for <=32-bit, BRANCHFREE+AVX2 for 64-bit
Algunenano Apr 8, 2026
94abccd
Fix buffer overflow in AVX2 modulo path for narrowing result types
Algunenano Apr 8, 2026
7fceedc
Add `NO_INLINE` to `hasAll` SIMD specializations to prevent LTO bloat
Algunenano Apr 8, 2026
5efd4c7
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 8, 2026
bc89b30
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 10, 2026
1ebc66e
Clarify perf-report skill: emphasize mandatory master cross-reference…
Algunenano Apr 10, 2026
128d85c
Fix LinfNorm regression: only suppress vectorization for sum-based norms
Algunenano Apr 10, 2026
f740340
Fix UInt64 modulo-by-constant regression on x86-64-v3
Algunenano Apr 10, 2026
ac5f7ba
Avoid 256-bit stores in LZ4 match copies to prevent store-forwarding …
Algunenano Apr 10, 2026
45f5a91
Suppress unrolling in array() element interleave loop
Algunenano Apr 10, 2026
1cc56d8
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 11, 2026
71488a0
Fix arrayDotProduct build after merge with master
Algunenano Apr 11, 2026
1d2a2ef
Add batched addBatchSinglePlace for AggregateFunctionDistinct
Algunenano Apr 11, 2026
98bf633
Fix style: Allman-style brace for requires clause
Algunenano Apr 11, 2026
3ef2871
Fix SIGABRT in intDiv with zero divisor on x86-64-v3
Algunenano Apr 11, 2026
f2ffe76
Fix base58 fast decoder, intDiv crash, and fastops ARM build
Algunenano Apr 11, 2026
ab70466
Fix clang-tidy warnings: default arg, unused var, redundant cast
Algunenano Apr 11, 2026
c61431f
Disable ENABLE_MULTITARGET_CODE for non-default x86 arch levels
Algunenano Apr 11, 2026
18f38a6
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano Apr 12, 2026
e10d6de
Work around clang-21 codegen bug in join selectivity computation
Algunenano Apr 13, 2026
1754221
Address review: fix default comment, add popcnt to v2 preflight, stre…
Algunenano Apr 13, 2026
031970c
Address review: complete v3 preflight flags, fix error message wording
Algunenano Apr 13, 2026
7ca3657
Address review: fix default comment, simplify CPU preflight checks
Algunenano Apr 13, 2026
7798fed
Add LLVM bug tracker reference to the codegen workaround
Algunenano Apr 13, 2026
fb965b2
Work around LLVM x86 backend bug in join selectivity computation
Algunenano Apr 13, 2026
3a62f4b
Merge branch 'master' into x86v3
Algunenano Apr 13, 2026
782aaef
Compile arrayNorm.cpp at x86-64-v2 level on v3 builds
Algunenano Apr 14, 2026
9b47f71
Fix install script abort on non-AVX2 hosts, compile arrayNorm at v2
Algunenano Apr 14, 2026
f8e8e34
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano May 4, 2026
5322e34
Simplify arrayNorm v2 compile flags
Algunenano May 4, 2026
483442c
Compile FunctionsStringDistance.cpp at v2 to fix Jaccard regression
Algunenano May 5, 2026
d3578a7
Compile randomString.cpp at v2 to fix vzeroupper-in-loop
Algunenano May 5, 2026
bb05e83
Merge remote-tracking branch 'mine/x86v3' into x86v3
Algunenano May 5, 2026
f46df5e
Split QuantileTiming::merge to keep hot tiny path inline
Algunenano May 5, 2026
020709f
Strengthen v4 host check to detect Knights-Landing-style AVX-512 CPUs
Algunenano May 5, 2026
1cfd404
Rename example class `Myv3Impl` -> `Myv4Impl` in `PerformanceAdaptors.h`
Algunenano May 6, 2026
fafaed1
Compile `FunctionsHashingMisc.cpp` at v2 to fix empty-string hash reg…
Algunenano May 6, 2026
fd8c3de
Skip the intermediate `Field` for the const buckets argument
Algunenano May 6, 2026
143e4d8
Compile `arrayDistance.cpp` at v2 to fix BF16 distance regressions
Algunenano May 6, 2026
41e4556
Compute trunc as `x - x % scale` to avoid the trailing multi-word mul…
Algunenano May 6, 2026
a8f4b62
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano May 7, 2026
0e45100
Short-circuit same-width integer conversions to `std::memcpy`
Algunenano May 7, 2026
635d4c0
Compile `StorageGenerateRandom.cpp` at v2 to fix `generate_table_func…
Algunenano May 7, 2026
b1dae92
Outline `std::log` in `NaiveBayesClassifier::classify` to avoid v3 LT…
Algunenano May 7, 2026
59ecbf0
Compress the v3-override comments in CMakeLists into TODO blurbs
Algunenano May 7, 2026
a61ed3d
Disable vectorizers on Decimal128 multiply hot loop at v3
Algunenano May 7, 2026
03d2968
Fix dispatch example in TargetSpecific.h to call default impl
Algunenano May 8, 2026
afa1c5b
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano May 8, 2026
4aa9199
Address PR review feedback: trim comments, use natural language
Algunenano May 8, 2026
0ea30f0
Anchor `objcopy`->`ar` substitution to end of `OBJCOPY` path
Algunenano May 8, 2026
8fbd1f7
Rewrite only the basename when deriving `ar` from `OBJCOPY`
Algunenano May 10, 2026
11e6269
Restore v3 dispatch for `FunctionAnyHash` / `FunctionIntHash`
Algunenano May 11, 2026
e1b16e7
Merge remote-tracking branch 'blessed/master' into x86v3
Algunenano May 12, 2026
66f976d
Disable BMI on `AggregateFunctionUniq.cpp` to fix `uniq_stored` regre…
Algunenano May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
25 changes: 14 additions & 11 deletions .claude/skills/perf-report/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ Do NOT summarize, collapse, or hide entries. Do NOT dismiss anything as "noise"

### 3. Cross-reference with master history

For every test that shows as slower or faster above 1.10x, check the public CI database to determine if this is a known flaky test or a genuine change introduced by the PR.
**This step is MANDATORY.** For every test that shows as slower or faster above 1.10x, check the public CI database to determine if this is a known flaky test or a genuine change introduced by the PR. Do NOT skip this step or use alternative approaches (like manually fetching perf reports from other PRs).

Query the public CI database:
Query the `default.checks` table on `play.clickhouse.com` with `user=explorer`:

```bash
clickhouse client --host play.clickhouse.com --user explorer --secure -q "
clickhouse client --format PrettyCompactNoEscapes --host play.clickhouse.com --user explorer --secure --query "
SELECT
replaceRegexpOne(test_name, '::(new|old)$', '') AS test,
countIf(test_status = 'slower') AS slower_count,
Expand All @@ -58,22 +58,25 @@ SELECT
count() AS total_runs
FROM default.checks
WHERE pull_request_number = 0
AND check_name LIKE '%Performance%amd%' -- or arm
AND check_name LIKE '%Performance%amd%'
AND check_start_time >= now() - INTERVAL 30 DAY
AND test_name IN (
'test_name #N::new',
...
'norm_distance #2::new',
'array_sort #0::new'
)
GROUP BY test
ORDER BY slower_count DESC, test
"
```

**Important:**
- `pull_request_number = 0` means master commits
- Test names in the DB have `::new` and `::old` suffixes — query with `::new`
- Use `%amd%` for AMD results and `%arm%` for ARM results
- Query both architectures separately
Run **one query per architecture** — use `'%Performance%amd%'` for x86 and `'%Performance%arm%'` for ARM.

**Critical details:**
- **Host:** `play.clickhouse.com`, **user:** `explorer` (NOT `play`)
- **Table:** `default.checks` (NOT `perftest` or other tables)
- `pull_request_number = 0` filters to master-only commits (no PR noise)
- Test names in the DB have `::new` and `::old` suffixes — always query with `::new`
- Include ALL changed tests in a single IN clause to minimize round-trips

### 4. Classify each change

Expand Down
38 changes: 26 additions & 12 deletions cmake/cpu_features.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,27 +85,42 @@ elseif (ARCH_PPC64LE)

elseif (ARCH_AMD64)
# x86-64 microarchitecture levels (https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels):
# 1 SSE2 baseline, maximum compatibility with older/embedded hardware
# 2 SSE4.2, SSSE3, POPCNT (default, matches ClickHouse's historical baseline)
# 3 AVX2, BMI1/2, FMA, F16C etc.
# 4 AVX-512F/BW/CD/DQ/VL
set (X86_ARCH_LEVEL "2" CACHE STRING "x86-64 microarchitecture level (1, 2, 3, 4)")
# 1 - SSE2 baseline, maximum compatibility with older/embedded hardware
# 2 - SSE4.2, SSSE3, POPCNT (ClickHouse's historical baseline)
# 3 - AVX2, BMI1/2, FMA, F16C, LZCNT, MOVBE etc. (default)
# 4 - AVX-512F/BW/CD/DQ/VL
set (X86_ARCH_LEVEL "3" CACHE STRING "x86-64 microarchitecture level (1, 2, 3, 4)")
Comment thread
Algunenano marked this conversation as resolved.
set_property (CACHE X86_ARCH_LEVEL PROPERTY STRINGS "1" "2" "3" "4")

if (NOT X86_ARCH_LEVEL MATCHES "^[1-4]$")
message (FATAL_ERROR "X86_ARCH_LEVEL must be one of: 1, 2, 3, 4 (got '${X86_ARCH_LEVEL}')")
endif ()

# Same best-effort check for x86 as above for ARM.
# Best-effort check: verify that the build host supports the requested microarchitecture level. Build-time tools
# (tablegen, code generators) are compiled with these flags and will crash with SIGILL otherwise.
if (OS_LINUX AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64" AND X86_ARCH_LEVEL VERSION_GREATER_EQUAL 2)
# Test for flags in the default v2 profile.
# Test for a representative flag at each level. We intentionally keep this simple - no real CPU has avx2 without
# fma/bmi2, so checking the headline flag is enough while avoiding false positives from /proc/cpuinfo quirks
# (containers, nested virtualization, unusual flag naming).
set (X86_REPRESENTATIVE_FLAG "sse4_2")
if (X86_ARCH_LEVEL VERSION_GREATER_EQUAL 3)
set (X86_REPRESENTATIVE_FLAG "avx2")
endif ()
if (X86_ARCH_LEVEL VERSION_GREATER_EQUAL 4)
Comment thread
Algunenano marked this conversation as resolved.
# `x86-64-v4` requires AVX-512 F/BW/CD/DQ/VL. Knights Landing has `avx512f` but lacks BW/DQ/VL, so check one
# of those instead - any CPU with `avx512vl` will also have F.
set (X86_REPRESENTATIVE_FLAG "avx512vl")
endif ()
execute_process(
COMMAND grep -P "^(?=.*ssse3)(?=.*sse4_1)(?=.*sse4_2)" /proc/cpuinfo
COMMAND grep -P "(?=.*${X86_REPRESENTATIVE_FLAG})" /proc/cpuinfo
OUTPUT_VARIABLE FLAGS)
if (NOT FLAGS)
MESSAGE(FATAL_ERROR "The build machine does not satisfy the minimum CPU requirements, try to run cmake with -DX86_ARCH_LEVEL=1")
endif()
endif()
message (FATAL_ERROR
"The build machine does not support x86-64-v${X86_ARCH_LEVEL} "
"(${X86_REPRESENTATIVE_FLAG} not found in /proc/cpuinfo). "
"Run cmake with -DX86_ARCH_LEVEL=<level> to lower the requirement.")
endif ()
endif ()

# ClickHouse can be cross-compiled (e.g. on an ARM host for x86) but it is also possible to build ClickHouse on x86 w/o AVX for x86 w/
# AVX. We only assume that the compiler can emit certain SIMD instructions, we don't care if the host system is able to run the binary.
Expand All @@ -119,7 +134,6 @@ elseif (ARCH_AMD64)
set (COMPILER_FLAGS "${COMPILER_FLAGS} -mpclmul")
list (APPEND RUSTFLAGS_CPU "-C" "target-feature=+pclmulqdq")
endif ()

else ()
# RISC-V + exotic platforms
endif ()
17 changes: 2 additions & 15 deletions cmake/linux/default_libs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,8 @@ endif()

if (ENABLE_LLVM_LIBC_MATH)
link_directories("${CMAKE_BINARY_DIR}/contrib/libllvmlibc-cmake")

if (ARCH_AMD64)
if (X86_ARCH_LEVEL VERSION_LESS 2)
# Compat mode: single library, no dispatch
target_link_libraries(global-libs INTERFACE libllvmlibc)
set (DEFAULT_LIBS "${DEFAULT_LIBS} -llibllvmlibc")
else()
# Dispatch mode: v2/v3 variants with runtime CPU detection
target_link_libraries(global-libs INTERFACE llvmlibc_dispatch libllvmlibc_x86_64_v2 libllvmlibc_x86_64_v3)
set (DEFAULT_LIBS "${DEFAULT_LIBS} -lllvmlibc_dispatch -llibllvmlibc_x86_64_v2 -llibllvmlibc_x86_64_v3")
endif()
elseif (ARCH_AARCH64)
target_link_libraries(global-libs INTERFACE libllvmlibc)
set (DEFAULT_LIBS "${DEFAULT_LIBS} -llibllvmlibc")
endif()
target_link_libraries(global-libs INTERFACE libllvmlibc)
set (DEFAULT_LIBS "${DEFAULT_LIBS} -llibllvmlibc")
endif()

if (OS_ANDROID)
Expand Down
134 changes: 134 additions & 0 deletions cmake/localize_rust_c_symbols.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env bash
#
# Localize known C library symbols in a Rust static library (.a).
#
# Rust static libraries bundle compiler_builtins and libm, which export
# standard C symbols (cbrt, fma, sin, memcpy, __muloti4, etc.) as globals.
# When linked before our own C implementations (libllvmlibc, glibc-compat),
# these silently win — bypassing our -falign-functions=64, -march, and other
# optimization flags.
#
# This script localizes those known C library symbols so the linker picks
# our own implementations instead. All other symbols (Rust-mangled, crate
# FFI, etc.) are left untouched.
#
# Usage: localize_rust_c_symbols.sh <library.a> <objcopy>

set -eu

LIB_PATH="$1"
OBJCOPY="$2"

if [ -z "$LIB_PATH" ] || [ -z "$OBJCOPY" ]; then
echo "Usage: $0 <library.a> <objcopy>" >&2
exit 1
fi

if [ ! -f "$LIB_PATH" ]; then
echo "Error: Rust library not found: $LIB_PATH" >&2
echo "If this is a workspace subcrate, set IMPORTED_LOCATION on the target" >&2
echo "before calling clickhouse_config_crate_flags()." >&2
exit 1
fi

# Known C library symbols that Rust's compiler_builtins / libm may export.
# This list covers:
# - C math functions (libm)
# - Compiler-rt builtins (__muloti4, __divti3, etc.)
# - C string/memory functions that may be provided by Rust
KNOWN_C_SYMBOLS=(
# Math functions (float64)
cbrt cos sin tan acos asin atan atan2
exp exp2 exp10 log log2 log10 log1p expm1
pow sqrt hypot
fma fmod remainder
ceil floor round trunc nearbyint rint
copysign fabs fdim fmax fmin
erf erfc tgamma lgamma
frexp ldexp modf scalbn ilogb logb
nextafter nexttoward
# Math functions (float32)
cbrtf cosf sinf tanf acosf asinf atanf atan2f
expf exp2f exp10f logf log2f log10f log1pf expm1f
powf sqrtf hypotf
fmaf fmodf remainderf
ceilf floorf roundf truncf nearbyintf rintf
copysignf fabsf fdimf fmaxf fminf
erff erfcf tgammaf lgammaf
frexpf ldexpf modff scalbnf ilogbf logbf
nextafterf nexttowardf
# Math functions (long double)
ceill floorl roundl truncl
sqrtl frexpl ldexpl scalbnl
# Compiler-rt integer builtins
__absvdi2 __absvsi2 __absvti2
__addvdi3 __addvsi3 __addvti3
__cmpdi2 __cmpti2
__divdc3 __divsc3
__muldc3 __mulsc3
__mulvdi3 __mulvsi3 __mulvti3
__negdf2 __negsf2 __negdi2 __negti2
__negvdi2 __negvsi2 __negvti2
__paritydi2 __paritysi2 __parityti2
__popcountdi2 __popcountsi2 __popcountti2
__muloti4
)

# Collect which of these actually exist as global symbols in the library
TMPFILE=$(mktemp)
WORK_DIR=""
cleanup() { rm -f "$TMPFILE"; [ -n "$WORK_DIR" ] && rm -rf "$WORK_DIR"; true; }
trap cleanup EXIT

if ! command -v llvm-nm >/dev/null 2>&1; then
echo "Error: llvm-nm not found in PATH (required for Rust C-symbol localization)" >&2
exit 1
fi

# Get all global defined symbols from the library. llvm-nm may print per-member errors for non-ELF archive
# members (e.g. debug metadata objects) - those are non-fatal as long as at least one ELF member is read.
# A truly broken/missing archive produces empty output and is caught below.
llvm-nm "$LIB_PATH" 2>/dev/null \
Comment thread
Algunenano marked this conversation as resolved.
| grep -E '^[0-9a-f]+ [TDBCWV] ' \
| awk '{print $3}' \
| sort -u \
> "$TMPFILE" || true

if [ ! -s "$TMPFILE" ]; then
echo "Error: llvm-nm produced no symbols for $LIB_PATH; cannot localize Rust C symbols" >&2
exit 1
fi

# Build objcopy flags for symbols that exist in both lists
LOCALIZE_FLAGS=""
for sym in "${KNOWN_C_SYMBOLS[@]}"; do
if grep -qxF "$sym" "$TMPFILE"; then
LOCALIZE_FLAGS="$LOCALIZE_FLAGS --localize-symbol=$sym"
fi
done

if [ -n "$LOCALIZE_FLAGS" ]; then
# Try direct objcopy on the archive first (fast path).
# Some Rust archives contain non-ELF members (e.g. debug metadata objects)
# that cause llvm-objcopy to fail. In that case, fall back to extracting
# individual members, processing only valid ELF objects, and repacking.
if ! $OBJCOPY $LOCALIZE_FLAGS "$LIB_PATH" 2>/dev/null; then
# Substitute only inside the basename so a directory containing `objcopy`
# is not rewritten and a versioned name like `llvm-objcopy-21` still maps
# to `llvm-ar-21`.
OBJCOPY_NAME="${OBJCOPY##*/}"
AR_NAME="${OBJCOPY_NAME/objcopy/ar}"
if [ "$OBJCOPY_NAME" = "$OBJCOPY" ]; then
AR="$AR_NAME"
else
AR="${OBJCOPY%/*}/$AR_NAME"
fi
WORK_DIR=$(mktemp -d)

(cd "$WORK_DIR" && "$AR" x "$LIB_PATH")
for obj in "$WORK_DIR"/*.o; do
$OBJCOPY $LOCALIZE_FLAGS "$obj" 2>/dev/null || true
Comment thread
Algunenano marked this conversation as resolved.
done
"$AR" rcs "$LIB_PATH" "$WORK_DIR"/*.o
fi
fi
43 changes: 43 additions & 0 deletions contrib/corrosion-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ function(clickhouse_import_crate)
enable_dummy_launchers_if_needed()
endfunction()

# Configure a Rust crate target with ClickHouse-specific flags.
function(clickhouse_config_crate_flags target_name)
corrosion_set_env_vars(${target_name} "CFLAGS=${RUST_CFLAGS}")
corrosion_set_env_vars(${target_name} "CXXFLAGS=${RUST_CXXFLAGS}")
Expand Down Expand Up @@ -257,4 +258,46 @@ function(clickhouse_config_crate_flags target_name)
# Refs: https://github.com/rust-lang/cargo/issues/15099#issuecomment-2732847355
corrosion_set_env_vars(${target_name} "CARGO_NET_OFFLINE=true")
corrosion_link_libraries(${target_name} cxx)

# Localize all C-namespace symbols from Rust static libraries so they
# don't shadow our own implementations (libllvmlibc, glibc-compat).
# Rust's compiler_builtins exports cbrt, fma, sin, etc. as global symbols;
# without this, they silently win at link time and bypass our -falign-functions=64
# and -march flags, causing performance regressions.
#
# For workspace crates the .a may land in a parent directory rather than
# CMAKE_CURRENT_BINARY_DIR. Set IMPORTED_LOCATION on the target before
# calling this function if the default path is wrong (see wasmtime for an
# example).
get_target_property(_rust_lib_path ${target_name} IMPORTED_LOCATION)
if (NOT _rust_lib_path OR _rust_lib_path MATCHES "NOTFOUND")
set(_rust_lib_path "${CMAKE_CURRENT_BINARY_DIR}/lib${target_name}.a")
endif()

# Skip on Darwin (Mach-O), ppc64le (broken .eh_frame), and dummy builds.
if (CMAKE_OBJCOPY AND NOT OS_DARWIN
AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le"
AND NOT CMAKE_AR MATCHES "dummy_compiler_linker")
# Verify the library path looks plausible at configure time. The file
# won't exist yet (cargo hasn't run), but the parent directory must exist
# and the filename must end in .a — otherwise someone forgot to set
# IMPORTED_LOCATION for a workspace subcrate.
get_filename_component(_rust_lib_dir "${_rust_lib_path}" DIRECTORY)
if (NOT IS_DIRECTORY "${_rust_lib_dir}")
message(FATAL_ERROR
"localize_rust_c_symbols: output directory '${_rust_lib_dir}' for "
"target '${target_name}' does not exist. If this is a workspace "
"subcrate, set IMPORTED_LOCATION on the target before calling "
"clickhouse_config_crate_flags(). Expected library: ${_rust_lib_path}")
endif()

add_custom_target(localize_rust_c_${target_name}
COMMAND bash "${ClickHouse_SOURCE_DIR}/cmake/localize_rust_c_symbols.sh"
"${_rust_lib_path}" "${CMAKE_OBJCOPY}"
COMMENT "Localizing C-namespace symbols in ${target_name}"
VERBATIM
)
add_dependencies(localize_rust_c_${target_name} cargo-build_${target_name})
add_dependencies(${target_name} localize_rust_c_${target_name})
endif()
endfunction()
28 changes: 17 additions & 11 deletions contrib/fastops-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,33 @@ endif()

set(LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/fastops")

set(SRCS "")
set(SRCS
"${LIBRARY_DIR}/fastops/fastops.cpp"
)

if(ARCH_AMD64)
set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/avx/ops_avx.cpp")
set_source_files_properties("${LIBRARY_DIR}/fastops/avx/ops_avx.cpp" PROPERTIES COMPILE_FLAGS "-mavx -DNO_AVX2")

set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/avx2/ops_avx2.cpp")
set_source_files_properties("${LIBRARY_DIR}/fastops/avx2/ops_avx2.cpp" PROPERTIES COMPILE_FLAGS "-mavx2 -mfma")
if (ARCH_AMD64)
list(APPEND SRCS "${LIBRARY_DIR}/fastops/avx2/ops_avx2.cpp")
endif()

set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/plain/ops_plain.cpp" "${LIBRARY_DIR}/fastops/core/avx_id.cpp")
if (ARCH_AMD64 AND X86_ARCH_LEVEL VERSION_LESS 3)
# Below v3: need runtime dispatch with AVX-only and Plain fallbacks.
list(APPEND SRCS
"${LIBRARY_DIR}/fastops/avx/ops_avx.cpp"
"${LIBRARY_DIR}/fastops/plain/ops_plain.cpp"
"${LIBRARY_DIR}/fastops/core/avx_id.cpp"
)
set_source_files_properties("${LIBRARY_DIR}/fastops/avx/ops_avx.cpp" PROPERTIES COMPILE_FLAGS "-mavx -DNO_AVX2")
set_source_files_properties("${LIBRARY_DIR}/fastops/avx2/ops_avx2.cpp" PROPERTIES COMPILE_FLAGS "-mavx2 -mfma -DNO_AVX")
elseif(ARCH_AARCH64)
set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/neon/ops_neon.cpp")
list(APPEND SRCS "${LIBRARY_DIR}/fastops/neon/ops_neon.cpp")

# SVE requires arm_sve.h which is only available on Linux toolchains (not Darwin/FreeBSD).
if(OS_LINUX)
set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/sve/ops_sve.cpp")
list(APPEND SRCS "${LIBRARY_DIR}/fastops/sve/ops_sve.cpp")
set_source_files_properties("${LIBRARY_DIR}/fastops/sve/ops_sve.cpp" PROPERTIES COMPILE_FLAGS "-march=armv8-a+sve")
endif()
endif()

set (SRCS ${SRCS} "${LIBRARY_DIR}/fastops/fastops.cpp")

add_library(_fastops ${SRCS})

Expand Down
6 changes: 3 additions & 3 deletions contrib/libdivide-cmake/libdivide-config.h
Loading