Skip to content

Commit 4b068f3

Browse files
author
segher
committed
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259380 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 0c0a0f3 commit 4b068f3

File tree

6 files changed

+144
-80
lines changed

6 files changed

+144
-80
lines changed

gcc/ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2018-04-13 Paul A. Clarke <[email protected]>
2+
3+
PR target/83402
4+
* config/rs6000/emmintrin.h (_mm_slli_epi{16,32,64}):
5+
Ensure that vec_splat_s32 is only called with 0 <= shift < 16.
6+
Ensure negative shifts result in {0}.
7+
18
2018-04-13 Vladimir Makarov <[email protected]>
29

310
PR rtl-optimization/79916

gcc/config/rs6000/emmintrin.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,12 +1488,12 @@ _mm_slli_epi16 (__m128i __A, int __B)
14881488
__v8hu lshift;
14891489
__v8hi result = { 0, 0, 0, 0, 0, 0, 0, 0 };
14901490

1491-
if (__B < 16)
1491+
if (__B >= 0 && __B < 16)
14921492
{
14931493
if (__builtin_constant_p(__B))
1494-
lshift = (__v8hu) vec_splat_s16(__B);
1494+
lshift = (__v8hu) vec_splat_s16(__B);
14951495
else
1496-
lshift = vec_splats ((unsigned short) __B);
1496+
lshift = vec_splats ((unsigned short) __B);
14971497

14981498
result = vec_vslh ((__v8hi) __A, lshift);
14991499
}
@@ -1507,9 +1507,9 @@ _mm_slli_epi32 (__m128i __A, int __B)
15071507
__v4su lshift;
15081508
__v4si result = { 0, 0, 0, 0 };
15091509

1510-
if (__B < 32)
1510+
if (__B >= 0 && __B < 32)
15111511
{
1512-
if (__builtin_constant_p(__B))
1512+
if (__builtin_constant_p(__B) && __B < 16)
15131513
lshift = (__v4su) vec_splat_s32(__B);
15141514
else
15151515
lshift = vec_splats ((unsigned int) __B);
@@ -1527,17 +1527,12 @@ _mm_slli_epi64 (__m128i __A, int __B)
15271527
__v2du lshift;
15281528
__v2di result = { 0, 0 };
15291529

1530-
if (__B < 64)
1530+
if (__B >= 0 && __B < 64)
15311531
{
1532-
if (__builtin_constant_p(__B))
1533-
{
1534-
if (__B < 32)
1535-
lshift = (__v2du) vec_splat_s32(__B);
1536-
else
1537-
lshift = (__v2du) vec_splats((unsigned long long)__B);
1538-
}
1532+
if (__builtin_constant_p(__B) && __B < 16)
1533+
lshift = (__v2du) vec_splat_s32(__B);
15391534
else
1540-
lshift = (__v2du) vec_splats ((unsigned int) __B);
1535+
lshift = (__v2du) vec_splats ((unsigned int) __B);
15411536

15421537
result = vec_vsld ((__v2di) __A, lshift);
15431538
}

gcc/testsuite/ChangeLog

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2018-04-13 Paul A. Clarke <[email protected]>
2+
3+
PR target/83402
4+
* gcc.target/powerpc/sse2-psllw-1.c: Refactor and add tests for
5+
several values: positive, negative, and zero.
6+
* gcc.target/powerpc/sse2-pslld-1.c: Same.
7+
* gcc.target/powerpc/sse2-psllq-1.c: Same.
8+
19
2018-04-13 Vladimir Makarov <[email protected]>
210

311
PR rtl-optimization/79916

gcc/testsuite/gcc.target/powerpc/sse2-pslld-1.c

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,50 @@
1313
#define TEST sse2_test_pslld_1
1414
#endif
1515

16-
#define N 0xf
17-
1816
#include <emmintrin.h>
1917

20-
static __m128i
21-
__attribute__((noinline, unused))
22-
test (__m128i s1)
23-
{
24-
return _mm_slli_epi32 (s1, N);
25-
}
18+
#define TEST_FUNC(id, N) \
19+
static __m128i \
20+
__attribute__((noinline, unused)) \
21+
test##id (__m128i s1) \
22+
{ \
23+
return _mm_slli_epi32 (s1, N); \
24+
}
25+
26+
TEST_FUNC(0, 0)
27+
TEST_FUNC(15, 15)
28+
TEST_FUNC(16, 16)
29+
TEST_FUNC(31, 31)
30+
TEST_FUNC(neg1, -1)
31+
TEST_FUNC(neg16, -16)
32+
TEST_FUNC(neg32, -32)
33+
TEST_FUNC(neg64, -64)
34+
TEST_FUNC(neg128, -128)
35+
36+
#define TEST_CODE(id, N) \
37+
{ \
38+
int e[4] = {0}; \
39+
union128i_d u, s; \
40+
int i; \
41+
s.x = _mm_set_epi32 (1, -2, 3, 4); \
42+
u.x = test##id (s.x); \
43+
if (N >= 0 && N < 32) \
44+
for (i = 0; i < 4; i++) \
45+
e[i] = s.a[i] << (N * (N >= 0)); \
46+
if (check_union128i_d (u, e)) \
47+
abort (); \
48+
}
2649

2750
static void
2851
TEST (void)
2952
{
30-
union128i_d u, s;
31-
int e[4] = {0};
32-
int i;
33-
34-
s.x = _mm_set_epi32 (1, -2, 3, 4);
35-
36-
u.x = test (s.x);
37-
38-
if (N < 32)
39-
for (i = 0; i < 4; i++)
40-
e[i] = s.a[i] << N;
41-
42-
if (check_union128i_d (u, e))
43-
abort ();
53+
TEST_CODE(0, 0);
54+
TEST_CODE(15, 15);
55+
TEST_CODE(16, 16);
56+
TEST_CODE(31, 31);
57+
TEST_CODE(neg1, -1);
58+
TEST_CODE(neg16, -16);
59+
TEST_CODE(neg32, -32);
60+
TEST_CODE(neg64, -64);
61+
TEST_CODE(neg128, -128);
4462
}

gcc/testsuite/gcc.target/powerpc/sse2-psllq-1.c

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,56 @@
1313
#define TEST sse2_test_psllq_1
1414
#endif
1515

16-
#define N 60
17-
1816
#include <emmintrin.h>
1917

2018
#ifdef _ARCH_PWR8
21-
static __m128i
22-
__attribute__((noinline, unused))
23-
test (__m128i s1)
24-
{
25-
return _mm_slli_epi64 (s1, N);
26-
}
19+
#define TEST_FUNC(id, N) \
20+
static __m128i \
21+
__attribute__((noinline, unused)) \
22+
test##id (__m128i s1) \
23+
{ \
24+
return _mm_slli_epi64 (s1, N); \
25+
}
26+
27+
TEST_FUNC(0, 0)
28+
TEST_FUNC(15, 15)
29+
TEST_FUNC(16, 16)
30+
TEST_FUNC(31, 31)
31+
TEST_FUNC(63, 63)
32+
TEST_FUNC(neg1, -1)
33+
TEST_FUNC(neg16, -16)
34+
TEST_FUNC(neg32, -32)
35+
TEST_FUNC(neg64, -64)
36+
TEST_FUNC(neg128, -128)
2737
#endif
2838

39+
#define TEST_CODE(id, N) \
40+
{ \
41+
union128i_q u, s; \
42+
long long e[2] = {0}; \
43+
int i; \
44+
s.x = _mm_set_epi64x (-1, 0xf); \
45+
u.x = test##id (s.x); \
46+
if (N >= 0 && N < 64) \
47+
for (i = 0; i < 2; i++) \
48+
e[i] = s.a[i] << (N * (N >= 0)); \
49+
if (check_union128i_q (u, e)) \
50+
abort (); \
51+
}
52+
2953
static void
3054
TEST (void)
3155
{
3256
#ifdef _ARCH_PWR8
33-
union128i_q u, s;
34-
long long e[2] = {0};
35-
int i;
36-
37-
s.x = _mm_set_epi64x (-1, 0xf);
38-
39-
u.x = test (s.x);
40-
41-
if (N < 64)
42-
for (i = 0; i < 2; i++)
43-
e[i] = s.a[i] << N;
44-
45-
if (check_union128i_q (u, e))
46-
abort ();
57+
TEST_CODE(0, 0);
58+
TEST_CODE(15, 15);
59+
TEST_CODE(16, 16);
60+
TEST_CODE(31, 31);
61+
TEST_CODE(63, 63);
62+
TEST_CODE(neg1, -1);
63+
TEST_CODE(neg16, -16);
64+
TEST_CODE(neg32, -32);
65+
TEST_CODE(neg64, -64);
66+
TEST_CODE(neg128, -128);
4767
#endif
4868
}

gcc/testsuite/gcc.target/powerpc/sse2-psllw-1.c

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,48 @@
1313
#define TEST sse2_test_psllw_1
1414
#endif
1515

16-
#define N 0xb
17-
1816
#include <emmintrin.h>
1917

20-
static __m128i
21-
__attribute__((noinline, unused))
22-
test (__m128i s1)
23-
{
24-
return _mm_slli_epi16 (s1, N);
25-
}
18+
#define TEST_FUNC(id, N) \
19+
static __m128i \
20+
__attribute__((noinline, unused)) \
21+
test##id (__m128i s1) \
22+
{ \
23+
return _mm_slli_epi16 (s1, N); \
24+
}
25+
26+
TEST_FUNC(0, 0)
27+
TEST_FUNC(15, 15)
28+
TEST_FUNC(16, 16)
29+
TEST_FUNC(neg1, -1)
30+
TEST_FUNC(neg16, -16)
31+
TEST_FUNC(neg32, -32)
32+
TEST_FUNC(neg64, -64)
33+
TEST_FUNC(neg128, -128)
34+
35+
#define TEST_CODE(id, N) \
36+
{ \
37+
short e[8] = {0}; \
38+
union128i_w u, s; \
39+
int i; \
40+
s.x = _mm_set_epi16 (1, 2, 3, 4, 5, 6, 0x7000, 0x9000); \
41+
u.x = test##id (s.x); \
42+
if (N >= 0 && N < 16) \
43+
for (i = 0; i < 8; i++) \
44+
e[i] = s.a[i] << (N * (N >= 0)); \
45+
if (check_union128i_w (u, e)) \
46+
abort (); \
47+
}
2648

2749
static void
2850
TEST (void)
2951
{
30-
union128i_w u, s;
31-
short e[8] = {0};
32-
int i;
33-
34-
s.x = _mm_set_epi16 (1, 2, 3, 4, 5, 6, 0x7000, 0x9000);
35-
36-
u.x = test (s.x);
37-
38-
if (N < 16)
39-
for (i = 0; i < 8; i++)
40-
e[i] = s.a[i] << N;
41-
42-
if (check_union128i_w (u, e))
43-
abort ();
52+
TEST_CODE(0, 0);
53+
TEST_CODE(15, 15);
54+
TEST_CODE(16, 16);
55+
TEST_CODE(neg1, -1);
56+
TEST_CODE(neg16, -16);
57+
TEST_CODE(neg32, -32);
58+
TEST_CODE(neg64, -64);
59+
TEST_CODE(neg128, -128);
4460
}

0 commit comments

Comments
 (0)