xtensa: Make register A0 allocable for the CALL0 ABI
authorTakayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
Fri, 21 Oct 2022 22:46:13 +0000 (07:46 +0900)
committerMax Filippov <jcmvbkbc@gmail.com>
Sat, 22 Oct 2022 07:23:02 +0000 (00:23 -0700)
This patch offers an additional allocable register by RA for the CALL0
ABI.

> Register a0 holds the return address upon entry to a function, but
> unlike the windowed register ABI, it is not reserved for this purpose
> and may hold other values after the return address has been saved.
  - Xtensa ISA Reference Manual,
                   8.1.2 "CALL0 Register Usage and Stack Layout" [p.589]

gcc/ChangeLog:

* config/xtensa/xtensa.cc (xtensa_conditional_register_usage):
Remove register A0 from FIXED_REGS if the CALL0 ABI.
(xtensa_expand_epilogue): Change to emit '(use (reg:SI A0_REG))'
unconditionally after restoring callee-saved registers for
sibling-call functions, in order to prevent misleading that
register A0 is free to use.

gcc/config/xtensa/xtensa.cc

index 950eb5a..94a98c2 100644 (file)
@@ -3471,15 +3471,14 @@ xtensa_expand_epilogue (bool sibcall_p)
          if (xtensa_call_save_reg(regno))
            {
              rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
-             rtx reg;
 
              offset -= UNITS_PER_WORD;
-             emit_move_insn (reg = gen_rtx_REG (SImode, regno),
+             emit_move_insn (gen_rtx_REG (SImode, regno),
                              gen_frame_mem (SImode, x));
-             if (regno == A0_REG && sibcall_p)
-               emit_use (reg);
            }
        }
+      if (sibcall_p)
+       emit_use (gen_rtx_REG (SImode, A0_REG));
 
       if (cfun->machine->current_frame_size > 0)
        {
@@ -4970,6 +4969,13 @@ xtensa_conditional_register_usage (void)
   /* Remove hard FP register from the preferred reload registers set.  */
   CLEAR_HARD_REG_BIT (reg_class_contents[(int)RL_REGS],
                      HARD_FRAME_POINTER_REGNUM);
+
+  /* Register A0 holds the return address upon entry to a function
+     for the CALL0 ABI, but unlike the windowed register ABI, it is
+     not reserved for this purpose and may hold other values after
+     the return address has been saved.  */
+  if (!TARGET_WINDOWED_ABI)
+    fixed_regs[A0_REG] = 0;
 }
 
 /* Map hard register number to register class */