aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-04-01 08:55:55 +0200
committerJakub Jelinek <jakub@redhat.com>2023-04-01 08:55:55 +0200
commitb1f6cb2cc3aad0521ad3181d5107e52be155fd18 (patch)
tree8685e8eb0e2633073de945b9ae7319ec9ca63d50 /gcc
parentfc4cde2e6aa4d6ebdf7f70b7b4359fb59a1915ae (diff)
downloadgcc-b1f6cb2cc3aad0521ad3181d5107e52be155fd18.zip
gcc-b1f6cb2cc3aad0521ad3181d5107e52be155fd18.tar.gz
gcc-b1f6cb2cc3aad0521ad3181d5107e52be155fd18.tar.bz2
aarch64, builtins: Include PR registers in FUNCTION_ARG_REGNO_P etc. [PR109254]
The following testcase is miscompiled on aarch64-linux in the regname pass, because while the function takes arguments in the p0 register, FUNCTION_ARG_REGNO_P doesn't reflect that, so DF doesn't know the register is used in register passing. It sees 2 chains with p1 register and wants to replace the second one and as DF doesn't know p0 is live at the start of the function, it will happily use p0 register even when it is used in subsequent instructions. The following patch fixes that. FUNCTION_ARG_REGNO_P returns non-zero for p0-p3 (unconditionally, seems for the floating/vector registers it doesn't conditionalize them on TARGET_FLOAT either, but if you want, I can conditionalize p0-p3 on TARGET_SVE), similarly targetm.calls.function_value_regno_p returns true for p0-p3 registers if TARGET_SVE (again for consistency, that function conditionalizes the float/vector on TARGET_FLOAT). Now, that change broke bootstrap in libobjc and some __builtin_apply_args/__builtin_apply/__builtin_return tests. The aarch64_get_reg_raw_mode hook already documents that SVE scalable arg/return passing is fundamentally incompatible with those builtins, but unlike the floating/vector regs where it forces a fixed vector mode, I think there is no fixed mode which could be used for p0-p3. So, I have tweaked the generic code so that it uses VOIDmode return from that hook to signal that a register shouldn't be touched by __builtin_apply_args/__builtin_apply/__builtin_return despite being mentioned in FUNCTION_ARG_REGNO_P or targetm.calls.function_value_regno_p. gcc/ 2023-04-01 Jakub Jelinek <jakub@redhat.com> PR target/109254 * builtins.cc (apply_args_size): If targetm.calls.get_raw_arg_mode returns VOIDmode, handle it like if the register isn't used for passing arguments at all. (apply_result_size): If targetm.calls.get_raw_result_mode returns VOIDmode, handle it like if the register isn't used for returning results at all. * target.def (get_raw_result_mode, get_raw_arg_mode): Document what it means to return VOIDmode. * doc/tm.texi: Regenerated. * config/aarch64/aarch64.cc (aarch64_function_value_regno_p): Return TARGET_SVE for P0_REGNUM. (aarch64_function_arg_regno_p): Also return true for p0-p3. (aarch64_get_reg_raw_mode): Return VOIDmode for PR_REGNUM_P regs. gcc/testsuite/ 2023-04-01 Jakub Jelinek <jakub@redhat.com> Richard Sandiford <richard.sandiford@arm.com> PR target/109254 * gcc.target/aarch64/sve/pr109254.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/builtins.cc38
-rw-r--r--gcc/config/aarch64/aarch64.cc10
-rw-r--r--gcc/doc/tm.texi6
-rw-r--r--gcc/target.def6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr109254.c27
5 files changed, 65 insertions, 22 deletions
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index ed0efd5..1bfdc59 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -1446,18 +1446,19 @@ apply_args_size (void)
{
fixed_size_mode mode = targetm.calls.get_raw_arg_mode (regno);
- gcc_assert (mode != VOIDmode);
-
- align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
- if (size % align != 0)
- size = CEIL (size, align) * align;
- size += GET_MODE_SIZE (mode);
- apply_args_mode[regno] = mode;
+ if (mode != VOIDmode)
+ {
+ align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ if (size % align != 0)
+ size = CEIL (size, align) * align;
+ size += GET_MODE_SIZE (mode);
+ apply_args_mode[regno] = mode;
+ }
+ else
+ apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
}
else
- {
- apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
- }
+ apply_args_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
}
return size;
}
@@ -1481,13 +1482,16 @@ apply_result_size (void)
{
fixed_size_mode mode = targetm.calls.get_raw_result_mode (regno);
- gcc_assert (mode != VOIDmode);
-
- align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
- if (size % align != 0)
- size = CEIL (size, align) * align;
- size += GET_MODE_SIZE (mode);
- apply_result_mode[regno] = mode;
+ if (mode != VOIDmode)
+ {
+ align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ if (size % align != 0)
+ size = CEIL (size, align) * align;
+ size += GET_MODE_SIZE (mode);
+ apply_result_mode[regno] = mode;
+ }
+ else
+ apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
}
else
apply_result_mode[regno] = as_a <fixed_size_mode> (VOIDmode);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index cc119d0..42617ce 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -7388,6 +7388,9 @@ aarch64_function_value_regno_p (const unsigned int regno)
if (regno >= V0_REGNUM && regno < V0_REGNUM + HA_MAX_NUM_FLDS)
return TARGET_FLOAT;
+ if (regno >= P0_REGNUM && regno < P0_REGNUM + HA_MAX_NUM_FLDS)
+ return TARGET_SVE;
+
return false;
}
@@ -7959,7 +7962,8 @@ bool
aarch64_function_arg_regno_p (unsigned regno)
{
return ((GP_REGNUM_P (regno) && regno < R0_REGNUM + NUM_ARG_REGS)
- || (FP_REGNUM_P (regno) && regno < V0_REGNUM + NUM_FP_ARG_REGS));
+ || (FP_REGNUM_P (regno) && regno < V0_REGNUM + NUM_FP_ARG_REGS)
+ || (PR_REGNUM_P (regno) && regno < P0_REGNUM + NUM_PR_ARG_REGS));
}
/* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least
@@ -7995,6 +7999,10 @@ aarch64_get_reg_raw_mode (int regno)
for SVE types are fundamentally incompatible with the
__builtin_return/__builtin_apply interface. */
return as_a <fixed_size_mode> (V16QImode);
+ if (PR_REGNUM_P (regno))
+ /* For SVE PR regs, indicate that they should be ignored for
+ __builtin_apply/__builtin_return. */
+ return as_a <fixed_size_mode> (VOIDmode);
return default_get_reg_raw_mode (regno);
}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4bb48c5..a660e33 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4820,13 +4820,15 @@ nothing when you use @option{-freg-struct-return} mode.
@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_RESULT_MODE (int @var{regno})
This target hook returns the mode to be used when accessing raw return
registers in @code{__builtin_return}. Define this macro if the value
-in @var{reg_raw_mode} is not correct.
+in @var{reg_raw_mode} is not correct. Use @code{VOIDmode} if a register
+should be ignored for @code{__builtin_return} purposes.
@end deftypefn
@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_ARG_MODE (int @var{regno})
This target hook returns the mode to be used when accessing raw argument
registers in @code{__builtin_apply_args}. Define this macro if the value
-in @var{reg_raw_mode} is not correct.
+in @var{reg_raw_mode} is not correct. Use @code{VOIDmode} if a register
+should be ignored for @code{__builtin_apply_args} purposes.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_EMPTY_RECORD_P (const_tree @var{type})
diff --git a/gcc/target.def b/gcc/target.def
index 1b9c882..171bbd1 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5324,7 +5324,8 @@ DEFHOOK
(get_raw_result_mode,
"This target hook returns the mode to be used when accessing raw return\n\
registers in @code{__builtin_return}. Define this macro if the value\n\
-in @var{reg_raw_mode} is not correct.",
+in @var{reg_raw_mode} is not correct. Use @code{VOIDmode} if a register\n\
+should be ignored for @code{__builtin_return} purposes.",
fixed_size_mode, (int regno),
default_get_reg_raw_mode)
@@ -5334,7 +5335,8 @@ DEFHOOK
(get_raw_arg_mode,
"This target hook returns the mode to be used when accessing raw argument\n\
registers in @code{__builtin_apply_args}. Define this macro if the value\n\
-in @var{reg_raw_mode} is not correct.",
+in @var{reg_raw_mode} is not correct. Use @code{VOIDmode} if a register\n\
+should be ignored for @code{__builtin_apply_args} purposes.",
fixed_size_mode, (int regno),
default_get_reg_raw_mode)
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr109254.c b/gcc/testsuite/gcc.target/aarch64/sve/pr109254.c
new file mode 100644
index 0000000..2df28e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr109254.c
@@ -0,0 +1,27 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -funroll-loops" } */
+
+#include <arm_sve.h>
+
+svfloat32_t __attribute__((noipa))
+func_demo (svfloat32_t x, svfloat32_t y, svbool_t pg)
+{
+ svfloat32_t z = svadd_f32_x (pg, x, svdup_f32 (0x1.800fep19f));
+ svbool_t cmp = svcmplt_f32 (pg, z, svdup_f32 (0.0f));
+ svfloat32_t zM1 = svsub_f32_x (pg, z, svdup_n_f32 (1.0f));
+ z = svsel_f32 (cmp, zM1, z);
+ svfloat32_t sum = svadd_f32_x (pg, z, y);
+ return sum;
+}
+
+int
+main ()
+{
+ float arr[2];
+ svfloat32_t x = svinsr_n_f32 (svdup_f32 (-0x1.880fep19f), 2.0f);
+ svfloat32_t res = func_demo (x, svdup_f32 (0.5f), svptrue_b32 ());
+ svst1_f32 (svptrue_pat_b32 (SV_VL2), arr, res);
+ if (arr[0] != 786561.5f || arr[1] != -16384.5f)
+ __builtin_abort ();
+ return 0;
+}