TYPE_MODE of record and union depends on whether vector_mode_supported_p returns true or not. x86-64 backend uses TYPE_MODE to decide how to pass a parameter and return a value in a function. 64-bit integer vectors were supported only by MMX and 64-bit float vector was supported only by 3DNOW. GCC 10 enabled 64-bit integer vectors without MMX by:
commit dfa61b9ed06d71901c4c430caa89820972ad68fe Author: H.J. Lu <hongjiu...@intel.com> Date: Wed May 15 15:02:54 2019 +0000 i386: Allow MMX register modes in SSE registers In 64-bit mode, SSE2 can be used to emulate MMX instructions without 3DNOW. We can use SSE2 to support MMX register modes. GCC 11 enabled 64-bit float vector without 3DNOW by: commit 7c355156aa20eaec7401d7c66f6a6cfbe597abc2 Author: Uros Bizjak <ubiz...@gmail.com> Date: Mon May 11 11:16:31 2020 +0200 i386: Vectorize basic V2SFmode operations [PR94913] Enable V2SFmode vectorization and vectorize V2SFmode PLUS, MINUS, MULT, MIN and MAX operations using XMM registers. Add ABI warnings for 64-bit integer vectors without MMX and 64-bit float vector without 3DNOW. gcc/ PR target/102027 PR target/102105 * config/i386/i386.c (single_m64_base_type): New function. (type_natural_mode): Add ABI warnings for 64-bit vectors. gcc/testsuite/ PR target/102027 PR target/102105 * gcc.target/i386/pr102027-1.c: New test. * gcc.target/i386/pr102027-2.c: Likewise. * gcc.target/i386/pr102027-3.c: Likewise. * gcc.target/i386/pr102105-1.c: Likewise. * gcc.target/i386/pr102105-2.c: Likewise. * gcc.target/i386/pr102105-3.c: Likewise. * gcc.target/i386/pr102105-4.c: Likewise. * gcc.target/i386/sse2-mmx-4.c: Add -Wno-psabi. --- gcc/config/i386/i386.c | 131 ++++++++++++++++++++- gcc/testsuite/gcc.target/i386/pr102027-1.c | 15 +++ gcc/testsuite/gcc.target/i386/pr102027-2.c | 15 +++ gcc/testsuite/gcc.target/i386/pr102027-3.c | 17 +++ gcc/testsuite/gcc.target/i386/pr102105-1.c | 15 +++ gcc/testsuite/gcc.target/i386/pr102105-2.c | 15 +++ gcc/testsuite/gcc.target/i386/pr102105-3.c | 17 +++ gcc/testsuite/gcc.target/i386/pr102105-4.c | 17 +++ gcc/testsuite/gcc.target/i386/sse2-mmx-4.c | 2 +- 9 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr102027-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102027-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102027-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102105-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102105-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102105-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr102105-4.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3bb2cab57a3..cd69e466ca7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1840,6 +1840,54 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ cfun->machine->arg_reg_available = (cum->nregs > 0); } +/* Return the single 64-bit vector type of TYPE. */ + +static const_tree +single_m64_base_type (const_tree type) +{ + if ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == QUAL_UNION_TYPE) + && int_size_in_bytes (type) == 8) + { + const_tree field; + const_tree first_field = nullptr; + + for (field = TYPE_FIELDS (type); + field; + field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + { + if (TREE_TYPE (field) == error_mark_node) + continue; + + /* Skip if structure has more than one field. */ + if (first_field) + return nullptr; + + first_field = field; + } + + /* Skip if structure doesn't have any fields. */ + if (!first_field) + return nullptr; + + type = TREE_TYPE (first_field); + + /* Skip if structure size isn't 64 bits. */ + if (int_size_in_bytes (type) != 8) + return nullptr; + + /* Return if a 64-bit vector is found. */ + if (TREE_CODE (type) == VECTOR_TYPE) + return type; + + return single_m64_base_type (type); + } + + return nullptr; +} + /* Return the "natural" mode for TYPE. In most cases, this is just TYPE_MODE. But in the case of vector types, it is some vector mode. @@ -1861,7 +1909,88 @@ static machine_mode type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum, bool in_return) { - machine_mode mode = TYPE_MODE (type); + machine_mode mode; + + const_tree m64_type = single_m64_base_type (type); + if (m64_type) + { + mode = TYPE_MODE (m64_type); + + if (!warn_psabi) + return mode; + + const char *url; + if (mode == V2SFmode) + { + /* GCC 11 enables V2SFmode without TARGET_3DNOW. */ + if (TARGET_3DNOW) + return mode; + + url = CHANGES_ROOT_URL "gcc-11/changes.html#x86_64_m64"; + if (in_return) + { + static bool warnedm64_ret; + if (!warnedm64_ret) + { + warnedm64_ret = true; + inform (input_location, + "the ABI of returning structure with a 64-bit " + "single precision vector has changed in " + "%{GCC 11.1%}", + url); + } + } + else + { + static bool warnedm64; + if (!warnedm64) + { + warnedm64 = true; + inform (input_location, + "the ABI of passing structure with a 64-bit " + "single precision vector has changed in " + "%{GCC 11.1%}", + url); + } + } + } + else + { + /* GCC 10 enables other MMX modes without TARGET_MMX. */ + if (TARGET_MMX) + return mode; + + url = CHANGES_ROOT_URL "gcc-10/changes.html#x86_64_m64"; + if (in_return) + { + static bool warnedm64_ret; + if (!warnedm64_ret) + { + warnedm64_ret = true; + inform (input_location, + "the ABI of returning structure with a 64-bit " + "integer vector has changed in %{GCC 10.1%}", + url); + } + } + else + { + static bool warnedm64; + if (!warnedm64) + { + warnedm64 = true; + inform (input_location, + "the ABI of passing structure with a 64-bit " + "integer vector has changed in %{GCC 10.1%}", + url); + } + } + } + + return mode; + } + + mode = TYPE_MODE (type); if (TREE_CODE (type) == VECTOR_TYPE && !VECTOR_MODE_P (mode)) { diff --git a/gcc/testsuite/gcc.target/i386/pr102027-1.c b/gcc/testsuite/gcc.target/i386/pr102027-1.c new file mode 100644 index 00000000000..f2c16771a06 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102027-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-3dnow" } */ + +struct V2SF { + __attribute__((__vector_size__(2 * sizeof(float)))) float v; +}; +extern struct V2SF x; +extern void foo (struct V2SF); + +struct V2SF +bar (void) +{ /* { dg-message "note: the ABI of returning structure with a 64-bit single precision vector has changed in GCC 11.1" } */ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit single precision vector has changed in GCC 11.1" } */ + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/pr102027-2.c b/gcc/testsuite/gcc.target/i386/pr102027-2.c new file mode 100644 index 00000000000..53d1586a68b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102027-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-3dnow" } */ + +union U2SF { + __attribute__((__vector_size__(2 * sizeof(float)))) float v; +}; +extern union U2SF x; +extern void foo (union U2SF); + +union U2SF +bar (void) +{ /* { dg-message "note: the ABI of returning structure with a 64-bit single precision vector has changed in GCC 11.1" } */ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit single precision vector has changed in GCC 11.1" } */ + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/pr102027-3.c b/gcc/testsuite/gcc.target/i386/pr102027-3.c new file mode 100644 index 00000000000..61e7318ec6f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102027-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-3dnow" } */ + +struct V2SF1 { + __attribute__((__vector_size__(2 * sizeof(float)))) float v; +}; +struct V2SF { + struct V2SF1 x; +}; +extern struct V2SF x; +extern void foo (struct V2SF); + +void +bar (void) +{ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit single precision vector has changed in GCC 11.1" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr102105-1.c b/gcc/testsuite/gcc.target/i386/pr102105-1.c new file mode 100644 index 00000000000..31344147419 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102105-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-mmx" } */ + +struct V8QI { + __attribute__((__vector_size__(8))) char v; +}; +extern struct V8QI x; +extern void foo (struct V8QI); + +struct V8QI +bar (void) +{ /* { dg-message "note: the ABI of returning structure with a 64-bit integer vector has changed in GCC 10.1" } */ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit integer vector has changed in GCC 10.1" } */ + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/pr102105-2.c b/gcc/testsuite/gcc.target/i386/pr102105-2.c new file mode 100644 index 00000000000..ab834217a24 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102105-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-mmx" } */ + +union U8QI { + __attribute__((__vector_size__(8))) char v; +}; +extern union U8QI x; +extern void foo (union U8QI); + +union U8QI +bar (void) +{ /* { dg-message "note: the ABI of returning structure with a 64-bit integer vector has changed in GCC 10.1" } */ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit integer vector has changed in GCC 10.1" } */ + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/pr102105-3.c b/gcc/testsuite/gcc.target/i386/pr102105-3.c new file mode 100644 index 00000000000..614309579c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102105-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-mmx" } */ + +struct V8QI1 { + __attribute__((__vector_size__(8))) char v; +}; +struct V8QI { + struct V8QI1 x; +}; +extern struct V8QI x; +extern void foo (struct V8QI); + +void +bar (void) +{ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit integer vector has changed in GCC 10.1" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr102105-4.c b/gcc/testsuite/gcc.target/i386/pr102105-4.c new file mode 100644 index 00000000000..54a4b6d86a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102105-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mno-mmx" } */ + +struct v1di +{ + __attribute__((__vector_size__(8))) long long ll; +}; +extern struct v1di x; + +extern void foo (struct v1di); + +struct v1di +bar (void) +{ /* { dg-message "note: the ABI of returning structure with a 64-bit integer vector has changed in GCC 10.1" } */ + foo (x); /* { dg-message "note: the ABI of passing structure with a 64-bit integer vector has changed in GCC 10.1" } */ + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c index d923724fc1c..01ee8db4a4a 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c +++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c @@ -1,4 +1,4 @@ /* { dg-do run { target { ! ia32 } } } */ -/* { dg-options "-O2 -msse2 -mno-mmx" } */ +/* { dg-options "-O2 -msse2 -mno-mmx -Wno-psabi" } */ #include "mmx-4.c" -- 2.31.1