From: Richard Sandiford Date: Mon, 30 Sep 2019 16:19:59 +0000 (+0000) Subject: Pass an ABI identifier to hard_regno_call_part_clobbered X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6ee2cc70024253d2670a4a317158b2a65251a1d1;p=gcc.git Pass an ABI identifier to hard_regno_call_part_clobbered This patch replaces the rtx_insn argument to targetm.hard_regno_call_part_clobbered with an ABI identifier, since call insns are now just one possible way of getting an ABI handle. This in turn allows predefined_function_abi::initialize to do the right thing for non-default ABIs. The horrible ?: in need_for_call_save_p goes away in a later patch, with the series as a whole removing most direct calls to the hook in favour of function_abi operations. 2019-09-30 Richard Sandiford gcc/ * target.def (hard_regno_call_part_clobbered): Take an ABI identifier instead of an rtx_insn. * doc/tm.texi: Regenerate. * hooks.h (hook_bool_insn_uint_mode_false): Delete. (hook_bool_uint_uint_mode_false): New function. * hooks.c (hook_bool_insn_uint_mode_false): Delete. (hook_bool_uint_uint_mode_false): New function. * config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered): Take an ABI identifier instead of an rtx_insn. * config/avr/avr.c (avr_hard_regno_call_part_clobbered): Likewise. * config/i386/i386.c (ix86_hard_regno_call_part_clobbered): Likewise. * config/mips/mips.c (mips_hard_regno_call_part_clobbered): Likewise. * config/pru/pru.c (pru_hard_regno_call_part_clobbered): Likewise. * config/rs6000/rs6000.c (rs6000_hard_regno_call_part_clobbered): Likewise. * config/s390/s390.c (s390_hard_regno_call_part_clobbered): Likewise. * cselib.c: Include function-abi.h. (cselib_process_insn): Update call to targetm.hard_regno_call_part_clobbered, using insn_callee_abi to get the appropriate ABI identifier. * function-abi.cc (predefined_function_abi::initialize): Update call to targetm.hard_regno_call_part_clobbered. * ira-conflicts.c (ira_build_conflicts): Likewise. * ira-costs.c (ira_tune_allocno_costs): Likewise. * lra-constraints.c: Include function-abi.h. (need_for_call_save_p): Update call to targetm.hard_regno_call_part_clobbered, using insn_callee_abi to get the appropriate ABI identifier. * lra-lives.c (check_pseudos_live_through_calls): Likewise. * regcprop.c (copyprop_hardreg_forward_1): Update call to targetm.hard_regno_call_part_clobbered. * reginfo.c (choose_hard_reg_mode): Likewise. * regrename.c (check_new_reg_p): Likewise. * reload.c (find_equiv_reg): Likewise. * reload1.c (emit_reload_insns): Likewise. * sched-deps.c: Include function-abi.h. (deps_analyze_insn): Update call to targetm.hard_regno_call_part_clobbered, using insn_callee_abi to get the appropriate ABI identifier. * sel-sched.c (init_regs_for_mode, mark_unavailable_hard_regs): Update call to targetm.hard_regno_call_part_clobbered. * targhooks.c (default_dwarf_frame_reg_mode): Likewise. From-SVN: r276311 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index acdcd914dc2..59bfeb2b66f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,48 @@ +2019-09-30 Richard Sandiford + + * target.def (hard_regno_call_part_clobbered): Take an ABI + identifier instead of an rtx_insn. + * doc/tm.texi: Regenerate. + * hooks.h (hook_bool_insn_uint_mode_false): Delete. + (hook_bool_uint_uint_mode_false): New function. + * hooks.c (hook_bool_insn_uint_mode_false): Delete. + (hook_bool_uint_uint_mode_false): New function. + * config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered): + Take an ABI identifier instead of an rtx_insn. + * config/avr/avr.c (avr_hard_regno_call_part_clobbered): Likewise. + * config/i386/i386.c (ix86_hard_regno_call_part_clobbered): Likewise. + * config/mips/mips.c (mips_hard_regno_call_part_clobbered): Likewise. + * config/pru/pru.c (pru_hard_regno_call_part_clobbered): Likewise. + * config/rs6000/rs6000.c (rs6000_hard_regno_call_part_clobbered): + Likewise. + * config/s390/s390.c (s390_hard_regno_call_part_clobbered): Likewise. + * cselib.c: Include function-abi.h. + (cselib_process_insn): Update call to + targetm.hard_regno_call_part_clobbered, using insn_callee_abi + to get the appropriate ABI identifier. + * function-abi.cc (predefined_function_abi::initialize): Update call + to targetm.hard_regno_call_part_clobbered. + * ira-conflicts.c (ira_build_conflicts): Likewise. + * ira-costs.c (ira_tune_allocno_costs): Likewise. + * lra-constraints.c: Include function-abi.h. + (need_for_call_save_p): Update call to + targetm.hard_regno_call_part_clobbered, using insn_callee_abi + to get the appropriate ABI identifier. + * lra-lives.c (check_pseudos_live_through_calls): Likewise. + * regcprop.c (copyprop_hardreg_forward_1): Update call + to targetm.hard_regno_call_part_clobbered. + * reginfo.c (choose_hard_reg_mode): Likewise. + * regrename.c (check_new_reg_p): Likewise. + * reload.c (find_equiv_reg): Likewise. + * reload1.c (emit_reload_insns): Likewise. + * sched-deps.c: Include function-abi.h. + (deps_analyze_insn): Update call to + targetm.hard_regno_call_part_clobbered, using insn_callee_abi + to get the appropriate ABI identifier. + * sel-sched.c (init_regs_for_mode, mark_unavailable_hard_regs): Update + call to targetm.hard_regno_call_part_clobbered. + * targhooks.c (default_dwarf_frame_reg_mode): Likewise. + 2019-09-30 Richard Sandiford * config/i386/i386.c: Include function-abi.h. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 71cdce3033c..ca4c183d89d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1910,12 +1910,13 @@ aarch64_insn_callee_abi (const rtx_insn *insn) clobbers the top 64 bits when restoring the bottom 64 bits. */ static bool -aarch64_hard_regno_call_part_clobbered (rtx_insn *insn, unsigned int regno, +aarch64_hard_regno_call_part_clobbered (unsigned int abi_id, + unsigned int regno, machine_mode mode) { if (FP_REGNUM_P (regno)) { - bool simd_p = insn && CALL_P (insn) && aarch64_simd_call_p (insn); + bool simd_p = (abi_id == ARM_PCS_SIMD); poly_int64 per_register_size = GET_MODE_SIZE (mode); unsigned int nregs = hard_regno_nregs (regno, mode); if (nregs > 1) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 04fc00f4a55..3ccff8ebedc 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -12164,8 +12164,8 @@ avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode) /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */ static bool -avr_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned regno, machine_mode mode) +avr_hard_regno_call_part_clobbered (unsigned, unsigned regno, + machine_mode mode) { /* FIXME: This hook gets called with MODE:REGNO combinations that don't represent valid hard registers like, e.g. HI:29. Returning TRUE diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a13aef8077a..8af4bc581e1 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -18794,8 +18794,8 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) the low 16 bytes are saved. */ static bool -ix86_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned int regno, machine_mode mode) +ix86_hard_regno_call_part_clobbered (unsigned int, unsigned int regno, + machine_mode mode) { return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16; } diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index c682ebd5add..91dd94bf4e6 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -12928,8 +12928,8 @@ mips_hard_regno_scratch_ok (unsigned int regno) registers with MODE > 64 bits are part clobbered too. */ static bool -mips_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned int regno, machine_mode mode) +mips_hard_regno_call_part_clobbered (unsigned int, unsigned int regno, + machine_mode mode) { if (TARGET_FLOATXX && hard_regno_nregs (regno, mode) == 1 diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c index 416399ea5fd..16d1451262e 100644 --- a/gcc/config/pru/pru.c +++ b/gcc/config/pru/pru.c @@ -559,8 +559,8 @@ pru_hard_regno_scratch_ok (unsigned int regno) /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */ static bool -pru_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned regno, machine_mode mode) +pru_hard_regno_call_part_clobbered (unsigned, unsigned regno, + machine_mode mode) { HARD_REG_SET caller_saved_set; HARD_REG_SET callee_saved_set; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d6e1fea8426..330e2490301 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1946,8 +1946,8 @@ rs6000_modes_tieable_p (machine_mode mode1, machine_mode mode2) /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */ static bool -rs6000_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned int regno, machine_mode mode) +rs6000_hard_regno_call_part_clobbered (unsigned int, unsigned int regno, + machine_mode mode) { if (TARGET_32BIT && TARGET_POWERPC64 diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index cfdfa4e141d..1764c3450e6 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -10297,8 +10297,8 @@ s390_hard_regno_scratch_ok (unsigned int regno) bytes are saved across calls, however. */ static bool -s390_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED, - unsigned int regno, machine_mode mode) +s390_hard_regno_call_part_clobbered (unsigned int, unsigned int regno, + machine_mode mode) { if (!TARGET_64BIT && TARGET_ZARCH diff --git a/gcc/cselib.c b/gcc/cselib.c index 109cc27959c..5de14a07317 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "cselib.h" #include "params.h" +#include "function-abi.h" /* A list of cselib_val structures. */ struct elt_list @@ -2765,11 +2766,13 @@ cselib_process_insn (rtx_insn *insn) memory. */ if (CALL_P (insn)) { + function_abi callee_abi = insn_callee_abi (insn); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (call_used_or_fixed_reg_p (i) || (REG_VALUES (i) && REG_VALUES (i)->elt && (targetm.hard_regno_call_part_clobbered - (insn, i, GET_MODE (REG_VALUES (i)->elt->val_rtx))))) + (callee_abi.id (), i, + GET_MODE (REG_VALUES (i)->elt->val_rtx))))) cselib_invalidate_regno (i, reg_raw_mode[i]); /* Since it is not clear how cselib is going to be used, be diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 33997a5c7a0..419c706cb9e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1919,14 +1919,23 @@ interoperability between several ABIs in the same translation unit. @cindex call-used register @cindex call-clobbered register @cindex call-saved register -@deftypefn {Target Hook} bool TARGET_HARD_REGNO_CALL_PART_CLOBBERED (rtx_insn *@var{insn}, unsigned int @var{regno}, machine_mode @var{mode}) -This hook should return true if @var{regno} is partly call-saved and -partly call-clobbered, and if a value of mode @var{mode} would be partly -clobbered by call instruction @var{insn}. If @var{insn} is NULL then it -should return true if any call could partly clobber the register. -For example, if the low 32 bits of @var{regno} are preserved across a call -but higher bits are clobbered, this hook should return true for a 64-bit -mode but false for a 32-bit mode. +@deftypefn {Target Hook} bool TARGET_HARD_REGNO_CALL_PART_CLOBBERED (unsigned int @var{abi_id}, unsigned int @var{regno}, machine_mode @var{mode}) +ABIs usually specify that calls must preserve the full contents +of a particular register, or that calls can alter any part of a +particular register. This information is captured by the target macro +@code{CALL_REALLY_USED_REGISTERS}. However, some ABIs specify that calls +must preserve certain bits of a particular register but can alter others. +This hook should return true if this applies to at least one of the +registers in @samp{(reg:@var{mode} @var{regno})}, and if as a result the +call would alter part of the @var{mode} value. For example, if a call +preserves the low 32 bits of a 64-bit hard register @var{regno} but can +clobber the upper 32 bits, this hook should return true for a 64-bit mode +but false for a 32-bit mode. + +The value of @var{abi_id} comes from the @code{predefined_function_abi} +structure that describes the ABI of the call; see the definition of the +structure for more details. If (as is usual) the target uses the same ABI +for all functions in a translation unit, @var{abi_id} is always 0. The default implementation returns false, which is correct for targets that don't have partly call-clobbered registers. diff --git a/gcc/function-abi.cc b/gcc/function-abi.cc index e2c35b6a274..1d1ac9a2589 100644 --- a/gcc/function-abi.cc +++ b/gcc/function-abi.cc @@ -50,7 +50,7 @@ predefined_function_abi::initialize (unsigned int id, If the ABI specifies that part of a hard register R is call-clobbered, we should be able to find a single-register mode M for which - targetm.hard_regno_call_part_clobbered (NULL, R, M) is true. + targetm.hard_regno_call_part_clobbered (m_id, R, M) is true. In other words, it shouldn't be the case that R can hold all single-register modes across a call, but can't hold part of a multi-register mode. @@ -66,7 +66,7 @@ predefined_function_abi::initialize (unsigned int id, for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) if (targetm.hard_regno_mode_ok (regno, mode) && hard_regno_nregs (regno, mode) == 1 - && targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + && targetm.hard_regno_call_part_clobbered (m_id, regno, mode)) SET_HARD_REG_BIT (m_full_and_partial_reg_clobbers, regno); } @@ -89,7 +89,7 @@ predefined_function_abi::initialize (unsigned int id, for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) if (targetm.hard_regno_mode_ok (regno, mode) && !overlaps_hard_reg_set_p (m_full_reg_clobbers, mode, regno) - && !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + && !targetm.hard_regno_call_part_clobbered (m_id, regno, mode)) remove_from_hard_reg_set (&m_mode_clobbers[i], mode, regno); } @@ -104,7 +104,7 @@ predefined_function_abi::initialize (unsigned int id, for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) if (targetm.hard_regno_mode_ok (regno, mode) && !overlaps_hard_reg_set_p (m_full_reg_clobbers, mode, regno) - && targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + && targetm.hard_regno_call_part_clobbered (m_id, regno, mode)) gcc_assert (overlaps_hard_reg_set_p (all_clobbers, mode, regno) && overlaps_hard_reg_set_p (m_mode_clobbers[i], mode, regno)); diff --git a/gcc/hooks.c b/gcc/hooks.c index ca731c440e7..a9a87de3cdb 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -140,9 +140,8 @@ hook_bool_puint64_puint64_true (poly_uint64, poly_uint64) return true; } -/* Generic hook that takes (unsigned int, machine_mode) and returns false. */ bool -hook_bool_insn_uint_mode_false (rtx_insn *, unsigned int, machine_mode) +hook_bool_uint_uint_mode_false (unsigned int, unsigned int, machine_mode) { return false; } diff --git a/gcc/hooks.h b/gcc/hooks.h index 040eff008db..7cfe91d12df 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -40,7 +40,7 @@ extern bool hook_bool_const_rtx_insn_const_rtx_insn_true (const rtx_insn *, extern bool hook_bool_mode_uhwi_false (machine_mode, unsigned HOST_WIDE_INT); extern bool hook_bool_puint64_puint64_true (poly_uint64, poly_uint64); -extern bool hook_bool_insn_uint_mode_false (rtx_insn *, unsigned int, +extern bool hook_bool_uint_uint_mode_false (unsigned int, unsigned int, machine_mode); extern bool hook_bool_uint_mode_true (unsigned int, machine_mode); extern bool hook_bool_tree_false (tree); diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index c199309e7a6..6ceed533329 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -838,7 +838,7 @@ ira_build_conflicts (void) regs must conflict with them. */ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (!TEST_HARD_REG_BIT (call_used_or_fixed_regs, regno) - && targetm.hard_regno_call_part_clobbered (NULL, regno, + && targetm.hard_regno_call_part_clobbered (0, regno, obj_mode)) { SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno); diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index aefec08da54..2e7e10ac903 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -2381,7 +2381,7 @@ ira_tune_allocno_costs (void) *crossed_calls_clobber_regs) && (ira_hard_reg_set_intersection_p (regno, mode, call_used_or_fixed_regs) - || targetm.hard_regno_call_part_clobbered (NULL, regno, + || targetm.hard_regno_call_part_clobbered (0, regno, mode))) cost += (ALLOCNO_CALL_FREQ (a) * (ira_memory_move_cost[mode][rclass][0] diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index a60bc6cc3f9..43fe1074788 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -131,6 +131,7 @@ #include "lra.h" #include "lra-int.h" #include "print-rtl.h" +#include "function-abi.h" /* Value of LRA_CURR_RELOAD_NUM at the beginning of BB of the current insn. Remember that LRA_CURR_RELOAD_NUM is the number of emitted @@ -5442,7 +5443,8 @@ need_for_call_save_p (int regno) : call_used_or_fixed_regs, PSEUDO_REGNO_MODE (regno), reg_renumber[regno]) || (targetm.hard_regno_call_part_clobbered - (lra_reg_info[regno].call_insn, + (lra_reg_info[regno].call_insn + ? insn_callee_abi (lra_reg_info[regno].call_insn).id () : 0, reg_renumber[regno], PSEUDO_REGNO_MODE (regno))))); } diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index b84d6461c4c..40e9f66f3b1 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -594,7 +594,7 @@ check_pseudos_live_through_calls (int regno, if (! sparseset_bit_p (pseudos_live_through_calls, regno)) return; - gcc_assert (call_insn && CALL_P (call_insn)); + function_abi callee_abi = insn_callee_abi (call_insn); old_call_insn = lra_reg_info[regno].call_insn; if (!old_call_insn || (targetm.return_call_with_max_clobbers @@ -606,7 +606,7 @@ check_pseudos_live_through_calls (int regno, lra_reg_info[regno].conflict_hard_regs |= last_call_used_reg_set; for (hr = 0; HARD_REGISTER_NUM_P (hr); hr++) - if (targetm.hard_regno_call_part_clobbered (call_insn, hr, + if (targetm.hard_regno_call_part_clobbered (callee_abi.id (), hr, PSEUDO_REGNO_MODE (regno))) add_to_hard_reg_set (&lra_reg_info[regno].conflict_hard_regs, PSEUDO_REGNO_MODE (regno), hr); diff --git a/gcc/regcprop.c b/gcc/regcprop.c index 4879063ea69..0bdd6b91815 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -1057,7 +1057,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if ((callee_abi.clobbers_full_reg_p (regno) || (targetm.hard_regno_call_part_clobbered - (insn, regno, vd->e[regno].mode))) + (callee_abi.id (), regno, vd->e[regno].mode))) && (regno < set_regno || regno >= set_regno + set_nregs)) kill_value_regno (regno, 1, vd); diff --git a/gcc/reginfo.c b/gcc/reginfo.c index a3fbbe67c52..f084c0e4306 100644 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c @@ -568,7 +568,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, if (hard_regno_nregs (regno, mode) == nregs && targetm.hard_regno_mode_ok (regno, mode) && (!call_saved - || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + || !targetm.hard_regno_call_part_clobbered (0, regno, mode)) && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode))) found_mode = mode; @@ -576,7 +576,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, if (hard_regno_nregs (regno, mode) == nregs && targetm.hard_regno_mode_ok (regno, mode) && (!call_saved - || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + || !targetm.hard_regno_call_part_clobbered (0, regno, mode)) && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode))) found_mode = mode; @@ -584,7 +584,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, if (hard_regno_nregs (regno, mode) == nregs && targetm.hard_regno_mode_ok (regno, mode) && (!call_saved - || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + || !targetm.hard_regno_call_part_clobbered (0, regno, mode)) && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode))) found_mode = mode; @@ -592,7 +592,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, if (hard_regno_nregs (regno, mode) == nregs && targetm.hard_regno_mode_ok (regno, mode) && (!call_saved - || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + || !targetm.hard_regno_call_part_clobbered (0, regno, mode)) && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode))) found_mode = mode; @@ -606,7 +606,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED, if (hard_regno_nregs (regno, mode) == nregs && targetm.hard_regno_mode_ok (regno, mode) && (!call_saved - || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))) + || !targetm.hard_regno_call_part_clobbered (0, regno, mode))) return mode; } diff --git a/gcc/regrename.c b/gcc/regrename.c index 14ce95470b2..6a2442bdaa7 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -339,9 +339,9 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg, && ! DEBUG_INSN_P (tmp->insn)) || (this_head->need_caller_save_reg && ! (targetm.hard_regno_call_part_clobbered - (NULL, reg, GET_MODE (*tmp->loc))) + (0, reg, GET_MODE (*tmp->loc))) && (targetm.hard_regno_call_part_clobbered - (NULL, new_reg, GET_MODE (*tmp->loc))))) + (0, new_reg, GET_MODE (*tmp->loc))))) return false; return true; diff --git a/gcc/reload.c b/gcc/reload.c index 7731e0fcf57..b7601307f82 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -6912,14 +6912,14 @@ find_equiv_reg (rtx goal, rtx_insn *insn, enum reg_class rclass, int other, if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) for (i = 0; i < nregs; ++i) if (call_used_or_fixed_reg_p (regno + i) - || targetm.hard_regno_call_part_clobbered (NULL, regno + i, + || targetm.hard_regno_call_part_clobbered (0, regno + i, mode)) return 0; if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER) for (i = 0; i < valuenregs; ++i) if (call_used_or_fixed_reg_p (valueno + i) - || targetm.hard_regno_call_part_clobbered (NULL, valueno + i, + || targetm.hard_regno_call_part_clobbered (0, valueno + i, mode)) return 0; } diff --git a/gcc/reload1.c b/gcc/reload1.c index c619c541174..39dff6a32b2 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -8193,8 +8193,7 @@ emit_reload_insns (class insn_chain *chain) : out_regno + k); reg_reloaded_insn[regno + k] = insn; SET_HARD_REG_BIT (reg_reloaded_valid, regno + k); - if (targetm.hard_regno_call_part_clobbered (NULL, - regno + k, + if (targetm.hard_regno_call_part_clobbered (0, regno + k, mode)) SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + k); @@ -8274,8 +8273,7 @@ emit_reload_insns (class insn_chain *chain) : in_regno + k); reg_reloaded_insn[regno + k] = insn; SET_HARD_REG_BIT (reg_reloaded_valid, regno + k); - if (targetm.hard_regno_call_part_clobbered (NULL, - regno + k, + if (targetm.hard_regno_call_part_clobbered (0, regno + k, mode)) SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + k); @@ -8391,7 +8389,7 @@ emit_reload_insns (class insn_chain *chain) CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + k); SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + k); if (targetm.hard_regno_call_part_clobbered - (NULL, src_regno + k, mode)) + (0, src_regno + k, mode)) SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, src_regno + k); else diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 52db3cc1523..87d0791374e 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "sched-int.h" #include "params.h" #include "cselib.h" +#include "function-abi.h" #ifdef INSN_SCHEDULING @@ -3723,6 +3724,7 @@ deps_analyze_insn (class deps_desc *deps, rtx_insn *insn) } else { + function_abi callee_abi = insn_callee_abi (insn); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) /* A call may read and modify global register variables. */ if (global_regs[i]) @@ -3734,8 +3736,8 @@ deps_analyze_insn (class deps_desc *deps, rtx_insn *insn) Since we only have a choice between 'might be clobbered' and 'definitely not clobbered', we must include all partly call-clobbered registers here. */ - else if (targetm.hard_regno_call_part_clobbered (insn, i, - reg_raw_mode[i]) + else if (targetm.hard_regno_call_part_clobbered + (callee_abi.id (), i, reg_raw_mode[i]) || TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) SET_REGNO_REG_SET (reg_pending_clobbers, i); /* We don't know what set of fixed registers might be used diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c index 077845e156a..bf370b5a5d8 100644 --- a/gcc/sel-sched.c +++ b/gcc/sel-sched.c @@ -1102,7 +1102,7 @@ init_regs_for_mode (machine_mode mode) if (i >= 0) continue; - if (targetm.hard_regno_call_part_clobbered (NULL, cur_reg, mode)) + if (targetm.hard_regno_call_part_clobbered (0, cur_reg, mode)) SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode], cur_reg); @@ -1247,7 +1247,7 @@ mark_unavailable_hard_regs (def_t def, struct reg_rename *reg_rename_p, /* Exclude registers that are partially call clobbered. */ if (def->crosses_call - && !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)) + && !targetm.hard_regno_call_part_clobbered (0, regno, mode)) reg_rename_p->available_for_renaming &= ~sel_hrd.regs_for_call_clobbered[mode]; diff --git a/gcc/target.def b/gcc/target.def index adf7a96e419..3bdbb8d86ba 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5814,18 +5814,27 @@ The default version of this hook always returns @code{true}.", DEFHOOK (hard_regno_call_part_clobbered, - "This hook should return true if @var{regno} is partly call-saved and\n\ -partly call-clobbered, and if a value of mode @var{mode} would be partly\n\ -clobbered by call instruction @var{insn}. If @var{insn} is NULL then it\n\ -should return true if any call could partly clobber the register.\n\ -For example, if the low 32 bits of @var{regno} are preserved across a call\n\ -but higher bits are clobbered, this hook should return true for a 64-bit\n\ -mode but false for a 32-bit mode.\n\ + "ABIs usually specify that calls must preserve the full contents\n\ +of a particular register, or that calls can alter any part of a\n\ +particular register. This information is captured by the target macro\n\ +@code{CALL_REALLY_USED_REGISTERS}. However, some ABIs specify that calls\n\ +must preserve certain bits of a particular register but can alter others.\n\ +This hook should return true if this applies to at least one of the\n\ +registers in @samp{(reg:@var{mode} @var{regno})}, and if as a result the\n\ +call would alter part of the @var{mode} value. For example, if a call\n\ +preserves the low 32 bits of a 64-bit hard register @var{regno} but can\n\ +clobber the upper 32 bits, this hook should return true for a 64-bit mode\n\ +but false for a 32-bit mode.\n\ +\n\ +The value of @var{abi_id} comes from the @code{predefined_function_abi}\n\ +structure that describes the ABI of the call; see the definition of the\n\ +structure for more details. If (as is usual) the target uses the same ABI\n\ +for all functions in a translation unit, @var{abi_id} is always 0.\n\ \n\ The default implementation returns false, which is correct\n\ for targets that don't have partly call-clobbered registers.", - bool, (rtx_insn *insn, unsigned int regno, machine_mode mode), - hook_bool_insn_uint_mode_false) + bool, (unsigned int abi_id, unsigned int regno, machine_mode mode), + hook_bool_uint_uint_mode_false) DEFHOOK (return_call_with_max_clobbers, diff --git a/gcc/targhooks.c b/gcc/targhooks.c index d2e3ff662b6..6105137aad5 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1928,7 +1928,7 @@ default_dwarf_frame_reg_mode (int regno) { machine_mode save_mode = reg_raw_mode[regno]; - if (targetm.hard_regno_call_part_clobbered (NULL, regno, save_mode)) + if (targetm.hard_regno_call_part_clobbered (0, regno, save_mode)) save_mode = choose_hard_reg_mode (regno, 1, true); return save_mode; }