Make -fzero-call-used-regs work on the SPARC
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 1 Dec 2020 20:12:54 +0000 (21:12 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Tue, 1 Dec 2020 20:15:53 +0000 (21:15 +0100)
This contains both a generic fixlet for targets implementing the leaf
register optimization (SPARC and Xtensa) and the implementation of the
target hook TARGET_ZERO_CALL_USED_REGS which is needed to make this work
on the SPARC.

gcc/ChangeLog:
* function.c (gen_call_used_regs_seq): In a function subject to the
leaf register optimization, skip registers that are not present.
* config/sparc/sparc.c (TARGET_ZERO_CALL_USED_REGS): Define to...
(sparc_zero_call_used_regs): ...this.  New function.

gcc/config/sparc/sparc.c
gcc/function.c

index 02138c5d4788cf891ac3d2973dc852b206614e99..ec0921b7ef51c614534ae9a5ae72ce3ae0160288 100644 (file)
@@ -708,6 +708,7 @@ static HOST_WIDE_INT sparc_constant_alignment (const_tree, HOST_WIDE_INT);
 static bool sparc_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
                                            const vec_perm_indices &);
 static bool sparc_can_follow_jump (const rtx_insn *, const rtx_insn *);
+static HARD_REG_SET sparc_zero_call_used_regs (HARD_REG_SET);
 \f
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
@@ -959,6 +960,9 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_CAN_FOLLOW_JUMP
 #define TARGET_CAN_FOLLOW_JUMP sparc_can_follow_jump
 
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS sparc_zero_call_used_regs
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return the memory reference contained in X if any, zero otherwise.  */
@@ -13810,4 +13814,50 @@ sparc_constant_alignment (const_tree exp, HOST_WIDE_INT align)
   return align;
 }
 
+/* Implement TARGET_ZERO_CALL_USED_REGS.
+
+   Generate a sequence of instructions that zero registers specified by
+   NEED_ZEROED_HARDREGS.  Return the ZEROED_HARDREGS that are actually
+   zeroed.  */
+
+static HARD_REG_SET
+sparc_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+      {
+       /* Do not touch the CC registers or the FP registers if no VIS.  */
+       if (regno >= SPARC_FCC_REG
+           || (regno >= SPARC_FIRST_FP_REG && !TARGET_VIS))
+         CLEAR_HARD_REG_BIT (need_zeroed_hardregs, regno);
+
+       /* Do not access the odd upper FP registers individually.  */
+       else if (regno >= SPARC_FIRST_V9_FP_REG && (regno & 1))
+         ;
+
+       /* Use the most natural mode for the registers, which is not given by
+          regno_reg_rtx/reg_raw_mode for the FP registers on the SPARC.  */
+       else
+         {
+           machine_mode mode;
+           rtx reg;
+
+           if (regno < SPARC_FIRST_FP_REG)
+             {
+               reg = regno_reg_rtx[regno];
+               mode = GET_MODE (reg);
+             }
+           else
+             {
+               mode = regno < SPARC_FIRST_V9_FP_REG ? SFmode : DFmode;
+               reg = gen_raw_REG (mode, regno);
+             }
+
+           emit_move_insn (reg, CONST0_RTX (mode));
+         }
+      }
+
+  return need_zeroed_hardregs;
+}
+
 #include "gt-sparc.h"
index 004fa389207b366e01920b108cab78c1d7609179..59fd72b0e820de69625fd493726bb9542ac100a0 100644 (file)
@@ -5880,6 +5880,10 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
        continue;
       if (only_arg && !FUNCTION_ARG_REGNO_P (regno))
        continue;
+#ifdef LEAF_REG_REMAP
+      if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
+       continue;
+#endif
 
       /* Now this is a register that we might want to zero.  */
       SET_HARD_REG_BIT (selected_hardregs, regno);