From 47e00450158b4f36d5f9bc8f0b8ab6b061770d28 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:49:36 +0300 Subject: [PATCH 01/13] glmm, x86: define hadd function --- include/cglm/simd/x86.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index d1d9cfd..bbeccb3 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -48,6 +48,15 @@ glmm_abs(__m128 x) { return _mm_andnot_ps(_mm_set1_ps(-0.0f), x); } +static inline +__m128 +glmm_vhadd(__m128 v) { + __m128 x0; + x0 = _mm_add_ps(v, glmm_shuff1(v, 0, 1, 2, 3)); + x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1)); + return x0; +} + static inline __m128 glmm_vhadds(__m128 v) { From c5655bbd2eb08851d009f678fb8eb2cdb9a405b0 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:49:50 +0300 Subject: [PATCH 02/13] glmm: define fma functions --- include/cglm/simd/arm.h | 20 ++++++++++++++++++++ include/cglm/simd/x86.h | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/cglm/simd/arm.h b/include/cglm/simd/arm.h index 64b2dad..405b9d5 100644 --- a/include/cglm/simd/arm.h +++ b/include/cglm/simd/arm.h @@ -79,5 +79,25 @@ glmm_norm_inf(float32x4_t a) { return glmm_hmax(glmm_abs(a)); } +static inline +float32x4_t +glmm_fmadd(float32x4_t a, float32x4_t b, float32x4_t c) { +#if defined(__aarch64__) + return vfmaq_f32(a, b, c); +#else + return vmlaq_f32(a, b, c); +#endif +} + +static inline +float32x4_t +glmm_fnmadd(float32x4_t a, float32x4_t b, float32x4_t c) { +#if defined(__aarch64__) + return vfmsq_f32(a, b, c); +#else + return vmlsq_f32(a, b, c); +#endif +} + #endif #endif /* cglm_simd_arm_h */ diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index bbeccb3..2a5716b 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -197,5 +197,25 @@ glmm_store3(float v[3], __m128 vx) { _mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2)); } +static inline +__m128 +glmm_fmadd(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fmadd_ps(a, b, c); +#else + return _mm_add_ps(c, _mm_mul_ps(a, b)); +#endif +} + +static inline +__m128 +glmm_fnmadd(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fnmadd_ps(a, b, c); +#else + return _mm_sub_ps(c, _mm_mul_ps(a, b)); +#endif +} + #endif #endif /* cglm_simd_x86_h */ From abe29a788a04e4a3745bf5751e6941736bb4cef9 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:50:51 +0300 Subject: [PATCH 03/13] opitimize mat4 operations with fma --- include/cglm/simd/sse2/mat4.h | 230 ++++++++++++++-------------------- 1 file changed, 95 insertions(+), 135 deletions(-) diff --git a/include/cglm/simd/sse2/mat4.h b/include/cglm/simd/sse2/mat4.h index 7c87eb5..78fac21 100644 --- a/include/cglm/simd/sse2/mat4.h +++ b/include/cglm/simd/sse2/mat4.h @@ -55,47 +55,38 @@ glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { l1 = glmm_load(m1[1]); l2 = glmm_load(m1[2]); l3 = glmm_load(m1[3]); + +#define XX(C) \ + \ + r = glmm_load(m2[C]); \ + glmm_store(dest[C], \ + glmm_fmadd(glmm_shuff1x(r, 0), l0, \ + glmm_fmadd(glmm_shuff1x(r, 1), l1, \ + glmm_fmadd(glmm_shuff1x(r, 2), l2, \ + _mm_mul_ps(glmm_shuff1x(r, 3), \ + l3))))); - r = glmm_load(m2[0]); - glmm_store(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2), - _mm_mul_ps(glmm_shuff1x(r, 3), l3)))); - r = glmm_load(m2[1]); - glmm_store(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2), - _mm_mul_ps(glmm_shuff1x(r, 3), l3)))); - r = glmm_load(m2[2]); - glmm_store(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2), - _mm_mul_ps(glmm_shuff1x(r, 3), l3)))); + XX(0); + XX(1); + XX(2); + XX(3); - r = glmm_load(m2[3]); - glmm_store(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2), - _mm_mul_ps(glmm_shuff1x(r, 3), l3)))); +#undef XX } CGLM_INLINE void glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { - __m128 x0, x1, x2; - + __m128 x0, x1; + x0 = glmm_load(v); - x1 = _mm_add_ps(_mm_mul_ps(glmm_load(m[0]), glmm_shuff1x(x0, 0)), - _mm_mul_ps(glmm_load(m[1]), glmm_shuff1x(x0, 1))); - - x2 = _mm_add_ps(_mm_mul_ps(glmm_load(m[2]), glmm_shuff1x(x0, 2)), - _mm_mul_ps(glmm_load(m[3]), glmm_shuff1x(x0, 3))); - - glmm_store(dest, _mm_add_ps(x1, x2)); + x1 = glmm_fmadd(glmm_load(m[0]), glmm_shuff1x(x0, 0), + glmm_fmadd(glmm_load(m[1]), glmm_shuff1x(x0, 1), + glmm_fmadd(glmm_load(m[2]), glmm_shuff1x(x0, 2), + _mm_mul_ps(glmm_load(m[3]), + glmm_shuff1x(x0, 3))))); + + glmm_store(dest, x1); } CGLM_INLINE @@ -115,20 +106,18 @@ glm_mat4_det_sse2(mat4 mat) { t[3] = i * p - m * l; t[4] = i * o - m * k; */ - x0 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1), - glmm_shuff1(r3, 2, 3, 2, 3)), - _mm_mul_ps(glmm_shuff1(r3, 0, 0, 1, 1), - glmm_shuff1(r2, 2, 3, 2, 3))); + x0 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 1, 1), glmm_shuff1(r2, 2, 3, 2, 3), + _mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1), + glmm_shuff1(r3, 2, 3, 2, 3))); /* t[0] = k * p - o * l; t[0] = k * p - o * l; t[5] = i * n - m * j; t[5] = i * n - m * j; */ - x1 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2), - glmm_shuff1(r3, 1, 1, 3, 3)), - _mm_mul_ps(glmm_shuff1(r3, 0, 0, 2, 2), - glmm_shuff1(r2, 1, 1, 3, 3))); + x1 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 2, 2), glmm_shuff1(r2, 1, 1, 3, 3), + _mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2), + glmm_shuff1(r3, 1, 1, 3, 3))); /* a * (f * t[0] - g * t[1] + h * t[2]) @@ -136,21 +125,16 @@ glm_mat4_det_sse2(mat4 mat) { + c * (e * t[1] - f * t[3] + h * t[5]) - d * (e * t[2] - f * t[4] + g * t[5]) */ - x2 = _mm_sub_ps(_mm_mul_ps(glmm_shuff1(r1, 0, 0, 0, 1), - _mm_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0))), - _mm_mul_ps(glmm_shuff1(r1, 1, 1, 2, 2), - glmm_shuff1(x0, 3, 2, 2, 0))); - - x2 = _mm_add_ps(x2, - _mm_mul_ps(glmm_shuff1(r1, 2, 3, 3, 3), - _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 2, 3, 1)))); + x2 = glmm_fnmadd(glmm_shuff1(r1, 1, 1, 2, 2), glmm_shuff1(x0, 3, 2, 2, 0), + _mm_mul_ps(glmm_shuff1(r1, 0, 0, 0, 1), + _mm_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0)))); + x2 = glmm_fmadd(glmm_shuff1(r1, 2, 3, 3, 3), + _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 2, 3, 1)), + x2); + x2 = _mm_xor_ps(x2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); - - x0 = _mm_mul_ps(r0, x2); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3)); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 3, 3, 1)); - - return _mm_cvtss_f32(x0); + + return glmm_hadd(_mm_mul_ps(x2, r0)); } CGLM_INLINE @@ -159,8 +143,11 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { __m128 r0, r1, r2, r3, v0, v1, v2, v3, t0, t1, t2, t3, t4, t5, - x0, x1, x2, x3, x4, x5, x6, x7; - + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + /* 127 <- 0 */ r0 = glmm_load(mat[0]); /* d c b a */ r1 = glmm_load(mat[1]); /* h g f e */ @@ -177,8 +164,8 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { t1[0] = k * p - o * l; t2[0] = g * p - o * h; t3[0] = g * l - k * h; */ - t0 = _mm_sub_ps(_mm_mul_ps(x3, x1), _mm_mul_ps(x2, x0)); - + t0 = glmm_fnmadd(x2, x0, _mm_mul_ps(x3, x1)); + x4 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(2, 1, 2, 1)); /* o n k j */ x4 = glmm_shuff1(x4, 0, 2, 2, 2); /* j n n n */ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */ @@ -187,14 +174,14 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { t1[1] = j * p - n * l; t2[1] = f * p - n * h; t3[1] = f * l - j * h; */ - t1 = _mm_sub_ps(_mm_mul_ps(x5, x1), _mm_mul_ps(x4, x0)); - + t1 = glmm_fnmadd(x4, x0, _mm_mul_ps(x5, x1)); + /* t1[2] = j * o - n * k t1[2] = j * o - n * k; t2[2] = f * o - n * g; t3[2] = f * k - j * g; */ - t2 = _mm_sub_ps(_mm_mul_ps(x5, x2), _mm_mul_ps(x4, x3)); - + t2 = glmm_fnmadd(x4, x3, _mm_mul_ps(x5, x2)); + x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */ x7 = glmm_shuff2(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */ @@ -202,20 +189,20 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { t1[3] = i * p - m * l; t2[3] = e * p - m * h; t3[3] = e * l - i * h; */ - t3 = _mm_sub_ps(_mm_mul_ps(x6, x1), _mm_mul_ps(x7, x0)); - + t3 = glmm_fnmadd(x7, x0, _mm_mul_ps(x6, x1)); + /* t1[4] = i * o - m * k; t1[4] = i * o - m * k; t2[4] = e * o - m * g; t3[4] = e * k - i * g; */ - t4 = _mm_sub_ps(_mm_mul_ps(x6, x2), _mm_mul_ps(x7, x3)); - + t4 = glmm_fnmadd(x7, x3, _mm_mul_ps(x6, x2)); + /* t1[5] = i * n - m * j; t1[5] = i * n - m * j; t2[5] = e * n - m * f; t3[5] = e * j - i * f; */ - t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5)); - + t5 = glmm_fnmadd(x7, x5, _mm_mul_ps(x6, x4)); + x0 = glmm_shuff2(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */ x1 = glmm_shuff2(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */ x2 = glmm_shuff2(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */ @@ -226,50 +213,35 @@ glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ - v0 = _mm_add_ps(_mm_mul_ps(x3, t2), - _mm_sub_ps(_mm_mul_ps(x1, t0), - _mm_mul_ps(x2, t1))); - v0 = _mm_xor_ps(v0, _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + v0 = _mm_xor_ps(glmm_fmadd(x3, t2, glmm_fnmadd(x2, t1, _mm_mul_ps(x1, t0))), x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = _mm_xor_ps(glmm_fmadd(x3, t5, glmm_fnmadd(x1, t3, _mm_mul_ps(x0, t1))), x8); /* dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ - v1 = _mm_add_ps(_mm_mul_ps(x3, t4), - _mm_sub_ps(_mm_mul_ps(x0, t0), - _mm_mul_ps(x2, t3))); - v1 = _mm_xor_ps(v1, _mm_set_ps(0.f, -0.f, 0.f, -0.f)); - - /* - dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; - dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); - dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; - dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ - v2 = _mm_add_ps(_mm_mul_ps(x3, t5), - _mm_sub_ps(_mm_mul_ps(x0, t1), - _mm_mul_ps(x1, t3))); - v2 = _mm_xor_ps(v2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + v1 = _mm_xor_ps(glmm_fmadd(x3, t4, glmm_fnmadd(x2, t3, _mm_mul_ps(x0, t0))), x9); /* dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ - v3 = _mm_add_ps(_mm_mul_ps(x2, t5), - _mm_sub_ps(_mm_mul_ps(x0, t2), - _mm_mul_ps(x1, t4))); - v3 = _mm_xor_ps(v3, _mm_set_ps(0.f, -0.f, 0.f, -0.f)); + v3 = _mm_xor_ps(glmm_fmadd(x2, t5, glmm_fnmadd(x1, t4, _mm_mul_ps(x0, t2))), x9); /* determinant */ x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0)); x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0)); x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0)); - x0 = _mm_mul_ps(x0, r0); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3)); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1)); - x0 = _mm_rcp_ps(x0); + x0 = _mm_rcp_ps(glmm_vhadd(_mm_mul_ps(x0, r0))); glmm_store(dest[0], _mm_mul_ps(v0, x0)); glmm_store(dest[1], _mm_mul_ps(v1, x0)); @@ -283,8 +255,11 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { __m128 r0, r1, r2, r3, v0, v1, v2, v3, t0, t1, t2, t3, t4, t5, - x0, x1, x2, x3, x4, x5, x6, x7; - + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + /* 127 <- 0 */ r0 = glmm_load(mat[0]); /* d c b a */ r1 = glmm_load(mat[1]); /* h g f e */ @@ -301,8 +276,8 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { t1[0] = k * p - o * l; t2[0] = g * p - o * h; t3[0] = g * l - k * h; */ - t0 = _mm_sub_ps(_mm_mul_ps(x3, x1), _mm_mul_ps(x2, x0)); - + t0 = glmm_fnmadd(x2, x0, _mm_mul_ps(x3, x1)); + x4 = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(2, 1, 2, 1)); /* o n k j */ x4 = glmm_shuff1(x4, 0, 2, 2, 2); /* j n n n */ x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */ @@ -311,14 +286,14 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { t1[1] = j * p - n * l; t2[1] = f * p - n * h; t3[1] = f * l - j * h; */ - t1 = _mm_sub_ps(_mm_mul_ps(x5, x1), _mm_mul_ps(x4, x0)); - + t1 = glmm_fnmadd(x4, x0, _mm_mul_ps(x5, x1)); + /* t1[2] = j * o - n * k t1[2] = j * o - n * k; t2[2] = f * o - n * g; t3[2] = f * k - j * g; */ - t2 = _mm_sub_ps(_mm_mul_ps(x5, x2), _mm_mul_ps(x4, x3)); - + t2 = glmm_fnmadd(x4, x3, _mm_mul_ps(x5, x2)); + x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */ x7 = glmm_shuff2(r3, r2, 0, 0, 0, 0, 2, 0, 0, 0); /* i m m m */ @@ -326,20 +301,20 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { t1[3] = i * p - m * l; t2[3] = e * p - m * h; t3[3] = e * l - i * h; */ - t3 = _mm_sub_ps(_mm_mul_ps(x6, x1), _mm_mul_ps(x7, x0)); - + t3 = glmm_fnmadd(x7, x0, _mm_mul_ps(x6, x1)); + /* t1[4] = i * o - m * k; t1[4] = i * o - m * k; t2[4] = e * o - m * g; t3[4] = e * k - i * g; */ - t4 = _mm_sub_ps(_mm_mul_ps(x6, x2), _mm_mul_ps(x7, x3)); - + t4 = glmm_fnmadd(x7, x3, _mm_mul_ps(x6, x2)); + /* t1[5] = i * n - m * j; t1[5] = i * n - m * j; t2[5] = e * n - m * f; t3[5] = e * j - i * f; */ - t5 = _mm_sub_ps(_mm_mul_ps(x6, x4), _mm_mul_ps(x7, x5)); - + t5 = glmm_fnmadd(x7, x5, _mm_mul_ps(x6, x4)); + x0 = glmm_shuff2(r1, r0, 0, 0, 0, 0, 2, 2, 2, 0); /* a a a e */ x1 = glmm_shuff2(r1, r0, 1, 1, 1, 1, 2, 2, 2, 0); /* b b b f */ x2 = glmm_shuff2(r1, r0, 2, 2, 2, 2, 2, 2, 2, 0); /* c c c g */ @@ -350,50 +325,35 @@ glm_mat4_inv_sse2(mat4 mat, mat4 dest) { dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ - v0 = _mm_add_ps(_mm_mul_ps(x3, t2), - _mm_sub_ps(_mm_mul_ps(x1, t0), - _mm_mul_ps(x2, t1))); - v0 = _mm_xor_ps(v0, _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + v0 = _mm_xor_ps(glmm_fmadd(x3, t2, glmm_fnmadd(x2, t1, _mm_mul_ps(x1, t0))), x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = _mm_xor_ps(glmm_fmadd(x3, t5, glmm_fnmadd(x1, t3, _mm_mul_ps(x0, t1))), x8); /* dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ - v1 = _mm_add_ps(_mm_mul_ps(x3, t4), - _mm_sub_ps(_mm_mul_ps(x0, t0), - _mm_mul_ps(x2, t3))); - v1 = _mm_xor_ps(v1, _mm_set_ps(0.f, -0.f, 0.f, -0.f)); - - /* - dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; - dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); - dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; - dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ - v2 = _mm_add_ps(_mm_mul_ps(x3, t5), - _mm_sub_ps(_mm_mul_ps(x0, t1), - _mm_mul_ps(x1, t3))); - v2 = _mm_xor_ps(v2, _mm_set_ps(-0.f, 0.f, -0.f, 0.f)); + v1 = _mm_xor_ps(glmm_fmadd(x3, t4, glmm_fnmadd(x2, t3, _mm_mul_ps(x0, t0))), x9); /* dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ - v3 = _mm_add_ps(_mm_mul_ps(x2, t5), - _mm_sub_ps(_mm_mul_ps(x0, t2), - _mm_mul_ps(x1, t4))); - v3 = _mm_xor_ps(v3, _mm_set_ps(0.f, -0.f, 0.f, -0.f)); + v3 = _mm_xor_ps(glmm_fmadd(x2, t5, glmm_fnmadd(x1, t4, _mm_mul_ps(x0, t2))), x9); /* determinant */ x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0)); x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0)); x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0)); - x0 = _mm_mul_ps(x0, r0); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 2, 3)); - x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1)); - x0 = _mm_div_ps(_mm_set1_ps(1.0f), x0); + x0 = _mm_div_ps(_mm_set1_ps(1.0f), glmm_vhadd(_mm_mul_ps(x0, r0))); glmm_store(dest[0], _mm_mul_ps(v0, x0)); glmm_store(dest[1], _mm_mul_ps(v1, x0)); From 7cc4c37afb733b52df864bd0b943b008f7df51fc Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:51:03 +0300 Subject: [PATCH 04/13] opitimize mat3 operations with fma --- include/cglm/simd/sse2/mat3.h | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/include/cglm/simd/sse2/mat3.h b/include/cglm/simd/sse2/mat3.h index 9c972ff..cda8449 100644 --- a/include/cglm/simd/sse2/mat3.h +++ b/include/cglm/simd/sse2/mat3.h @@ -30,24 +30,17 @@ glm_mat3_mul_sse2(mat3 m1, mat3 m2, mat3 dest) { x1 = glmm_shuff2(l0, l1, 1, 0, 3, 3, 0, 3, 2, 0); x2 = glmm_shuff2(l1, l2, 0, 0, 3, 2, 0, 2, 1, 0); - x0 = _mm_add_ps(_mm_mul_ps(glmm_shuff1(l0, 0, 2, 1, 0), - glmm_shuff1(r0, 3, 0, 0, 0)), - _mm_mul_ps(x1, glmm_shuff2(r0, r1, 0, 0, 1, 1, 2, 0, 0, 0))); - - x0 = _mm_add_ps(x0, - _mm_mul_ps(x2, glmm_shuff2(r0, r1, 1, 1, 2, 2, 2, 0, 0, 0))); + x0 = glmm_fmadd(glmm_shuff1(l0, 0, 2, 1, 0), glmm_shuff1(r0, 3, 0, 0, 0), + glmm_fmadd(x1, glmm_shuff2(r0, r1, 0, 0, 1, 1, 2, 0, 0, 0), + _mm_mul_ps(x2, glmm_shuff2(r0, r1, 1, 1, 2, 2, 2, 0, 0, 0)))); _mm_storeu_ps(dest[0], x0); - x0 = _mm_add_ps(_mm_mul_ps(glmm_shuff1(l0, 1, 0, 2, 1), - _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(2, 2, 3, 3))), - _mm_mul_ps(glmm_shuff1(x1, 1, 0, 2, 1), - glmm_shuff1(r1, 3, 3, 0, 0))); - - x0 = _mm_add_ps(x0, - _mm_mul_ps(glmm_shuff1(x2, 1, 0, 2, 1), - _mm_shuffle_ps(r1, r2, _MM_SHUFFLE(0, 0, 1, 1)))); - + x0 = glmm_fmadd(glmm_shuff1(l0, 1, 0, 2, 1), _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(2, 2, 3, 3)), + glmm_fmadd(glmm_shuff1(x1, 1, 0, 2, 1), glmm_shuff1(r1, 3, 3, 0, 0), + _mm_mul_ps(glmm_shuff1(x2, 1, 0, 2, 1), + _mm_shuffle_ps(r1, r2, _MM_SHUFFLE(0, 0, 1, 1))))); + _mm_storeu_ps(&dest[1][1], x0); dest[2][2] = m1[0][2] * m2[2][0] From 7df5aa2e26e5e33c12a6bef31635ab0132ef3e3a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:51:09 +0300 Subject: [PATCH 05/13] opitimize mat2 operations with fma --- include/cglm/simd/sse2/mat2.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cglm/simd/sse2/mat2.h b/include/cglm/simd/sse2/mat2.h index b3b4d97..1f832b0 100644 --- a/include/cglm/simd/sse2/mat2.h +++ b/include/cglm/simd/sse2/mat2.h @@ -26,11 +26,11 @@ glm_mat2_mul_sse2(mat2 m1, mat2 m2, mat2 dest) { dest[1][0] = a * g + c * h; dest[1][1] = b * g + d * h; */ - x0 = _mm_mul_ps(_mm_movelh_ps(x1, x1), glmm_shuff1(x2, 2, 2, 0, 0)); - x1 = _mm_mul_ps(_mm_movehl_ps(x1, x1), glmm_shuff1(x2, 3, 3, 1, 1)); - x1 = _mm_add_ps(x0, x1); + x0 = glmm_fmadd(_mm_movelh_ps(x1, x1), glmm_shuff1(x2, 2, 2, 0, 0), + _mm_mul_ps(_mm_movehl_ps(x1, x1), + glmm_shuff1(x2, 3, 3, 1, 1))); - glmm_store(dest[0], x1); + glmm_store(dest[0], x0); } CGLM_INLINE From 0d0d22f96ce0e2ebaa219e0098d4deded20bed6e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 13:51:22 +0300 Subject: [PATCH 06/13] opitimize affine matrix operations with fma --- include/cglm/simd/sse2/affine.h | 60 +++++++++++++++++---------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/include/cglm/simd/sse2/affine.h b/include/cglm/simd/sse2/affine.h index 87db1b8..236408c 100644 --- a/include/cglm/simd/sse2/affine.h +++ b/include/cglm/simd/sse2/affine.h @@ -22,31 +22,32 @@ glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { l1 = glmm_load(m1[1]); l2 = glmm_load(m1[2]); l3 = glmm_load(m1[3]); - + r = glmm_load(m2[0]); glmm_store(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); - + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); + r = glmm_load(m2[1]); glmm_store(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); r = glmm_load(m2[2]); glmm_store(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); r = glmm_load(m2[3]); glmm_store(dest[3], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 2), l2), - _mm_mul_ps(glmm_shuff1x(r, 3), l3)))); + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + glmm_fmadd(glmm_shuff1x(r, 2), l2, + _mm_mul_ps(glmm_shuff1x(r, 3), + l3))))); } CGLM_INLINE @@ -62,21 +63,22 @@ glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) { r = glmm_load(m2[0]); glmm_store(dest[0], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); - + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); + r = glmm_load(m2[1]); glmm_store(dest[1], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); - + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); + + r = glmm_load(m2[2]); glmm_store(dest[2], - _mm_add_ps(_mm_add_ps(_mm_mul_ps(glmm_shuff1x(r, 0), l0), - _mm_mul_ps(glmm_shuff1x(r, 1), l1)), - _mm_mul_ps(glmm_shuff1x(r, 2), l2))); + glmm_fmadd(glmm_shuff1x(r, 0), l0, + glmm_fmadd(glmm_shuff1x(r, 1), l1, + _mm_mul_ps(glmm_shuff1x(r, 2), l2)))); glmm_store(dest[3], l3); } @@ -94,9 +96,9 @@ glm_inv_tr_sse2(mat4 mat) { _MM_TRANSPOSE4_PS(r0, r1, r2, x1); - x0 = _mm_add_ps(_mm_mul_ps(r0, glmm_shuff1(r3, 0, 0, 0, 0)), - _mm_mul_ps(r1, glmm_shuff1(r3, 1, 1, 1, 1))); - x0 = _mm_add_ps(x0, _mm_mul_ps(r2, glmm_shuff1(r3, 2, 2, 2, 2))); + x0 = glmm_fmadd(r0, glmm_shuff1(r3, 0, 0, 0, 0), + glmm_fmadd(r1, glmm_shuff1(r3, 1, 1, 1, 1), + _mm_mul_ps(r2, glmm_shuff1(r3, 2, 2, 2, 2)))); x0 = _mm_xor_ps(x0, _mm_set1_ps(-0.f)); x0 = _mm_add_ps(x0, x1); From f3f29bd383f439d0dc1f949ac3839c5b594158f7 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Sun, 18 Apr 2021 16:24:29 +0300 Subject: [PATCH 07/13] vec4: optimize muladd and muladds with fma --- include/cglm/vec4.h | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 7a4549c..54d487f 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -568,14 +568,8 @@ glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { -#if defined( __SSE__ ) || defined( __SSE2__ ) - glmm_store(dest, _mm_add_ps(glmm_load(dest), - _mm_mul_ps(glmm_load(a), - glmm_load(b)))); -#elif defined(CGLM_NEON_FP) - vst1q_f32(dest, vaddq_f32(vld1q_f32(dest), - vmulq_f32(vld1q_f32(a), - vld1q_f32(b)))); +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_load(b), glmm_load(dest))); #else dest[0] += a[0] * b[0]; dest[1] += a[1] * b[1]; @@ -596,14 +590,8 @@ glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest) { -#if defined( __SSE__ ) || defined( __SSE2__ ) - glmm_store(dest, _mm_add_ps(glmm_load(dest), - _mm_mul_ps(glmm_load(a), - _mm_set1_ps(s)))); -#elif defined(CGLM_NEON_FP) - vst1q_f32(dest, vaddq_f32(vld1q_f32(dest), - vmulq_f32(vld1q_f32(a), - vdupq_n_f32(s)))); +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fmadd(glmm_load(a), _mm_set1_ps(s), glmm_load(dest))); #else dest[0] += a[0] * s; dest[1] += a[1] * s; From 7c8148224843b16df2e4d94906d54d1ce63b2f60 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 00:11:43 +0300 Subject: [PATCH 08/13] avx: implement scale matrix using AVX --- include/cglm/mat4.h | 4 +++- include/cglm/simd/avx/mat4.h | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/cglm/mat4.h b/include/cglm/mat4.h index cda5285..c099574 100644 --- a/include/cglm/mat4.h +++ b/include/cglm/mat4.h @@ -539,7 +539,9 @@ glm_mat4_scale_p(mat4 m, float s) { CGLM_INLINE void glm_mat4_scale(mat4 m, float s) { -#if defined( __SSE__ ) || defined( __SSE2__ ) +#ifdef __AVX__ + glm_mat4_scale_avx(m, s); +#elif defined( __SSE__ ) || defined( __SSE2__ ) glm_mat4_scale_sse2(m, s); #elif defined(CGLM_NEON_FP) glm_mat4_scale_neon(m, s); diff --git a/include/cglm/simd/avx/mat4.h b/include/cglm/simd/avx/mat4.h index 944769b..e8c36c8 100644 --- a/include/cglm/simd/avx/mat4.h +++ b/include/cglm/simd/avx/mat4.h @@ -14,6 +14,16 @@ #include +CGLM_INLINE +void +glm_mat4_scale_avx(mat4 m, float s) { + __m256 y0; + y0 = _mm256_set1_ps(s); + + glmm_store256(m[0], _mm256_mul_ps(y0, glmm_load256(m[0]))); + glmm_store256(m[2], _mm256_mul_ps(y0, glmm_load256(m[2]))); +} + CGLM_INLINE void glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) { From 11b1588105f8a6312fd164c6edc1958456e3e5d1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 00:20:47 +0300 Subject: [PATCH 09/13] glmm: missing FMA funcs for SSE and AVX --- include/cglm/simd/x86.h | 67 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index 2a5716b..29a02f3 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -201,7 +201,7 @@ static inline __m128 glmm_fmadd(__m128 a, __m128 b, __m128 c) { #ifdef __FMA__ - return _mm_fmadd_ps(a, b, c); + return _mm_fmadd_ps(a, b, c); #else return _mm_add_ps(c, _mm_mul_ps(a, b)); #endif @@ -211,11 +211,74 @@ static inline __m128 glmm_fnmadd(__m128 a, __m128 b, __m128 c) { #ifdef __FMA__ - return _mm_fnmadd_ps(a, b, c); + return _mm_fnmadd_ps(a, b, c); #else return _mm_sub_ps(c, _mm_mul_ps(a, b)); #endif } +static inline +__m128 +glmm_fmsub(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fmsub_ps(a, b, c); +#else + return _mm_sub_ps(_mm_mul_ps(a, b), c); +#endif +} + +static inline +__m128 +glmm_fnmsub(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fnmsub_ps(a, b, c); +#else + return _mm_xor_ps(_mm_add_ps(_mm_mul_ps(a, b), c), _mm_set1_ps(-0.0f)); +#endif +} + +#if defined(__AVX__) +static inline +__m256 +glmm256_fmadd(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmadd_ps(a, b, c); +#else + return _mm256_add_ps(c, _mm256_mul_ps(a, b)); +#endif +} + +static inline +__m256 +glmm256_fnmadd(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fnmadd_ps(a, b, c); +#else + return _mm256_sub_ps(c, _mm256_mul_ps(a, b)); +#endif +} + +static inline +__m256 +glmm256_fmsub(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmsub_ps(a, b, c); +#else + return _mm256_sub_ps(_mm256_mul_ps(a, b), c); +#endif +} + +static inline +__m256 +glmm256_fnmsub(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmsub_ps(a, b, c); +#else + return _mm256_xor_ps(_mm256_sub_ps(_mm256_mul_ps(a, b), c), + _mm256_set1_ps(-0.0f)); +#endif +} +#endif + #endif #endif /* cglm_simd_x86_h */ From 04008d9c3f8ad65d5242319c0864b3963eb6b2c9 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 00:21:04 +0300 Subject: [PATCH 10/13] arm: fix fma for glm_vec4_muladds --- include/cglm/vec4.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 54d487f..2453b1b 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -590,8 +590,10 @@ glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest) { -#if defined(CGLM_SIMD) +#if defined( __SSE__ ) || defined( __SSE2__ ) glmm_store(dest, glmm_fmadd(glmm_load(a), _mm_set1_ps(s), glmm_load(dest))); +#elif defined(CGLM_NEON_FP) + glmm_store(dest, glmm_fmadd(glmm_load(a), vdupq_n_f32(s), glmm_load(dest))); #else dest[0] += a[0] * s; dest[1] += a[1] * s; From 7b0eee497e1124205a67b70b007e23f24b592f6a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 00:28:07 +0300 Subject: [PATCH 11/13] arm: fix fmadd parameter order --- include/cglm/simd/arm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cglm/simd/arm.h b/include/cglm/simd/arm.h index 405b9d5..2c2b845 100644 --- a/include/cglm/simd/arm.h +++ b/include/cglm/simd/arm.h @@ -83,9 +83,9 @@ static inline float32x4_t glmm_fmadd(float32x4_t a, float32x4_t b, float32x4_t c) { #if defined(__aarch64__) - return vfmaq_f32(a, b, c); + return vfmaq_f32(c, a, b); #else - return vmlaq_f32(a, b, c); + return vmlaq_f32(c, a, b); #endif } @@ -93,9 +93,9 @@ static inline float32x4_t glmm_fnmadd(float32x4_t a, float32x4_t b, float32x4_t c) { #if defined(__aarch64__) - return vfmsq_f32(a, b, c); + return vfmsq_f32(c, a, b); #else - return vmlsq_f32(a, b, c); + return vmlsq_f32(c, a, b); #endif } From aa2fa89e6c41b5431f8885a92ded01e12f2f137d Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 00:35:19 +0300 Subject: [PATCH 12/13] arm: fma msub and nmsub --- include/cglm/simd/arm.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/cglm/simd/arm.h b/include/cglm/simd/arm.h index 2c2b845..1153694 100644 --- a/include/cglm/simd/arm.h +++ b/include/cglm/simd/arm.h @@ -99,5 +99,21 @@ glmm_fnmadd(float32x4_t a, float32x4_t b, float32x4_t c) { #endif } +static inline +float32x4_t +glmm_fmsub(float32x4_t a, float32x4_t b, float32x4_t c) { +#if defined(__aarch64__) + return vfmsq_f32(c, a, b); +#else + return vmlsq_f32(c, a, b); +#endif +} + +static inline +float32x4_t +glmm_fnmsub(float32x4_t a, float32x4_t b, float32x4_t c) { + return vsubq_f32(vdupq_n_f32(0.0f), glmm_fmadd(a, b, c)); +} + #endif #endif /* cglm_simd_arm_h */ From ebba4eea8e836567cf1736c84d8e9f24f4c805b4 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Mon, 19 Apr 2021 04:14:14 +0300 Subject: [PATCH 13/13] win, msvc: enable FMA macro for MSVC --- include/cglm/simd/x86.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index 29a02f3..9f8e110 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -197,6 +197,11 @@ glmm_store3(float v[3], __m128 vx) { _mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2)); } +/* enable FMA macro for MSVC? */ +#if !defined(__FMA__) && defined(__AVX2__) +# define __FMA__ 1 +#endif + static inline __m128 glmm_fmadd(__m128 a, __m128 b, __m128 c) {