From b3147c02dc772ad77eb7e1d5d6e14a8f222d1e65 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 1 Dec 2020 21:12:54 +0100 Subject: [PATCH] Make -fzero-call-used-regs work on the SPARC 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 | 50 ++++++++++++++++++++++++++++++++++++++++ gcc/function.c | 4 ++++ 2 files changed, 54 insertions(+) diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 02138c5d478..ec0921b7ef5 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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); #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" diff --git a/gcc/function.c b/gcc/function.c index 004fa389207..59fd72b0e82 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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); -- 2.30.2