From 56cef9ce0f86f70560c06047b9c29bbe9fefc320 Mon Sep 17 00:00:00 2001 From: OmniBlade Date: Tue, 8 Sep 2026 09:28:52 +0100 Subject: [PATCH 1/2] Implements fabs with SSE intrinsics. --- double/s_fabs.c | 12 ++++++++++++ float/s_fabsf.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/double/s_fabs.c b/double/s_fabs.c index fdb16df..1fa4665 100644 --- a/double/s_fabs.c +++ b/double/s_fabs.c @@ -20,8 +20,20 @@ double gm_fabs(double x) { +#if defined USE_SSE && (defined __amd64__ || defined _M_AMD64) + // Testing shows this only improves performance on x86_64 builds + double ret; + const union { + unsigned long long __ui; + double __uf; + } sign_mask = { 0x7FFFFFFFFFFFFFFF }; + + _mm_store_sd(&ret, _mm_and_pd(_mm_load_sd(&sign_mask.__uf), _mm_load_sd(&x))); + return ret; +#else uint32_t high; GET_HIGH_WORD(high,x); SET_HIGH_WORD(x,high&0x7fffffff); return x; +#endif } diff --git a/float/s_fabsf.c b/float/s_fabsf.c index bb84673..802e0de 100644 --- a/float/s_fabsf.c +++ b/float/s_fabsf.c @@ -23,8 +23,20 @@ float gm_fabsf(float x) { +#if defined USE_SSE && (defined __amd64__ || defined _M_AMD64) + // Testing shows this only improves performance on x86_64 builds + float ret; + const union { + unsigned __ui; + float __uf; + } sign_mask = { 0x7FFFFFFF }; + + _mm_store_ss(&ret, _mm_and_ps(_mm_load_ss(&sign_mask.__uf), _mm_load_ss(&x))); + return ret; +#else uint32_t ix; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x7fffffff); return x; +#endif } From 5c6d0aed404b81b1f0c96ea8ec72367802f19dda Mon Sep 17 00:00:00 2001 From: OmniBlade Date: Tue, 8 Sep 2026 09:29:32 +0100 Subject: [PATCH 2/2] Implement ARM intrinsics for sqrt. --- common/math_private.h | 5 +++++ double/e_sqrt.c | 13 +++++++++++++ float/e_sqrtf.c | 13 +++++++++++++ 3 files changed, 31 insertions(+) diff --git a/common/math_private.h b/common/math_private.h index b14ea9a..e5a9b91 100644 --- a/common/math_private.h +++ b/common/math_private.h @@ -28,6 +28,11 @@ #elif (defined __clang__ || defined __GNUC__) && (defined __i386__ || defined __amd64__) #include #define USE_SSE 1 +#elif defined(__aarch64__) || defined(_M_ARM64) +#include +#define USE_NEON 1 +#elif (defined(__ARM_FP) && ((__ARM_FP & 0XC) == 0xC)) +#define USE_VFP3 1 #endif #endif diff --git a/double/e_sqrt.c b/double/e_sqrt.c index f3511b4..2316998 100644 --- a/double/e_sqrt.c +++ b/double/e_sqrt.c @@ -93,6 +93,19 @@ __ieee754_sqrt(double x) double ret; _mm_store_sd(&ret, _mm_sqrt_pd(_mm_load_sd(&x))); return ret; +#elif defined USE_NEON + double ret; + float64x1_t a = {0}; + a = vset_lane_f64(x, a, 0); + float64x1_t r = vsqrt_f64(a); + ret = vget_lane_f64(r, 0); + return ret; +#elif defined USE_VFP3 + double ret; + __asm__ ("vsqrt.f64 %0, %1" + : "=w" (ret) + : "w" (x)); + return ret; #else double z; int32_t sign = (int)0x80000000; diff --git a/float/e_sqrtf.c b/float/e_sqrtf.c index 31774b9..31c46b4 100644 --- a/float/e_sqrtf.c +++ b/float/e_sqrtf.c @@ -25,6 +25,19 @@ __ieee754_sqrtf(float x) float ret; _mm_store_ss(&ret, _mm_sqrt_ps(_mm_load_ss(&x))); return ret; +#elif defined USE_NEON + float ret; + float32x2_t a = {0}; + a = vset_lane_f32(x, a, 0); + float32x2_t r = vsqrt_f32(a); + ret = vget_lane_f32(r, 0); + return ret; +#elif defined USE_VFP3 + float ret; + __asm__ ("vsqrt.f32 %0, %1" + : "=w" (ret) + : "w" (x)); + return ret; #else float z; int32_t sign = (int)0x80000000;