From 3d832a2f0206d4944fd374a587c7870644de6f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Wed, 12 Aug 2015 19:33:10 +0300 Subject: [PATCH] Fix scalar SSE1 comparison nan handling to be symmetric. Add test. --- system/include/emscripten/xmmintrin.h | 12 ++-- tests/core/test_simd12.in | 100 ++++++++++++++++++++++++++ tests/core/test_simd12.out | 1 + tests/test_core.py | 9 +++ 4 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 tests/core/test_simd12.in create mode 100644 tests/core/test_simd12.out diff --git a/system/include/emscripten/xmmintrin.h b/system/include/emscripten/xmmintrin.h index b4fdf19247cd..9c188b71f25e 100644 --- a/system/include/emscripten/xmmintrin.h +++ b/system/include/emscripten/xmmintrin.h @@ -509,7 +509,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_comieq_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 1; + if (isnanf(__a[0]) || isnanf(__b[0])) return 1; #endif return __a[0] == __b[0]; } @@ -530,7 +530,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_comile_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 1; + if (isnanf(__a[0]) || isnanf(__b[0])) return 1; #endif return __a[0] <= __b[0]; } @@ -539,7 +539,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_comilt_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 1; + if (isnanf(__a[0]) || isnanf(__b[0])) return 1; #endif return __a[0] < __b[0]; } @@ -548,7 +548,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_comineq_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 0; + if (isnanf(__a[0]) || isnanf(__b[0])) return 0; #endif return __a[0] != __b[0]; } @@ -557,7 +557,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_ucomieq_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 1; + if (isnanf(__a[0]) || isnanf(__b[0])) return 1; #endif return __a[0] == __b[0]; } @@ -590,7 +590,7 @@ static __inline__ int __attribute__((__always_inline__)) _mm_ucomineq_ss(__m128 __a, __m128 __b) { #ifdef __EMSCRIPTEN__ - if (isnanf(__a[0])) return 0; + if (isnanf(__a[0]) || isnanf(__b[0])) return 0; #endif return __a[0] != __b[0]; } diff --git a/tests/core/test_simd12.in b/tests/core/test_simd12.in new file mode 100644 index 000000000000..18251b70075f --- /dev/null +++ b/tests/core/test_simd12.in @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +volatile __m128 zero; +volatile __m128 one; +volatile __m128 nan_; + +int main() { + zero = _mm_set1_ps(0); + one = _mm_set1_ps(1); + nan_ = _mm_set1_ps(__builtin_nan("")); + + assert(_mm_comieq_ss(zero, zero) == 1); + assert(_mm_comieq_ss(zero, one) == 0); + assert(_mm_comieq_ss(one, zero) == 0); + assert(_mm_comieq_ss(zero, nan_) == 1); + assert(_mm_comieq_ss(nan_, zero) == 1); + assert(_mm_comieq_ss(nan_, nan_) == 1); + + assert(_mm_comige_ss(zero, zero) == 1); + assert(_mm_comige_ss(zero, one) == 0); + assert(_mm_comige_ss(one, zero) == 1); + assert(_mm_comige_ss(zero, nan_) == 0); + assert(_mm_comige_ss(nan_, zero) == 0); + assert(_mm_comige_ss(nan_, nan_) == 0); + + assert(_mm_comigt_ss(zero, zero) == 0); + assert(_mm_comigt_ss(zero, one) == 0); + assert(_mm_comigt_ss(one, zero) == 1); + assert(_mm_comigt_ss(zero, nan_) == 0); + assert(_mm_comigt_ss(nan_, zero) == 0); + assert(_mm_comigt_ss(nan_, nan_) == 0); + + assert(_mm_comile_ss(zero, zero) == 1); + assert(_mm_comile_ss(zero, one) == 1); + assert(_mm_comile_ss(one, zero) == 0); + assert(_mm_comile_ss(zero, nan_) == 1); + assert(_mm_comile_ss(nan_, zero) == 1); + assert(_mm_comile_ss(nan_, nan_) == 1); + + assert(_mm_comilt_ss(zero, zero) == 0); + assert(_mm_comilt_ss(zero, one) == 1); + assert(_mm_comilt_ss(one, zero) == 0); + assert(_mm_comilt_ss(zero, nan_) == 1); + assert(_mm_comilt_ss(nan_, zero) == 1); + assert(_mm_comilt_ss(nan_, nan_) == 1); + + assert(_mm_comineq_ss(zero, zero) == 0); + assert(_mm_comineq_ss(zero, one) == 1); + assert(_mm_comineq_ss(one, zero) == 1); + assert(_mm_comineq_ss(zero, nan_) == 0); + assert(_mm_comineq_ss(nan_, zero) == 0); + assert(_mm_comineq_ss(nan_, nan_) == 0); + + assert(_mm_ucomieq_ss(zero, zero) == 1); + assert(_mm_ucomieq_ss(zero, one) == 0); + assert(_mm_ucomieq_ss(one, zero) == 0); + assert(_mm_ucomieq_ss(zero, nan_) == 1); + assert(_mm_ucomieq_ss(nan_, zero) == 1); + assert(_mm_ucomieq_ss(nan_, nan_) == 1); + + assert(_mm_ucomige_ss(zero, zero) == 1); + assert(_mm_ucomige_ss(zero, one) == 0); + assert(_mm_ucomige_ss(one, zero) == 1); + assert(_mm_ucomige_ss(zero, nan_) == 0); + assert(_mm_ucomige_ss(nan_, zero) == 0); + assert(_mm_ucomige_ss(nan_, nan_) == 0); + + assert(_mm_ucomigt_ss(zero, zero) == 0); + assert(_mm_ucomigt_ss(zero, one) == 0); + assert(_mm_ucomigt_ss(one, zero) == 1); + assert(_mm_ucomigt_ss(zero, nan_) == 0); + assert(_mm_ucomigt_ss(nan_, zero) == 0); + assert(_mm_ucomigt_ss(nan_, nan_) == 0); + + assert(_mm_ucomile_ss(zero, zero) == 1); + assert(_mm_ucomile_ss(zero, one) == 1); + assert(_mm_ucomile_ss(one, zero) == 0); + assert(_mm_ucomile_ss(zero, nan_) == 1); + assert(_mm_ucomile_ss(nan_, zero) == 1); + assert(_mm_ucomile_ss(nan_, nan_) == 1); + + assert(_mm_ucomilt_ss(zero, zero) == 0); + assert(_mm_ucomilt_ss(zero, one) == 1); + assert(_mm_ucomilt_ss(one, zero) == 0); + assert(_mm_ucomilt_ss(zero, nan_) == 1); + assert(_mm_ucomilt_ss(nan_, zero) == 1); + assert(_mm_ucomilt_ss(nan_, nan_) == 1); + + assert(_mm_ucomineq_ss(zero, zero) == 0); + assert(_mm_ucomineq_ss(zero, one) == 1); + assert(_mm_ucomineq_ss(one, zero) == 1); + assert(_mm_ucomineq_ss(zero, nan_) == 0); + assert(_mm_ucomineq_ss(nan_, zero) == 0); + assert(_mm_ucomineq_ss(nan_, nan_) == 0); + + printf("DONE!\n"); +} diff --git a/tests/core/test_simd12.out b/tests/core/test_simd12.out new file mode 100644 index 000000000000..84ce3dcb4fdf --- /dev/null +++ b/tests/core/test_simd12.out @@ -0,0 +1 @@ +DONE! \ No newline at end of file diff --git a/tests/test_core.py b/tests/test_core.py index 8533ad35338e..db87dbb40704 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5695,6 +5695,15 @@ def test_simd11(self): self.emcc_args = self.emcc_args + ['-msse2'] self.do_run_from_file(src, output) + def test_simd12(self): + if self.is_emterpreter(): return self.skip('todo') + + test_path = path_from_root('tests', 'core', 'test_simd12') + src, output = (test_path + s for s in ('.in', '.out')) + + self.emcc_args = self.emcc_args + ['-msse'] + self.do_run_from_file(src, output) + def test_simd_dyncall(self): if self.is_emterpreter(): return self.skip('todo')