summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-10-22 06:58:57 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-10-22 06:58:57 +0000
commit6e154e02514032b673c74fa03a7412ec69c69ce9 (patch)
tree1493e35cc3b270e4b934b928b0311cda8b335208
parentb38cf1ab536f203e48dff474a375bd3f02682b80 (diff)
downloadgcc-6e154e02514032b673c74fa03a7412ec69c69ce9.tar.gz
PR target/63594
* config/i386/i386.c (ix86_expand_vector_init_duplicate): For V{8HI,16QI,16HI,32QI}mode call ix86_vector_duplicate_value even for just TARGET_AVX2, not only for TARGET_AVX512VL && TARGET_AVX512BW. For V{32HI,64QI}mode, call ix86_vector_duplicate_value only if TARGET_AVX512BW, otherwise build it using concatenation of 256-bit broadcast. * config/i386/sse.md (AVX_VEC_DUP_MODE): Moved after avx512 broadcast patterns. (vec_dup<mode>): Likewise. For avx2 use v<sseintprefix>broadcast<bcstscalarsuff> instead of vbroadcast<ssescalarmodesuffix>. (AVX2_VEC_DUP_MODE): New mode iterator. (*vec_dup<mode>): New TARGET_AVX2 define_insn with AVX2_VEC_DUP_MODE iterator, add a splitter for that. * gcc.dg/pr63594-1.c: New test. * gcc.dg/pr63594-2.c: New test. * gcc.target/i386/sse2-pr63594-1.c: New test. * gcc.target/i386/sse2-pr63594-2.c: New test. * gcc.target/i386/avx-pr63594-1.c: New test. * gcc.target/i386/avx-pr63594-2.c: New test. * gcc.target/i386/avx2-pr63594-1.c: New test. * gcc.target/i386/avx2-pr63594-2.c: New test. * gcc.target/i386/avx512f-pr63594-1.c: New test. * gcc.target/i386/avx512f-pr63594-2.c: New test. * gcc.target/i386/avx512f-vec-init.c: Adjust expected insn counts. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@216541 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/i386/i386.c31
-rw-r--r--gcc/config/i386/sse.md72
-rw-r--r--gcc/testsuite/ChangeLog14
-rw-r--r--gcc/testsuite/gcc.dg/pr63594-1.c65
-rw-r--r--gcc/testsuite/gcc.dg/pr63594-2.c92
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-pr63594-1.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-pr63594-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-pr63594-1.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-pr63594-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-pr63594-1.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-pr63594-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vec-init.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-pr63594-1.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-pr63594-2.c18
15 files changed, 363 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2ef7289879a..5ff077fbb22 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
2014-10-22 Jakub Jelinek <jakub@redhat.com>
+ PR target/63594
+ * config/i386/i386.c (ix86_expand_vector_init_duplicate): For
+ V{8HI,16QI,16HI,32QI}mode call ix86_vector_duplicate_value
+ even for just TARGET_AVX2, not only for
+ TARGET_AVX512VL && TARGET_AVX512BW. For V{32HI,64QI}mode,
+ call ix86_vector_duplicate_value only if TARGET_AVX512BW,
+ otherwise build it using concatenation of 256-bit
+ broadcast.
+ * config/i386/sse.md (AVX_VEC_DUP_MODE): Moved after
+ avx512 broadcast patterns.
+ (vec_dup<mode>): Likewise. For avx2 use
+ v<sseintprefix>broadcast<bcstscalarsuff> instead of
+ vbroadcast<ssescalarmodesuffix>.
+ (AVX2_VEC_DUP_MODE): New mode iterator.
+ (*vec_dup<mode>): New TARGET_AVX2 define_insn with
+ AVX2_VEC_DUP_MODE iterator, add a splitter for that.
+
PR target/63542
* config/i386/i386.c (ix86_pic_register_p): Also return
true if x is a hard register with ORIGINAL_REGNO equal to
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a6ff41de813..94b7f798b9e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -39870,8 +39870,6 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
case V8SFmode:
case V8SImode:
case V2DFmode:
- case V64QImode:
- case V32HImode:
case V2DImode:
case V4SFmode:
case V4SImode:
@@ -39902,8 +39900,8 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
goto widen;
case V8HImode:
- if (TARGET_AVX512VL && TARGET_AVX512BW)
- return ix86_vector_duplicate_value (mode, target, val);
+ if (TARGET_AVX2)
+ return ix86_vector_duplicate_value (mode, target, val);
if (TARGET_SSE2)
{
@@ -39935,8 +39933,8 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
goto widen;
case V16QImode:
- if (TARGET_AVX512VL && TARGET_AVX512BW)
- return ix86_vector_duplicate_value (mode, target, val);
+ if (TARGET_AVX2)
+ return ix86_vector_duplicate_value (mode, target, val);
if (TARGET_SSE2)
goto permute;
@@ -39967,8 +39965,8 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
case V16HImode:
case V32QImode:
- if (TARGET_AVX512VL && TARGET_AVX512BW)
- return ix86_vector_duplicate_value (mode, target, val);
+ if (TARGET_AVX2)
+ return ix86_vector_duplicate_value (mode, target, val);
else
{
enum machine_mode hvmode = (mode == V16HImode ? V8HImode : V16QImode);
@@ -39982,6 +39980,23 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
}
return true;
+ case V64QImode:
+ case V32HImode:
+ if (TARGET_AVX512BW)
+ return ix86_vector_duplicate_value (mode, target, val);
+ else
+ {
+ enum machine_mode hvmode = (mode == V32HImode ? V16HImode : V32QImode);
+ rtx x = gen_reg_rtx (hvmode);
+
+ ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
+ gcc_assert (ok);
+
+ x = gen_rtx_VEC_CONCAT (mode, x, x);
+ emit_insn (gen_rtx_SET (VOIDmode, target, x));
+ }
+ return true;
+
default:
return false;
}
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index a3f336fa15f..b7c2c4f59be 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -16523,25 +16523,6 @@
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
-;; Modes handled by AVX vec_dup patterns.
-(define_mode_iterator AVX_VEC_DUP_MODE
- [V8SI V8SF V4DI V4DF])
-
-(define_insn "vec_dup<mode>"
- [(set (match_operand:AVX_VEC_DUP_MODE 0 "register_operand" "=x,v,x")
- (vec_duplicate:AVX_VEC_DUP_MODE
- (match_operand:<ssescalarmode> 1 "nonimmediate_operand" "m,v,?x")))]
- "TARGET_AVX"
- "@
- vbroadcast<ssescalarmodesuffix>\t{%1, %0|%0, %1}
- vbroadcast<ssescalarmodesuffix>\t{%x1, %0|%0, %x1}
- #"
- [(set_attr "type" "ssemov")
- (set_attr "prefix_extra" "1")
- (set_attr "prefix" "maybe_evex")
- (set_attr "isa" "*,avx2,noavx2")
- (set_attr "mode" "V8SF")])
-
(define_insn "<avx512>_vec_dup<mode><mask_name>"
[(set (match_operand:V48_AVX512VL 0 "register_operand" "=v")
(vec_duplicate:V48_AVX512VL
@@ -16644,6 +16625,59 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+;; Modes handled by AVX vec_dup patterns.
+(define_mode_iterator AVX_VEC_DUP_MODE
+ [V8SI V8SF V4DI V4DF])
+;; Modes handled by AVX2 vec_dup patterns.
+(define_mode_iterator AVX2_VEC_DUP_MODE
+ [V32QI V16QI V16HI V8HI V8SI V4SI])
+
+(define_insn "*vec_dup<mode>"
+ [(set (match_operand:AVX2_VEC_DUP_MODE 0 "register_operand" "=x,x,x")
+ (vec_duplicate:AVX2_VEC_DUP_MODE
+ (match_operand:<ssescalarmode> 1 "nonimmediate_operand" "m,x,!r")))]
+ "TARGET_AVX2"
+ "@
+ v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0|%0, %1}
+ v<sseintprefix>broadcast<bcstscalarsuff>\t{%x1, %0|%0, %x1}
+ #"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "maybe_evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "vec_dup<mode>"
+ [(set (match_operand:AVX_VEC_DUP_MODE 0 "register_operand" "=x,x,v,x")
+ (vec_duplicate:AVX_VEC_DUP_MODE
+ (match_operand:<ssescalarmode> 1 "nonimmediate_operand" "m,m,v,?x")))]
+ "TARGET_AVX"
+ "@
+ v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0|%0, %1}
+ vbroadcast<ssescalarmodesuffix>\t{%1, %0|%0, %1}
+ v<sseintprefix>broadcast<bcstscalarsuff>\t{%x1, %0|%0, %x1}
+ #"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "maybe_evex")
+ (set_attr "isa" "avx2,noavx2,avx2,noavx2")
+ (set_attr "mode" "<sseinsnmode>,V8SF,<sseinsnmode>,V8SF")])
+
+(define_split
+ [(set (match_operand:AVX2_VEC_DUP_MODE 0 "register_operand")
+ (vec_duplicate:AVX2_VEC_DUP_MODE
+ (match_operand:<ssescalarmode> 1 "register_operand")))]
+ "TARGET_AVX2 && reload_completed && GENERAL_REG_P (operands[1])"
+ [(const_int 0)]
+{
+ emit_insn (gen_vec_setv4si_0 (gen_lowpart (V4SImode, operands[0]),
+ CONST0_RTX (V4SImode),
+ gen_lowpart (SImode, operands[1])));
+ emit_insn (gen_avx2_pbroadcast<mode> (operands[0],
+ gen_lowpart (<ssexmmmode>mode,
+ operands[0])));
+ DONE;
+})
+
(define_split
[(set (match_operand:AVX_VEC_DUP_MODE 0 "register_operand")
(vec_duplicate:AVX_VEC_DUP_MODE
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b0c392bb089..fa09a9c10c3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,19 @@
2014-10-22 Jakub Jelinek <jakub@redhat.com>
+ PR target/63594
+ * gcc.dg/pr63594-1.c: New test.
+ * gcc.dg/pr63594-2.c: New test.
+ * gcc.target/i386/sse2-pr63594-1.c: New test.
+ * gcc.target/i386/sse2-pr63594-2.c: New test.
+ * gcc.target/i386/avx-pr63594-1.c: New test.
+ * gcc.target/i386/avx-pr63594-2.c: New test.
+ * gcc.target/i386/avx2-pr63594-1.c: New test.
+ * gcc.target/i386/avx2-pr63594-2.c: New test.
+ * gcc.target/i386/avx512f-pr63594-1.c: New test.
+ * gcc.target/i386/avx512f-pr63594-2.c: New test.
+ * gcc.target/i386/avx512f-vec-init.c: Adjust expected
+ insn counts.
+
PR target/63542
* gcc.target/i386/pr63542-1.c: New test.
* gcc.target/i386/pr63542-2.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr63594-1.c b/gcc/testsuite/gcc.dg/pr63594-1.c
new file mode 100644
index 00000000000..2c577964003
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr63594-1.c
@@ -0,0 +1,65 @@
+/* PR target/63594 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi" } */
+/* { dg-additional-options "-mno-mmx" { target i?86-*-linux* x86_64-*-linux* } } */
+
+#define C1 c
+#define C2 C1, C1
+#define C4 C2, C2
+#define C8 C4, C4
+#define C16 C8, C8
+#define C32 C16, C16
+#define C64 C32, C32
+#define C_(n) n
+#define C(n) C_(C##n)
+
+#define T(t,s) \
+typedef t v##t##s __attribute__ ((__vector_size__ (s * sizeof (t)))); \
+v##t##s \
+test1##t##s (t c) \
+{ \
+ v##t##s v = { C(s) }; \
+ return v; \
+} \
+ \
+v##t##s \
+test2##t##s (t *p) \
+{ \
+ t c = *p; \
+ v##t##s v = { C(s) }; \
+ return v; \
+}
+
+typedef long long llong;
+
+T(char, 64)
+T(char, 32)
+T(char, 16)
+T(char, 8)
+T(char, 4)
+T(char, 2)
+T(char, 1)
+T(short, 32)
+T(short, 16)
+T(short, 8)
+T(short, 4)
+T(short, 2)
+T(short, 1)
+T(int, 16)
+T(int, 8)
+T(int, 4)
+T(int, 2)
+T(int, 1)
+T(float, 16)
+T(float, 8)
+T(float, 4)
+T(float, 2)
+T(float, 1)
+T(llong, 8)
+T(llong, 4)
+T(llong, 2)
+T(llong, 1)
+T(double, 8)
+T(double, 4)
+T(double, 2)
+T(double, 1)
diff --git a/gcc/testsuite/gcc.dg/pr63594-2.c b/gcc/testsuite/gcc.dg/pr63594-2.c
new file mode 100644
index 00000000000..39a64fa88da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr63594-2.c
@@ -0,0 +1,92 @@
+/* PR target/63594 */
+/* { dg-do run } */
+/* { dg-options "-O2 -Wno-psabi" } */
+/* { dg-additional-options "-mno-mmx" { target i?86-*-linux* x86_64-*-linux* } } */
+
+#define C1 c
+#define C2 C1, C1
+#define C4 C2, C2
+#define C8 C4, C4
+#define C16 C8, C8
+#define C32 C16, C16
+#define C64 C32, C32
+#define C_(n) n
+#define C(n) C_(C##n)
+
+#define T(t,s) \
+typedef t v##t##s __attribute__ ((__vector_size__ (s * sizeof (t)))); \
+__attribute__((noinline, noclone)) v##t##s \
+test1##t##s (t c) \
+{ \
+ v##t##s v = { C(s) }; \
+ return v; \
+} \
+ \
+__attribute__((noinline, noclone)) v##t##s \
+test2##t##s (t *p) \
+{ \
+ t c = *p; \
+ v##t##s v = { C(s) }; \
+ return v; \
+} \
+ \
+void \
+test3##t##s (void) \
+{ \
+ t c = 17; \
+ int i; \
+ v##t##s a = test1##t##s (c); \
+ for (i = 0; i < s; i++) \
+ if (a[i] != 17) \
+ __builtin_abort (); \
+ v##t##s b = test2##t##s (&c); \
+ for (i = 0; i < s; i++) \
+ if (a[i] != 17) \
+ __builtin_abort (); \
+}
+
+typedef long long llong;
+
+#define TESTS \
+T(char, 64) \
+T(char, 32) \
+T(char, 16) \
+T(char, 8) \
+T(char, 4) \
+T(char, 2) \
+T(char, 1) \
+T(short, 32) \
+T(short, 16) \
+T(short, 8) \
+T(short, 4) \
+T(short, 2) \
+T(short, 1) \
+T(int, 16) \
+T(int, 8) \
+T(int, 4) \
+T(int, 2) \
+T(int, 1) \
+T(float, 16) \
+T(float, 8) \
+T(float, 4) \
+T(float, 2) \
+T(float, 1) \
+T(llong, 8) \
+T(llong, 4) \
+T(llong, 2) \
+T(llong, 1) \
+T(double, 8) \
+T(double, 4) \
+T(double, 2) \
+T(double, 1)
+
+TESTS
+
+int
+main ()
+{
+#undef T
+#define T(t,s) test3##t##s ();
+ TESTS
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-pr63594-1.c b/gcc/testsuite/gcc.target/i386/avx-pr63594-1.c
new file mode 100644
index 00000000000..596a44b8073
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-pr63594-1.c
@@ -0,0 +1,5 @@
+/* PR target/63594 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mno-mmx -Wno-psabi" } */
+
+#include "../../gcc.dg/pr63594-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-pr63594-2.c b/gcc/testsuite/gcc.target/i386/avx-pr63594-2.c
new file mode 100644
index 00000000000..566a6c4402b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-pr63594-2.c
@@ -0,0 +1,18 @@
+/* PR target/63594 */
+/* { dg-do run { target avx } } */
+/* { dg-options "-O2 -mavx -mno-mmx -Wno-psabi" } */
+
+#include "avx-check.h"
+
+int do_main (void);
+
+static void
+avx_test (void)
+{
+ do_main ();
+}
+
+#undef main
+#define main() do_main ()
+
+#include "../../gcc.dg/pr63594-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr63594-1.c b/gcc/testsuite/gcc.target/i386/avx2-pr63594-1.c
new file mode 100644
index 00000000000..72bb7613fcf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-pr63594-1.c
@@ -0,0 +1,5 @@
+/* PR target/63594 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -mno-mmx -Wno-psabi" } */
+
+#include "../../gcc.dg/pr63594-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr63594-2.c b/gcc/testsuite/gcc.target/i386/avx2-pr63594-2.c
new file mode 100644
index 00000000000..86d2fb52d5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-pr63594-2.c
@@ -0,0 +1,18 @@
+/* PR target/63594 */
+/* { dg-do run { target avx2 } } */
+/* { dg-options "-O2 -mavx2 -mno-mmx -Wno-psabi" } */
+
+#include "avx2-check.h"
+
+int do_main (void);
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
+
+#undef main
+#define main() do_main ()
+
+#include "../../gcc.dg/pr63594-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr63594-1.c b/gcc/testsuite/gcc.target/i386/avx512f-pr63594-1.c
new file mode 100644
index 00000000000..ab28987868d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-pr63594-1.c
@@ -0,0 +1,5 @@
+/* PR target/63594 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f -mno-mmx -Wno-psabi" } */
+
+#include "../../gcc.dg/pr63594-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr63594-2.c b/gcc/testsuite/gcc.target/i386/avx512f-pr63594-2.c
new file mode 100644
index 00000000000..cd3288fa873
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-pr63594-2.c
@@ -0,0 +1,18 @@
+/* PR target/63594 */
+/* { dg-do run { target avx512f } } */
+/* { dg-options "-O2 -mavx512f -mno-mmx -Wno-psabi" } */
+
+#include "avx512f-check.h"
+
+int do_main (void);
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
+
+#undef main
+#define main() do_main ()
+
+#include "../../gcc.dg/pr63594-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vec-init.c b/gcc/testsuite/gcc.target/i386/avx512f-vec-init.c
index acbd34f3f36..a8d5b0ccb15 100644
--- a/gcc/testsuite/gcc.target/i386/avx512f-vec-init.c
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vec-init.c
@@ -1,12 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O3 -mavx512f" } */
-/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+%zmm" 2 } } */
-/* { dg-final { scan-assembler-times "vpbroadcastd" 1 } } */
-/* { dg-final { scan-assembler-times "vpbroadcastq" 1 } } */
-/* { dg-final { scan-assembler-times "vpbroadcastb" 2 } } */
-/* { dg-final { scan-assembler-times "vpbroadcastw" 2 } } */
-/* { dg-final { scan-assembler-times "vbroadcastss" 1 } } */
-/* { dg-final { scan-assembler-times "vbroadcastsd" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa64\[ \\t\]+%zmm" 0 } } */
+/* { dg-final { scan-assembler-times "vpbroadcastd" 2 } } */
+/* { dg-final { scan-assembler-times "vpbroadcastq" 2 } } */
+/* { dg-final { scan-assembler-times "vpbroadcastb" 3 } } */
+/* { dg-final { scan-assembler-times "vpbroadcastw" 3 } } */
+/* { dg-final { scan-assembler-times "vbroadcastss" 0 } } */
+/* { dg-final { scan-assembler-times "vbroadcastsd" 0 } } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse2-pr63594-1.c b/gcc/testsuite/gcc.target/i386/sse2-pr63594-1.c
new file mode 100644
index 00000000000..89aa7057dbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-pr63594-1.c
@@ -0,0 +1,5 @@
+/* PR target/63594 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-mmx -Wno-psabi" } */
+
+#include "../../gcc.dg/pr63594-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-pr63594-2.c b/gcc/testsuite/gcc.target/i386/sse2-pr63594-2.c
new file mode 100644
index 00000000000..552f611bbae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-pr63594-2.c
@@ -0,0 +1,18 @@
+/* PR target/63594 */
+/* { dg-do run { target sse2 } } */
+/* { dg-options "-O2 -msse2 -mno-mmx -Wno-psabi" } */
+
+#include "sse2-check.h"
+
+int do_main (void);
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
+
+#undef main
+#define main() do_main ()
+
+#include "../../gcc.dg/pr63594-2.c"