From: Paul A. Clarke Date: Fri, 13 Apr 2018 23:13:40 +0000 (+0000) Subject: rs6000: Fix _mm_slli_epi{32,64} for shift values 16 through 31 and negative (PR84302) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eef4632c6b3c95aadf73a46ace6aba263c10e709;p=gcc.git rs6000: Fix _mm_slli_epi{32,64} for shift values 16 through 31 and negative (PR84302) The powerpc versions of _mm_slli_epi32 and __mm_slli_epi64 in emmintrin.h do not properly handle shift values between 16 and 31, inclusive. These are setting up the shift with vec_splat_s32, which only accepts *5 bit signed* shift values, or a range of -16 to 15. Values above 15 produce an error: error: argument 1 must be a 5-bit signed literal Fix is to effectively reduce the range for which vec_splat_s32 is used to < 32 and use vec_splats otherwise. Also, __mm_slli_epi{16,32,64}, when given a negative shift value, should always return a vector of {0}. PR target/83402 * config/rs6000/emmintrin.h (_mm_slli_epi{16,32,64}): Ensure that vec_splat_s32 is only called with 0 <= shift < 16. Ensure negative shifts result in {0}. gcc/testsuite/ PR target/83402 * gcc.target/powerpc/sse2-psllw-1.c: Refactor and add tests for several values: positive, negative, and zero. * gcc.target/powerpc/sse2-pslld-1.c: Same. * gcc.target/powerpc/sse2-psllq-1.c: Same. From-SVN: r259380 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e04efca20d4..bbd731bc415 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-04-13 Paul A. Clarke + + PR target/83402 + * config/rs6000/emmintrin.h (_mm_slli_epi{16,32,64}): + Ensure that vec_splat_s32 is only called with 0 <= shift < 16. + Ensure negative shifts result in {0}. + 2018-04-13 Vladimir Makarov PR rtl-optimization/79916 diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h index 8d4545136e1..5d27a80339c 100644 --- a/gcc/config/rs6000/emmintrin.h +++ b/gcc/config/rs6000/emmintrin.h @@ -1488,12 +1488,12 @@ _mm_slli_epi16 (__m128i __A, int __B) __v8hu lshift; __v8hi result = { 0, 0, 0, 0, 0, 0, 0, 0 }; - if (__B < 16) + if (__B >= 0 && __B < 16) { if (__builtin_constant_p(__B)) - lshift = (__v8hu) vec_splat_s16(__B); + lshift = (__v8hu) vec_splat_s16(__B); else - lshift = vec_splats ((unsigned short) __B); + lshift = vec_splats ((unsigned short) __B); result = vec_vslh ((__v8hi) __A, lshift); } @@ -1507,9 +1507,9 @@ _mm_slli_epi32 (__m128i __A, int __B) __v4su lshift; __v4si result = { 0, 0, 0, 0 }; - if (__B < 32) + if (__B >= 0 && __B < 32) { - if (__builtin_constant_p(__B)) + if (__builtin_constant_p(__B) && __B < 16) lshift = (__v4su) vec_splat_s32(__B); else lshift = vec_splats ((unsigned int) __B); @@ -1527,17 +1527,12 @@ _mm_slli_epi64 (__m128i __A, int __B) __v2du lshift; __v2di result = { 0, 0 }; - if (__B < 64) + if (__B >= 0 && __B < 64) { - if (__builtin_constant_p(__B)) - { - if (__B < 32) - lshift = (__v2du) vec_splat_s32(__B); - else - lshift = (__v2du) vec_splats((unsigned long long)__B); - } + if (__builtin_constant_p(__B) && __B < 16) + lshift = (__v2du) vec_splat_s32(__B); else - lshift = (__v2du) vec_splats ((unsigned int) __B); + lshift = (__v2du) vec_splats ((unsigned int) __B); result = vec_vsld ((__v2di) __A, lshift); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 25225ec033e..13bb25b5b2a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-04-13 Paul A. Clarke + + PR target/83402 + * gcc.target/powerpc/sse2-psllw-1.c: Refactor and add tests for + several values: positive, negative, and zero. + * gcc.target/powerpc/sse2-pslld-1.c: Same. + * gcc.target/powerpc/sse2-psllq-1.c: Same. + 2018-04-13 Vladimir Makarov PR rtl-optimization/79916 diff --git a/gcc/testsuite/gcc.target/powerpc/sse2-pslld-1.c b/gcc/testsuite/gcc.target/powerpc/sse2-pslld-1.c index 90aac103fc2..835948bcb93 100644 --- a/gcc/testsuite/gcc.target/powerpc/sse2-pslld-1.c +++ b/gcc/testsuite/gcc.target/powerpc/sse2-pslld-1.c @@ -13,32 +13,50 @@ #define TEST sse2_test_pslld_1 #endif -#define N 0xf - #include -static __m128i -__attribute__((noinline, unused)) -test (__m128i s1) -{ - return _mm_slli_epi32 (s1, N); -} +#define TEST_FUNC(id, N) \ + static __m128i \ + __attribute__((noinline, unused)) \ + test##id (__m128i s1) \ + { \ + return _mm_slli_epi32 (s1, N); \ + } + +TEST_FUNC(0, 0) +TEST_FUNC(15, 15) +TEST_FUNC(16, 16) +TEST_FUNC(31, 31) +TEST_FUNC(neg1, -1) +TEST_FUNC(neg16, -16) +TEST_FUNC(neg32, -32) +TEST_FUNC(neg64, -64) +TEST_FUNC(neg128, -128) + +#define TEST_CODE(id, N) \ + { \ + int e[4] = {0}; \ + union128i_d u, s; \ + int i; \ + s.x = _mm_set_epi32 (1, -2, 3, 4); \ + u.x = test##id (s.x); \ + if (N >= 0 && N < 32) \ + for (i = 0; i < 4; i++) \ + e[i] = s.a[i] << (N * (N >= 0)); \ + if (check_union128i_d (u, e)) \ + abort (); \ + } static void TEST (void) { - union128i_d u, s; - int e[4] = {0}; - int i; - - s.x = _mm_set_epi32 (1, -2, 3, 4); - - u.x = test (s.x); - - if (N < 32) - for (i = 0; i < 4; i++) - e[i] = s.a[i] << N; - - if (check_union128i_d (u, e)) - abort (); + TEST_CODE(0, 0); + TEST_CODE(15, 15); + TEST_CODE(16, 16); + TEST_CODE(31, 31); + TEST_CODE(neg1, -1); + TEST_CODE(neg16, -16); + TEST_CODE(neg32, -32); + TEST_CODE(neg64, -64); + TEST_CODE(neg128, -128); } diff --git a/gcc/testsuite/gcc.target/powerpc/sse2-psllq-1.c b/gcc/testsuite/gcc.target/powerpc/sse2-psllq-1.c index 06904c50217..c89746f54ae 100644 --- a/gcc/testsuite/gcc.target/powerpc/sse2-psllq-1.c +++ b/gcc/testsuite/gcc.target/powerpc/sse2-psllq-1.c @@ -13,36 +13,56 @@ #define TEST sse2_test_psllq_1 #endif -#define N 60 - #include #ifdef _ARCH_PWR8 -static __m128i -__attribute__((noinline, unused)) -test (__m128i s1) -{ - return _mm_slli_epi64 (s1, N); -} +#define TEST_FUNC(id, N) \ + static __m128i \ + __attribute__((noinline, unused)) \ + test##id (__m128i s1) \ + { \ + return _mm_slli_epi64 (s1, N); \ + } + +TEST_FUNC(0, 0) +TEST_FUNC(15, 15) +TEST_FUNC(16, 16) +TEST_FUNC(31, 31) +TEST_FUNC(63, 63) +TEST_FUNC(neg1, -1) +TEST_FUNC(neg16, -16) +TEST_FUNC(neg32, -32) +TEST_FUNC(neg64, -64) +TEST_FUNC(neg128, -128) #endif +#define TEST_CODE(id, N) \ + { \ + union128i_q u, s; \ + long long e[2] = {0}; \ + int i; \ + s.x = _mm_set_epi64x (-1, 0xf); \ + u.x = test##id (s.x); \ + if (N >= 0 && N < 64) \ + for (i = 0; i < 2; i++) \ + e[i] = s.a[i] << (N * (N >= 0)); \ + if (check_union128i_q (u, e)) \ + abort (); \ + } + static void TEST (void) { #ifdef _ARCH_PWR8 - union128i_q u, s; - long long e[2] = {0}; - int i; - - s.x = _mm_set_epi64x (-1, 0xf); - - u.x = test (s.x); - - if (N < 64) - for (i = 0; i < 2; i++) - e[i] = s.a[i] << N; - - if (check_union128i_q (u, e)) - abort (); + TEST_CODE(0, 0); + TEST_CODE(15, 15); + TEST_CODE(16, 16); + TEST_CODE(31, 31); + TEST_CODE(63, 63); + TEST_CODE(neg1, -1); + TEST_CODE(neg16, -16); + TEST_CODE(neg32, -32); + TEST_CODE(neg64, -64); + TEST_CODE(neg128, -128); #endif } diff --git a/gcc/testsuite/gcc.target/powerpc/sse2-psllw-1.c b/gcc/testsuite/gcc.target/powerpc/sse2-psllw-1.c index f744bb244cb..4a0d6719ca3 100644 --- a/gcc/testsuite/gcc.target/powerpc/sse2-psllw-1.c +++ b/gcc/testsuite/gcc.target/powerpc/sse2-psllw-1.c @@ -13,32 +13,48 @@ #define TEST sse2_test_psllw_1 #endif -#define N 0xb - #include -static __m128i -__attribute__((noinline, unused)) -test (__m128i s1) -{ - return _mm_slli_epi16 (s1, N); -} +#define TEST_FUNC(id, N) \ + static __m128i \ + __attribute__((noinline, unused)) \ + test##id (__m128i s1) \ + { \ + return _mm_slli_epi16 (s1, N); \ + } + +TEST_FUNC(0, 0) +TEST_FUNC(15, 15) +TEST_FUNC(16, 16) +TEST_FUNC(neg1, -1) +TEST_FUNC(neg16, -16) +TEST_FUNC(neg32, -32) +TEST_FUNC(neg64, -64) +TEST_FUNC(neg128, -128) + +#define TEST_CODE(id, N) \ + { \ + short e[8] = {0}; \ + union128i_w u, s; \ + int i; \ + s.x = _mm_set_epi16 (1, 2, 3, 4, 5, 6, 0x7000, 0x9000); \ + u.x = test##id (s.x); \ + if (N >= 0 && N < 16) \ + for (i = 0; i < 8; i++) \ + e[i] = s.a[i] << (N * (N >= 0)); \ + if (check_union128i_w (u, e)) \ + abort (); \ + } static void TEST (void) { - union128i_w u, s; - short e[8] = {0}; - int i; - - s.x = _mm_set_epi16 (1, 2, 3, 4, 5, 6, 0x7000, 0x9000); - - u.x = test (s.x); - - if (N < 16) - for (i = 0; i < 8; i++) - e[i] = s.a[i] << N; - - if (check_union128i_w (u, e)) - abort (); + TEST_CODE(0, 0); + TEST_CODE(15, 15); + TEST_CODE(16, 16); + TEST_CODE(neg1, -1); + TEST_CODE(neg16, -16); + TEST_CODE(neg32, -32); + TEST_CODE(neg64, -64); + TEST_CODE(neg128, -128); }