From: Jakub Jelinek Date: Tue, 4 Apr 2017 10:45:55 +0000 (+0200) Subject: re PR target/80286 (AVX2 _mm_cvtsi128_si32 doesn't return a proper 32bits int) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b1fd967c2cfb38bdb42b986ca78deab2c2fc613e;p=gcc.git re PR target/80286 (AVX2 _mm_cvtsi128_si32 doesn't return a proper 32bits int) PR target/80286 * config/i386/i386.c (ix86_expand_args_builtin): If op has scalar int mode, convert_modes it to mode as unsigned, otherwise use lowpart_subreg to mode rather than SImode. * config/i386/sse.md (ashr3, ashr3, ashr3, 3): Use DImode instead of SImode for the shift count operand. * config/i386/mmx.md (mmx_ashr3, mmx_3): Likewise. testsuite/ * gcc.target/i386/avx-pr80286.c: New test. * gcc.dg/pr80286.c: New test. From-SVN: r246676 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eceada15c36..66d6cb719b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2017-04-04 Jakub Jelinek + + PR target/80286 + * config/i386/i386.c (ix86_expand_args_builtin): If op has scalar + int mode, convert_modes it to mode as unsigned, otherwise use + lowpart_subreg to mode rather than SImode. + * config/i386/sse.md (ashr3, + ashr3, ashr3, 3): + Use DImode instead of SImode for the shift count operand. + * config/i386/mmx.md (mmx_ashr3, mmx_3): + Likewise. + 2017-04-04 Richard Biener PR middle-end/80281 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 80b87736494..118ab50b6bb 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -35582,10 +35582,17 @@ ix86_expand_args_builtin (const struct builtin_description *d, { /* SIMD shift insns take either an 8-bit immediate or register as count. But builtin functions take int as - count. If count doesn't match, we put it in register. */ + count. If count doesn't match, we put it in register. + The instructions are using 64-bit count, if op is just + 32-bit, zero-extend it, as negative shift counts + are undefined behavior and zero-extension is more + efficient. */ if (!match) { - op = lowpart_subreg (SImode, op, GET_MODE (op)); + if (SCALAR_INT_MODE_P (GET_MODE (op))) + op = convert_modes (mode, GET_MODE (op), op, 1); + else + op = lowpart_subreg (mode, op, GET_MODE (op)); if (!insn_p->operand[i + 1].predicate (op, mode)) op = copy_to_reg (op); } diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 1e2e6c26eaa..68972bb45c9 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -930,7 +930,7 @@ [(set (match_operand:MMXMODE24 0 "register_operand" "=y") (ashiftrt:MMXMODE24 (match_operand:MMXMODE24 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "yN")))] + (match_operand:DI 2 "nonmemory_operand" "yN")))] "TARGET_MMX" "psra\t{%2, %0|%0, %2}" [(set_attr "type" "mmxshft") @@ -944,7 +944,7 @@ [(set (match_operand:MMXMODE248 0 "register_operand" "=y") (any_lshift:MMXMODE248 (match_operand:MMXMODE248 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "yN")))] + (match_operand:DI 2 "nonmemory_operand" "yN")))] "TARGET_MMX" "p\t{%2, %0|%0, %2}" [(set_attr "type" "mmxshft") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 1a9b332cc29..15ced880504 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -10620,7 +10620,7 @@ [(set (match_operand:VI24_AVX512BW_1 0 "register_operand" "=v,v") (ashiftrt:VI24_AVX512BW_1 (match_operand:VI24_AVX512BW_1 1 "nonimmediate_operand" "v,vm") - (match_operand:SI 2 "nonmemory_operand" "v,N")))] + (match_operand:DI 2 "nonmemory_operand" "v,N")))] "TARGET_AVX512VL" "vpsra\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sseishft") @@ -10634,7 +10634,7 @@ [(set (match_operand:VI24_AVX2 0 "register_operand" "=x,x") (ashiftrt:VI24_AVX2 (match_operand:VI24_AVX2 1 "register_operand" "0,x") - (match_operand:SI 2 "nonmemory_operand" "xN,xN")))] + (match_operand:DI 2 "nonmemory_operand" "xN,xN")))] "TARGET_SSE2" "@ psra\t{%2, %0|%0, %2} @@ -10667,7 +10667,7 @@ [(set (match_operand:VI248_AVX512BW_AVX512VL 0 "register_operand" "=v,v") (ashiftrt:VI248_AVX512BW_AVX512VL (match_operand:VI248_AVX512BW_AVX512VL 1 "nonimmediate_operand" "v,vm") - (match_operand:SI 2 "nonmemory_operand" "v,N")))] + (match_operand:DI 2 "nonmemory_operand" "v,N")))] "TARGET_AVX512F" "vpsra\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sseishft") @@ -10681,7 +10681,7 @@ [(set (match_operand:VI2_AVX2_AVX512BW 0 "register_operand" "=x,v") (any_lshift:VI2_AVX2_AVX512BW (match_operand:VI2_AVX2_AVX512BW 1 "register_operand" "0,v") - (match_operand:SI 2 "nonmemory_operand" "xN,vN")))] + (match_operand:DI 2 "nonmemory_operand" "xN,vN")))] "TARGET_SSE2 && && " "@ p\t{%2, %0|%0, %2} @@ -10700,7 +10700,7 @@ [(set (match_operand:VI48_AVX2 0 "register_operand" "=x,x,v") (any_lshift:VI48_AVX2 (match_operand:VI48_AVX2 1 "register_operand" "0,x,v") - (match_operand:SI 2 "nonmemory_operand" "xN,xN,vN")))] + (match_operand:DI 2 "nonmemory_operand" "xN,xN,vN")))] "TARGET_SSE2 && " "@ p\t{%2, %0|%0, %2} @@ -10720,7 +10720,7 @@ [(set (match_operand:VI48_512 0 "register_operand" "=v,v") (any_lshift:VI48_512 (match_operand:VI48_512 1 "nonimmediate_operand" "v,m") - (match_operand:SI 2 "nonmemory_operand" "vN,N")))] + (match_operand:DI 2 "nonmemory_operand" "vN,N")))] "TARGET_AVX512F && " "vp\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "avx512f") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8d7418cd366..e14af29e2b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-04-04 Jakub Jelinek + + PR target/80286 + * gcc.target/i386/avx-pr80286.c: New test. + * gcc.dg/pr80286.c: New test. + 2017-04-04 Richard Biener PR middle-end/80281 diff --git a/gcc/testsuite/gcc.dg/pr80286.c b/gcc/testsuite/gcc.dg/pr80286.c new file mode 100644 index 00000000000..82f35b50099 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr80286.c @@ -0,0 +1,23 @@ +/* PR target/80286 */ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-psabi" } */ + +typedef int V __attribute__((vector_size (4 * sizeof (int)))); + +__attribute__((noinline, noclone)) V +foo (V x, V y) +{ + return x << y[0]; +} + +int +main () +{ + V x = { 1, 2, 3, 4 }; + V y = { 5, 6, 7, 8 }; + V z = foo (x, y); + V e = { 1 << 5, 2 << 5, 3 << 5, 4 << 5 }; + if (__builtin_memcmp (&z, &e, sizeof (V))) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/avx-pr80286.c b/gcc/testsuite/gcc.target/i386/avx-pr80286.c new file mode 100644 index 00000000000..2e1881d218f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-pr80286.c @@ -0,0 +1,26 @@ +/* PR target/80286 */ +/* { dg-do run { target avx } } */ +/* { dg-options "-O2 -mavx" } */ + +#include "avx-check.h" +#include + +__m256i m; + +__attribute__((noinline, noclone)) __m128i +foo (__m128i x) +{ + int s = _mm_cvtsi128_si32 (_mm256_castsi256_si128 (m)); + return _mm_srli_epi16 (x, s); +} + +static void +avx_test (void) +{ + __m128i a = (__m128i) (__v8hi) { 1 << 7, 2 << 8, 3 << 9, 4 << 10, 5 << 11, 6 << 12, 7 << 13, 8 << 12 }; + m = (__m256i) (__v8si) { 7, 8, 9, 10, 11, 12, 13, 14 }; + __m128i c = foo (a); + __m128i b = (__m128i) (__v8hi) { 1, 2 << 1, 3 << 2, 4 << 3, 5 << 4, 6 << 5, 7 << 6, 8 << 5 }; + if (__builtin_memcmp (&c, &b, sizeof (__m128i))) + __builtin_abort (); +}