From fd3d458d88c5e039b522e96cf2b1551234a64044 Mon Sep 17 00:00:00 2001 From: "jg.kim0724" Date: Fri, 27 Mar 2026 19:28:31 +0900 Subject: [PATCH 1/2] math: restrict __builtin_roundeven to glibc >= 2.25 on GCC 10+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit roundeven() / roundevenf() are C23 functions added to glibc 2.25 (2017). On GCC 10+, HEDLEY_HAS_BUILTIN(__builtin_roundeven) returns true (both __has_builtin and __builtin_roundeven were introduced in GCC 10), so the builtin path is taken. GCC lowers this to a roundeven() libm call when the target has no native instruction (ROUNDSD/FRINTN). On non-glibc platforms (musl, OpenBSD, MinGW, etc.) this symbol is absent, causing a link error: undefined reference to 'roundevenf' Note: the previous HEDLEY_GCC_VERSION_CHECK(10,0,0) branch in the || condition was dead code — on GCC 10+ HEDLEY_HAS_BUILTIN already fires. Fix: guard the HEDLEY_HAS_BUILTIN path so GCC 10+ only uses the builtin when glibc >= 2.25 is confirmed. Non-glibc platforms and older glibc fall through to the portable inline fallback (roundf + fabsf), which requires no libm symbols beyond what every C platform provides. Clang is unaffected: it lowers __builtin_roundeven to llvm.roundeven.* intrinsics which are always emitted inline (no libm dependency), so the GCC guard does not apply there. Both simde_math_roundeven (double) and simde_math_roundevenf (float) are fixed identically. Fixes link failure observed on OpenBSD/GCC building VVenC with bundled SIMDE: fraunhoferhhi/vvenc#680 --- simde/simde-math.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/simde/simde-math.h b/simde/simde-math.h index a98384a8d..9685d903d 100644 --- a/simde/simde-math.h +++ b/simde/simde-math.h @@ -1266,9 +1266,17 @@ simde_math_fpclass(double v, const int imm8) { #endif #if !defined(simde_math_roundeven) + /* GCC 10+ lowers __builtin_roundeven to a libm roundeven() call when + * the target has no native instruction. roundeven() is C23 and only + * available in glibc >= 2.25; other platforms (musl, OpenBSD, MinGW, + * etc.) lack the symbol and produce a link error. Clang lowers the + * builtin to an llvm.roundeven.* intrinsic which is always emitted + * inline (no libm dependency), so the GCC guard is not needed there. */ #if \ - ((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && HEDLEY_HAS_BUILTIN(__builtin_roundeven)) || \ - HEDLEY_GCC_VERSION_CHECK(10,0,0) + ((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \ + HEDLEY_HAS_BUILTIN(__builtin_roundeven) && \ + (!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \ + (defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))))) #define simde_math_roundeven(v) __builtin_roundeven(v) #elif defined(simde_math_round) && defined(simde_math_fabs) static HEDLEY_INLINE @@ -1286,9 +1294,14 @@ simde_math_fpclass(double v, const int imm8) { #endif #if !defined(simde_math_roundevenf) + /* Same rationale as simde_math_roundeven above; applies to the float + * variant. GCC 10+ requires glibc >= 2.25 for roundevenf(); Clang + * is always safe via llvm.roundeven.f32 inline expansion. */ #if \ - ((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && HEDLEY_HAS_BUILTIN(__builtin_roundevenf)) || \ - HEDLEY_GCC_VERSION_CHECK(10,0,0) + ((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \ + HEDLEY_HAS_BUILTIN(__builtin_roundevenf) && \ + (!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \ + (defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))))) #define simde_math_roundevenf(v) __builtin_roundevenf(v) #elif defined(simde_math_roundf) && defined(simde_math_fabsf) static HEDLEY_INLINE From 4e0a8fcc4fc659237e169ff1b12491a71741e167 Mon Sep 17 00:00:00 2001 From: "jg.kim0724" Date: Fri, 27 Mar 2026 20:30:10 +0900 Subject: [PATCH 2/2] ci: add Alpine (musl + GCC + SIMDE_NO_NATIVE) to Cirrus CI Add a Cirrus CI task that builds and tests SIMDE on Alpine Linux (musl libc) with GCC and SIMDE_NO_NATIVE disabled. This combination catches link errors caused by __builtin_roundeven being lowered to a roundeven() libm call on GCC 10+: musl lacks roundeven() (C23), so the linker error surfaces immediately. SIMDE_NO_NATIVE ensures the scalar path is taken even on x86-64 with SSE4.1, preventing GCC from inlining the builtin as a ROUNDSD instruction and masking the issue. Suggested during review of #1398. --- .cirrus.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.cirrus.yml b/.cirrus.yml index 460ae1706..922045239 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,6 +1,23 @@ container: image: debian:trixie-slim +task: + name: Alpine (musl + GCC + SIMDE_NO_NATIVE) + skip: $BRANCH == "master" || ($BRANCH != 'ci/cirrus' && $BRANCH =~ '^ci/.+') + container: + image: alpine:latest + env: + CC: gcc + CXX: g++ + install_dependencies_script: + - apk add --no-cache build-base meson ninja python3 + configure_script: + - meson setup build -Dc_args="-DSIMDE_NO_NATIVE -Wextra -Werror" -Dcpp_args="-DSIMDE_NO_NATIVE -Wextra -Werror" + build_script: + - ninja -C build -v -j 3 + test_script: + - ninja -C build -v test + task: name: Sanitizers skip: $BRANCH == "master" || ($BRANCH != 'ci/cirrus' && $BRANCH =~ '^ci/.+')