From 1d238c84025aaef1641e4000bd2a8f4328b474dd Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 25 Apr 2024 12:44:14 +0200 Subject: Fix calling convention incompatibility with vendor compiler For the 20th anniversary of https://gcc.gnu.org/gcc-3.4/sparc-abi.html, a new calling convention incompatibility with the vendor compiler (and the ABI) has been discovered in 64-bit mode, affecting small structures containing arrays of floating-point components. The decision has been made to fix it on Solaris only at this point. gcc/ PR target/114416 * config/sparc/sparc.h (SUN_V9_ABI_COMPATIBILITY): New macro. * config/sparc/sol2.h (SUN_V9_ABI_COMPATIBILITY): Redefine it. * config/sparc/sparc.cc (fp_type_for_abi): New predicate. (traverse_record_type): Use it to spot floating-point types. (compute_fp_layout): Also deal with array types. gcc/testsuite/ * gcc.target/sparc/small-struct-1.c: New test. * gcc.target/sparc/pr105573.c: Rename to... * gcc.target/sparc/20230425-1.c: ...this. * gcc.target/sparc/pr109541.c: Rename to... * gcc.target/sparc/20230607-1.c: ...this --- gcc/config/sparc/sol2.h | 3 ++ gcc/config/sparc/sparc.cc | 26 ++++++++++++-- gcc/config/sparc/sparc.h | 3 ++ gcc/testsuite/gcc.target/sparc/20230425-1.c | 18 ++++++++++ gcc/testsuite/gcc.target/sparc/20230607-1.c | 26 ++++++++++++++ gcc/testsuite/gcc.target/sparc/pr105573.c | 15 -------- gcc/testsuite/gcc.target/sparc/pr109541.c | 23 ------------- gcc/testsuite/gcc.target/sparc/small-struct-1.c | 46 +++++++++++++++++++++++++ 8 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/sparc/20230425-1.c create mode 100644 gcc/testsuite/gcc.target/sparc/20230607-1.c delete mode 100644 gcc/testsuite/gcc.target/sparc/pr105573.c delete mode 100644 gcc/testsuite/gcc.target/sparc/pr109541.c create mode 100644 gcc/testsuite/gcc.target/sparc/small-struct-1.c (limited to 'gcc') diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index e849af9..552f58b 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -456,3 +456,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #undef SPARC_LOW_FE_EXCEPT_VALUES #define SPARC_LOW_FE_EXCEPT_VALUES 1 + +#undef SUN_V9_ABI_COMPATIBILITY +#define SUN_V9_ABI_COMPATIBILITY 1 diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc index 30fa447..8a5f76c 100644 --- a/gcc/config/sparc/sparc.cc +++ b/gcc/config/sparc/sparc.cc @@ -6782,6 +6782,22 @@ sparc_pass_by_reference (cumulative_args_t, const function_arg_info &arg) || GET_MODE_SIZE (mode) > 16); } +/* Return true if TYPE is considered as a floating-point type by the ABI. */ + +static bool +fp_type_for_abi (const_tree type) +{ + /* This is the original GCC implementation. */ + if (FLOAT_TYPE_P (type) || VECTOR_TYPE_P (type)) + return true; + + /* This has been introduced in GCC 14 to match the vendor compiler. */ + if (SUN_V9_ABI_COMPATIBILITY && TREE_CODE (type) == ARRAY_TYPE) + return fp_type_for_abi (TREE_TYPE (type)); + + return false; +} + /* Traverse the record TYPE recursively and call FUNC on its fields. NAMED is true if this is for a named parameter. DATA is passed to FUNC for each field. OFFSET is the starting position and @@ -6820,8 +6836,7 @@ traverse_record_type (const_tree type, bool named, T *data, packed); else { - const bool fp_type - = FLOAT_TYPE_P (field_type) || VECTOR_TYPE_P (field_type); + const bool fp_type = fp_type_for_abi (field_type); Func (field, bitpos, fp_type && named && !packed && TARGET_FPU, data); } @@ -7072,6 +7087,13 @@ compute_fp_layout (const_tree field, int bitpos, assign_data_t *data, mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field))); nregs = 2; } + else if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) + { + tree elt_type = strip_array_types (TREE_TYPE (field)); + mode = TYPE_MODE (elt_type); + nregs + = int_size_in_bytes (TREE_TYPE (field)) / int_size_in_bytes (elt_type); + } else nregs = 1; diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index fb07480..232ecb3 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1700,3 +1700,6 @@ extern int sparc_indent_opcode; #define SPARC_LOW_FE_EXCEPT_VALUES 0 #define TARGET_SUPPORTS_WIDE_INT 1 + +/* Define this to 1 to accept ABI changes to match the vendor compiler. */ +#define SUN_V9_ABI_COMPATIBILITY 0 diff --git a/gcc/testsuite/gcc.target/sparc/20230425-1.c b/gcc/testsuite/gcc.target/sparc/20230425-1.c new file mode 100644 index 0000000..c07dd32 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/20230425-1.c @@ -0,0 +1,18 @@ +/* PR target/105573 */ +/* Reported by Sam James */ + +/* { dg-do compile } */ +/* { dg-options "-O3 -mvis3" } */ + +int *UINT_sign_args, UINT_sign_steps; +int *UINT_sign_ip1; + +void UINT_sign() { + char *op1 = (char*) UINT_sign_args; + int os1 = UINT_sign_steps, i; + for (; i; i++, op1 += os1) { + unsigned in = *(unsigned *)UINT_sign_ip1; + int *out = (int*) op1; + *out = in > 0; + } +} diff --git a/gcc/testsuite/gcc.target/sparc/20230607-1.c b/gcc/testsuite/gcc.target/sparc/20230607-1.c new file mode 100644 index 0000000..3613dca --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/20230607-1.c @@ -0,0 +1,26 @@ +/* PR target.109541 */ +/* Reported by Sam James */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -mcpu=niagara4 -fpic -w" } */ + +int rhash_sha512_process_block_A, rhash_sha512_process_block_i, +rhash_sha512_process_block_block, rhash_sha512_process_block_W_0; + +unsigned rhash_sha512_process_block_W_2; + +void rhash_sha512_process_block (void) +{ + unsigned C, E, F, G, H, W_0, W_4, W_9, W_5, W_3, T1; + + for (; rhash_sha512_process_block_i; rhash_sha512_process_block_i += 6) { + T1 = F + (rhash_sha512_process_block_W_2 += 6); + rhash_sha512_process_block_A += H & G + (W_5 += rhash_sha512_process_block_W_0); + H = C & T1 & E ^ F + (W_9 += rhash_sha512_process_block_W_0); + G = T1 ^ 6 + (W_0 += rhash_sha512_process_block_block); + F = (unsigned) &G; + T1 = (unsigned) (&T1 + (W_3 += rhash_sha512_process_block_block > 9 > W_4)); + C = (unsigned) (T1 + &E); + W_4 += W_5 += rhash_sha512_process_block_W_0; + } +} diff --git a/gcc/testsuite/gcc.target/sparc/pr105573.c b/gcc/testsuite/gcc.target/sparc/pr105573.c deleted file mode 100644 index 14043a5..0000000 --- a/gcc/testsuite/gcc.target/sparc/pr105573.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -mvis3" } */ - -int *UINT_sign_args, UINT_sign_steps; -int *UINT_sign_ip1; - -void UINT_sign() { - char *op1 = (char*) UINT_sign_args; - int os1 = UINT_sign_steps, i; - for (; i; i++, op1 += os1) { - unsigned in = *(unsigned *)UINT_sign_ip1; - int *out = (int*) op1; - *out = in > 0; - } -} diff --git a/gcc/testsuite/gcc.target/sparc/pr109541.c b/gcc/testsuite/gcc.target/sparc/pr109541.c deleted file mode 100644 index 1360f10..0000000 --- a/gcc/testsuite/gcc.target/sparc/pr109541.c +++ /dev/null @@ -1,23 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O1 -mcpu=niagara4 -fpic -w" } */ - -int rhash_sha512_process_block_A, rhash_sha512_process_block_i, -rhash_sha512_process_block_block, rhash_sha512_process_block_W_0; - -unsigned rhash_sha512_process_block_W_2; - -void rhash_sha512_process_block (void) -{ - unsigned C, E, F, G, H, W_0, W_4, W_9, W_5, W_3, T1; - - for (; rhash_sha512_process_block_i; rhash_sha512_process_block_i += 6) { - T1 = F + (rhash_sha512_process_block_W_2 += 6); - rhash_sha512_process_block_A += H & G + (W_5 += rhash_sha512_process_block_W_0); - H = C & T1 & E ^ F + (W_9 += rhash_sha512_process_block_W_0); - G = T1 ^ 6 + (W_0 += rhash_sha512_process_block_block); - F = (unsigned) &G; - T1 = (unsigned) (&T1 + (W_3 += rhash_sha512_process_block_block > 9 > W_4)); - C = (unsigned) (T1 + &E); - W_4 += W_5 += rhash_sha512_process_block_W_0; - } -} diff --git a/gcc/testsuite/gcc.target/sparc/small-struct-1.c b/gcc/testsuite/gcc.target/sparc/small-struct-1.c new file mode 100644 index 0000000..4897288 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/small-struct-1.c @@ -0,0 +1,46 @@ +/* PR target/114416 */ +/* Reported by Rainer Orth */ + +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-require-effective-target lp64 } */ + +struct vec2 +{ + double x[2]; +}; + +struct vec2x +{ + double x; + double y; +}; + +struct vec2 sum2 (double val) +{ + struct vec2 v; + v.x[0] = val; + v.x[1] = val; + return v; +} + +struct vec2x sum2x (double val) +{ + struct vec2x v; + v.x = val; + v.y = val; + return v; +} + +double get2 (struct vec2 v) +{ + return v.x[0] + v.x[1]; +} + +double get2x (struct vec2x v) +{ + return v.x + v.y; +} + +/* { dg-final { scan-assembler-not "ldx" } } */ +/* { dg-final { scan-assembler-not "stx" } } */ -- cgit v1.1