Skip to content

Commit 6b772fe

Browse files
jkkim0724mr-c
authored andcommitted
math: restrict __builtin_roundeven to glibc >= 2.25 on GCC 10+
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
1 parent 856df51 commit 6b772fe

1 file changed

Lines changed: 17 additions & 4 deletions

File tree

simde/simde-math.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,9 +1266,17 @@ simde_math_fpclass(double v, const int imm8) {
12661266
#endif
12671267

12681268
#if !defined(simde_math_roundeven)
1269+
/* GCC 10+ lowers __builtin_roundeven to a libm roundeven() call when
1270+
* the target has no native instruction. roundeven() is C23 and only
1271+
* available in glibc >= 2.25; other platforms (musl, OpenBSD, MinGW,
1272+
* etc.) lack the symbol and produce a link error. Clang lowers the
1273+
* builtin to an llvm.roundeven.* intrinsic which is always emitted
1274+
* inline (no libm dependency), so the GCC guard is not needed there. */
12691275
#if \
1270-
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && HEDLEY_HAS_BUILTIN(__builtin_roundeven)) || \
1271-
HEDLEY_GCC_VERSION_CHECK(10,0,0)
1276+
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \
1277+
HEDLEY_HAS_BUILTIN(__builtin_roundeven) && \
1278+
(!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \
1279+
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))))
12721280
#define simde_math_roundeven(v) __builtin_roundeven(v)
12731281
#elif defined(simde_math_round) && defined(simde_math_fabs)
12741282
static HEDLEY_INLINE
@@ -1286,9 +1294,14 @@ simde_math_fpclass(double v, const int imm8) {
12861294
#endif
12871295

12881296
#if !defined(simde_math_roundevenf)
1297+
/* Same rationale as simde_math_roundeven above; applies to the float
1298+
* variant. GCC 10+ requires glibc >= 2.25 for roundevenf(); Clang
1299+
* is always safe via llvm.roundeven.f32 inline expansion. */
12891300
#if \
1290-
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && HEDLEY_HAS_BUILTIN(__builtin_roundevenf)) || \
1291-
HEDLEY_GCC_VERSION_CHECK(10,0,0)
1301+
((!defined(HEDLEY_EMSCRIPTEN_VERSION) || HEDLEY_EMSCRIPTEN_VERSION_CHECK(3, 1, 43)) && \
1302+
HEDLEY_HAS_BUILTIN(__builtin_roundevenf) && \
1303+
(!HEDLEY_GCC_VERSION_CHECK(10,0,0) || \
1304+
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))))
12921305
#define simde_math_roundevenf(v) __builtin_roundevenf(v)
12931306
#elif defined(simde_math_roundf) && defined(simde_math_fabsf)
12941307
static HEDLEY_INLINE

0 commit comments

Comments
 (0)