64 lines
2.3 KiB
Diff
64 lines
2.3 KiB
Diff
|
From 6787268a289bdbc32920b13b4697eaf756f9f7e0 Mon Sep 17 00:00:00 2001
|
||
|
From: Richard Sandiford <richard.sandiford@arm.com>
|
||
|
Date: Thu, 31 Aug 2023 16:15:10 +0100
|
||
|
Subject: [PATCH] aarch64: Fix return register handling in untyped_call
|
||
|
To: gcc-patches@gcc.gnu.org
|
||
|
|
||
|
While working on another patch, I hit a problem with the aarch64
|
||
|
expansion of untyped_call. The expander emits the usual:
|
||
|
|
||
|
(set (mem ...) (reg resN))
|
||
|
|
||
|
instructions to store the result registers to memory, but it didn't
|
||
|
say in RTL where those resN results came from. This eventually led
|
||
|
to a failure of gcc.dg/torture/stackalign/builtin-return-2.c,
|
||
|
via regrename.
|
||
|
|
||
|
This patch turns the untyped call from a plain call to a call_value,
|
||
|
to represent that the call returns (or might return) a useful value.
|
||
|
The patch also uses a PARALLEL return rtx to represent all the possible
|
||
|
return registers.
|
||
|
|
||
|
gcc/
|
||
|
* config/aarch64/aarch64.md (untyped_call): Emit a call_value
|
||
|
rather than a call. List each possible destination register
|
||
|
in the call pattern.
|
||
|
---
|
||
|
gcc/config/aarch64/aarch64.md | 20 +++++++++++++++++++-
|
||
|
1 file changed, 19 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
|
||
|
index 90f9ee658c5..97d27677985 100644
|
||
|
--- a/gcc/config/aarch64/aarch64.md
|
||
|
+++ b/gcc/config/aarch64/aarch64.md
|
||
|
@@ -934,7 +934,25 @@
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
- emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
|
||
|
+ /* Generate a PARALLEL that contains all of the register results.
|
||
|
+ The offsets are somewhat arbitrary, since we don't know the
|
||
|
+ actual return type. The main thing we need to avoid is having
|
||
|
+ overlapping byte ranges, since those might give the impression
|
||
|
+ that two registers are known to have data in common. */
|
||
|
+ rtvec rets = rtvec_alloc (XVECLEN (operands[2], 0));
|
||
|
+ unsigned HOST_WIDE_INT offset = 0;
|
||
|
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
||
|
+ {
|
||
|
+ rtx reg = SET_SRC (XVECEXP (operands[2], 0, i));
|
||
|
+ gcc_assert (REG_P (reg));
|
||
|
+ rtx offset_rtx = gen_int_mode (offset, Pmode);
|
||
|
+ rtx piece = gen_rtx_EXPR_LIST (VOIDmode, reg, offset_rtx);
|
||
|
+ RTVEC_ELT (rets, i) = piece;
|
||
|
+ offset += GET_MODE_SIZE (GET_MODE (reg));
|
||
|
+ }
|
||
|
+ rtx ret = gen_rtx_PARALLEL (VOIDmode, rets);
|
||
|
+
|
||
|
+ emit_call_insn (gen_call_value (ret, operands[0], const0_rtx, NULL));
|
||
|
|
||
|
for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
||
|
{
|
||
|
--
|
||
|
2.35.3
|
||
|
|