Richard Sandiford <richard.sandif...@arm.com> writes: > This patch replaces get_call_reg_set_usage with call_insn_abi, > which returns the ABI of the target of a call insn. The ABI's > full_reg_clobbers corresponds to regs_invalidated_by_call, > whereas many callers instead passed call_used_or_fixed_regs, i.e.: > > (regs_invalidated_by_call | fixed_reg_set) > > The patch slavishly preserves the "| fixed_reg_set" for these callers; > later patches will clean this up.
On reflection, I think insn_callee_abi would be a better name for the function than call_insn_abi, since it should make it clearer that the function returns the ABI of the target function. In future we could have expr_callee_abi for CALL_EXPRs. Also, after Segher's comments for 10/32, I've used "callee_abi" as the name of temporary variables, instead of just "abi". I've made the same change for later patches (except where I've posted new versions instead), but it didn't seem worth spamming the lists with that. Tested as before. Richard PS. Ping for the series :-) 2019-09-25 Richard Sandiford <richard.sandif...@arm.com> gcc/ * target.def (insn_callee_abi): New hook. (remove_extra_call_preserved_regs): Delete. * doc/tm.texi.in (TARGET_INSN_CALLEE_ABI): New macro. (TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): Delete. * doc/tm.texi: Regenerate. * targhooks.h (default_remove_extra_call_preserved_regs): Delete. * targhooks.c (default_remove_extra_call_preserved_regs): Delete. * config/aarch64/aarch64.c (aarch64_simd_call_p): Constify the insn argument. (aarch64_remove_extra_call_preserved_regs): Delete. (aarch64_insn_callee_abi): New function. (TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): Delete. (TARGET_INSN_CALLEE_ABI): New macro. * rtl.h (get_call_fndecl): Declare. (cgraph_rtl_info): Fix formatting. Tweak comment for function_used_regs. Remove function_used_regs_valid. * rtlanal.c (get_call_fndecl): Moved from final.c * function-abi.h (insn_callee_abi): Declare. (target_function_abi_info): Mention insn_callee_abi. * function-abi.cc (fndecl_abi): Handle flag_ipa_ra in a similar way to get_call_reg_set_usage did. (insn_callee_abi): New function. * regs.h (get_call_reg_set_usage): Delete. * final.c: Include function-abi.h. (collect_fn_hard_reg_usage): Add fixed and stack registers to function_used_regs before the main loop rather than afterwards. Use insn_callee_abi instead of get_call_reg_set_usage. Exit early if function_used_regs ends up not being useful. (get_call_fndecl): Move to rtlanal.c (get_call_cgraph_rtl_info, get_call_reg_set_usage): Delete. * caller-save.c: Include function-abi.h. (setup_save_areas, save_call_clobbered_regs): Use insn_callee_abi instead of get_call_reg_set_usage. * cfgcleanup.c: Include function-abi.h. (old_insns_match_p): Use insn_callee_abi instead of get_call_reg_set_usage. * cgraph.h (cgraph_node::rtl_info): Take a const_tree instead of a tree. * cgraph.c (cgraph_node::rtl_info): Likewise. Initialize function_used_regs. * df-scan.c: Include function-abi.h. (df_get_call_refs): Use insn_callee_abi instead of get_call_reg_set_usage. * ira-lives.c: Include function-abi.h. (process_bb_node_lives): Use insn_callee_abi instead of get_call_reg_set_usage. * lra-lives.c: Include function-abi.h. (process_bb_lives): Use insn_callee_abi instead of get_call_reg_set_usage. * postreload.c: Include function-abi.h. (reload_combine): Use insn_callee_abi instead of get_call_reg_set_usage. * regcprop.c: Include function-abi.h. (copyprop_hardreg_forward_1): Use insn_callee_abi instead of get_call_reg_set_usage. * resource.c: Include function-abi.h. (mark_set_resources, mark_target_live_regs): Use insn_callee_abi instead of get_call_reg_set_usage. * var-tracking.c: Include function-abi.h. (dataflow_set_clear_at_call): Use insn_callee_abi instead of get_call_reg_set_usage. Index: gcc/target.def =================================================================== --- gcc/target.def 2019-09-25 16:23:04.000000000 +0100 +++ gcc/target.def 2019-09-25 16:23:05.092580444 +0100 @@ -4952,6 +4952,19 @@ interoperability between several ABIs in const predefined_function_abi &, (const_tree type), NULL) +DEFHOOK +(insn_callee_abi, + "This hook returns a description of the ABI used by the target of\n\ +call instruction @var{insn}; see the definition of\n\ +@code{predefined_function_abi} for details of the ABI descriptor.\n\ +Only the global function @code{insn_callee_abi} should call this hook\n\ +directly.\n\ +\n\ +Targets only need to define this hook if they support\n\ +interoperability between several ABIs in the same translation unit.", + const predefined_function_abi &, (const rtx_insn *insn), + NULL) + /* ??? Documenting this hook requires a GFDL license grant. */ DEFHOOK_UNDOC (internal_arg_pointer, @@ -5834,20 +5847,6 @@ DEFHOOK const char *, (void), hook_constcharptr_void_null) -DEFHOOK -(remove_extra_call_preserved_regs, - "This hook removes registers from the set of call-clobbered registers\n\ - in @var{used_regs} if, contrary to the default rules, something guarantees\n\ - that @samp{insn} preserves those registers. For example, some targets\n\ - support variant ABIs in which functions preserve more registers than\n\ - normal functions would. Removing those extra registers from @var{used_regs}\n\ - can lead to better register allocation.\n\ - \n\ - The default implementation does nothing, which is always safe.\n\ - Defining the hook is purely an optimization.", - void, (rtx_insn *insn, HARD_REG_SET *used_regs), - default_remove_extra_call_preserved_regs) - /* Return the smallest number of different values for which it is best to use a jump-table instead of a tree of conditional branches. */ DEFHOOK Index: gcc/doc/tm.texi.in =================================================================== --- gcc/doc/tm.texi.in 2019-09-25 16:23:04.000000000 +0100 +++ gcc/doc/tm.texi.in 2019-09-25 16:23:05.088580476 +0100 @@ -1711,13 +1711,13 @@ must be defined. Modern ports should de @cindex call-saved register @hook TARGET_FNTYPE_ABI +@hook TARGET_INSN_CALLEE_ABI + @cindex call-used register @cindex call-clobbered register @cindex call-saved register @hook TARGET_HARD_REGNO_CALL_PART_CLOBBERED -@hook TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS - @hook TARGET_RETURN_CALL_WITH_MAX_CLOBBERS @hook TARGET_GET_MULTILIB_ABI_NAME Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi 2019-09-25 16:23:04.000000000 +0100 +++ gcc/doc/tm.texi 2019-09-25 16:23:05.084580502 +0100 @@ -1905,6 +1905,17 @@ descriptor. Targets only need to define interoperability between several ABIs in the same translation unit. @end deftypefn +@deftypefn {Target Hook} {const predefined_function_abi &} TARGET_INSN_CALLEE_ABI (const rtx_insn *@var{insn}) +This hook returns a description of the ABI used by the target of +call instruction @var{insn}; see the definition of +@code{predefined_function_abi} for details of the ABI descriptor. +Only the global function @code{insn_callee_abi} should call this hook +directly. + +Targets only need to define this hook if they support +interoperability between several ABIs in the same translation unit. +@end deftypefn + @cindex call-used register @cindex call-clobbered register @cindex call-saved register @@ -1921,18 +1932,6 @@ The default implementation returns false for targets that don't have partly call-clobbered registers. @end deftypefn -@deftypefn {Target Hook} void TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS (rtx_insn *@var{insn}, HARD_REG_SET *@var{used_regs}) -This hook removes registers from the set of call-clobbered registers - in @var{used_regs} if, contrary to the default rules, something guarantees - that @samp{insn} preserves those registers. For example, some targets - support variant ABIs in which functions preserve more registers than - normal functions would. Removing those extra registers from @var{used_regs} - can lead to better register allocation. - - The default implementation does nothing, which is always safe. - Defining the hook is purely an optimization. -@end deftypefn - @deftypefn {Target Hook} {rtx_insn *} TARGET_RETURN_CALL_WITH_MAX_CLOBBERS (rtx_insn *@var{call_1}, rtx_insn *@var{call_2}) This hook returns a pointer to the call that partially clobbers the most registers. If a platform supports multiple ABIs where the registers Index: gcc/targhooks.h =================================================================== --- gcc/targhooks.h 2019-09-25 16:23:04.000000000 +0100 +++ gcc/targhooks.h 2019-09-25 16:23:05.092580444 +0100 @@ -281,7 +281,5 @@ extern tree default_preferred_else_value extern bool default_have_speculation_safe_value (bool); extern bool speculation_safe_value_not_needed (bool); extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx); -extern void default_remove_extra_call_preserved_regs (rtx_insn *, - HARD_REG_SET *); #endif /* GCC_TARGHOOKS_H */ Index: gcc/targhooks.c =================================================================== --- gcc/targhooks.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/targhooks.c 2019-09-25 16:23:05.092580444 +0100 @@ -2363,9 +2363,4 @@ default_speculation_safe_value (machine_ return result; } -void -default_remove_extra_call_preserved_regs (rtx_insn *, HARD_REG_SET *) -{ -} - #include "gt-targhooks.h" Index: gcc/config/aarch64/aarch64.c =================================================================== --- gcc/config/aarch64/aarch64.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/config/aarch64/aarch64.c 2019-09-25 16:23:05.080580530 +0100 @@ -1877,7 +1877,7 @@ aarch64_reg_save_mode (tree fndecl, unsi the function. */ static bool -aarch64_simd_call_p (rtx_insn *insn) +aarch64_simd_call_p (const rtx_insn *insn) { rtx symbol; rtx call; @@ -1895,20 +1895,14 @@ aarch64_simd_call_p (rtx_insn *insn) return aarch64_simd_decl_p (fndecl); } -/* Implement TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS. If INSN calls - a function that uses the SIMD ABI, take advantage of the extra - call-preserved registers that the ABI provides. */ +/* Implement TARGET_INSN_CALLEE_ABI. */ -void -aarch64_remove_extra_call_preserved_regs (rtx_insn *insn, - HARD_REG_SET *return_set) +const predefined_function_abi & +aarch64_insn_callee_abi (const rtx_insn *insn) { if (aarch64_simd_call_p (insn)) - { - for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (FP_SIMD_SAVED_REGNUM_P (regno)) - CLEAR_HARD_REG_BIT (*return_set, regno); - } + return aarch64_simd_abi (); + return default_function_abi; } /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. The callee only saves @@ -20924,9 +20918,8 @@ #define TARGET_MODES_TIEABLE_P aarch64_m #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ aarch64_hard_regno_call_part_clobbered -#undef TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS -#define TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS \ - aarch64_remove_extra_call_preserved_regs +#undef TARGET_INSN_CALLEE_ABI +#define TARGET_INSN_CALLEE_ABI aarch64_insn_callee_abi #undef TARGET_RETURN_CALL_WITH_MAX_CLOBBERS #define TARGET_RETURN_CALL_WITH_MAX_CLOBBERS \ Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2019-09-25 16:23:04.000000000 +0100 +++ gcc/rtl.h 2019-09-25 16:23:05.092580444 +0100 @@ -3438,6 +3438,7 @@ extern int rtx_unstable_p (const_rtx); extern bool rtx_varies_p (const_rtx, bool); extern bool rtx_addr_varies_p (const_rtx, bool); extern rtx get_call_rtx_from (const rtx_insn *); +extern tree get_call_fndecl (const rtx_insn *); extern HOST_WIDE_INT get_integer_term (const_rtx); extern rtx get_related_value (const_rtx); extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT); @@ -4389,14 +4390,11 @@ extern tree GTY(()) global_regs_decl[FIR Available only for functions that has been already assembled. */ struct GTY(()) cgraph_rtl_info { - unsigned int preferred_incoming_stack_boundary; + unsigned int preferred_incoming_stack_boundary; - /* Call unsaved hard registers really used by the corresponding - function (including ones used by functions called by the - function). */ + /* Which registers the function clobbers, either directly or by + calling another function. */ HARD_REG_SET function_used_regs; - /* Set if function_used_regs is valid. */ - unsigned function_used_regs_valid: 1; }; /* If loads from memories of mode MODE always sign or zero extend, Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/rtlanal.c 2019-09-25 16:23:05.092580444 +0100 @@ -822,6 +822,24 @@ get_call_rtx_from (const rtx_insn *insn) return x; return NULL_RTX; } + +/* Get the declaration of the function called by INSN. */ + +tree +get_call_fndecl (const rtx_insn *insn) +{ + rtx note, datum; + + note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX); + if (note == NULL_RTX) + return NULL_TREE; + + datum = XEXP (note, 0); + if (datum != NULL_RTX) + return SYMBOL_REF_DECL (datum); + + return NULL_TREE; +} /* Return the value of the integer term in X, if one is apparent; otherwise return 0. Index: gcc/function-abi.h =================================================================== --- gcc/function-abi.h 2019-09-25 16:23:04.000000000 +0100 +++ gcc/function-abi.h 2019-09-25 16:23:05.088580476 +0100 @@ -224,6 +224,8 @@ struct target_function_abi_info * crtl->abi is the ABI of the function that we are currently compiling to rtl. + * insn_callee_abi (INSN) is the ABI used by the target of call insn INSN. + * eh_edge_abi is the "ABI" used when taking an EH edge from an exception-throwing statement to an exception handler. Catching exceptions from calls can be treated as an abnormal return from @@ -265,5 +267,6 @@ #define eh_edge_abi default_function_abi extern const predefined_function_abi &fntype_abi (const_tree); extern function_abi fndecl_abi (const_tree); +extern function_abi insn_callee_abi (const rtx_insn *); #endif Index: gcc/function-abi.cc =================================================================== --- gcc/function-abi.cc 2019-09-25 16:23:04.000000000 +0100 +++ gcc/function-abi.cc 2019-09-25 16:23:05.088580476 +0100 @@ -143,5 +143,28 @@ function_abi fndecl_abi (const_tree fndecl) { gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL); - return fntype_abi (TREE_TYPE (fndecl)); + const predefined_function_abi &base_abi = fntype_abi (TREE_TYPE (fndecl)); + + if (flag_ipa_ra && decl_binds_to_current_def_p (fndecl)) + if (cgraph_rtl_info *info = cgraph_node::rtl_info (fndecl)) + return function_abi (base_abi, info->function_used_regs); + + return base_abi; +} + +/* Return the ABI of the function called by INSN. */ + +function_abi +insn_callee_abi (const rtx_insn *insn) +{ + gcc_assert (insn && CALL_P (insn)); + + if (flag_ipa_ra) + if (tree fndecl = get_call_fndecl (insn)) + return fndecl_abi (fndecl); + + if (targetm.calls.insn_callee_abi) + return targetm.calls.insn_callee_abi (insn); + + return default_function_abi; } Index: gcc/regs.h =================================================================== --- gcc/regs.h 2019-09-25 16:23:04.000000000 +0100 +++ gcc/regs.h 2019-09-25 16:23:05.088580476 +0100 @@ -383,8 +383,4 @@ range_in_hard_reg_set_p (const_hard_reg_ return true; } -/* Get registers used by given function call instruction. */ -extern bool get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set, - HARD_REG_SET default_set); - #endif /* GCC_REGS_H */ Index: gcc/final.c =================================================================== --- gcc/final.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/final.c 2019-09-25 16:23:05.088580476 +0100 @@ -81,6 +81,7 @@ #define INCLUDE_ALGORITHM /* reverse */ #include "asan.h" #include "rtl-iter.h" #include "print-rtl.h" +#include "function-abi.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -230,7 +231,6 @@ static int alter_cond (rtx); #endif static int align_fuzz (rtx, rtx, int, unsigned); static void collect_fn_hard_reg_usage (void); -static tree get_call_fndecl (rtx_insn *); /* Initialize data in final at the beginning of a compilation. */ @@ -4994,7 +4994,16 @@ collect_fn_hard_reg_usage (void) if (!targetm.call_fusage_contains_non_callee_clobbers) return; - CLEAR_HARD_REG_SET (function_used_regs); + /* Be conservative - mark fixed and global registers as used. */ + function_used_regs = fixed_reg_set; + +#ifdef STACK_REGS + /* Handle STACK_REGS conservatively, since the df-framework does not + provide accurate information for them. */ + + for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) + SET_HARD_REG_BIT (function_used_regs, i); +#endif for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn)) { @@ -5005,96 +5014,23 @@ collect_fn_hard_reg_usage (void) if (CALL_P (insn) && !self_recursive_call_p (insn)) - { - if (!get_call_reg_set_usage (insn, &insn_used_regs, - call_used_or_fixed_regs)) - return; - - function_used_regs |= insn_used_regs; - } + function_used_regs + |= insn_callee_abi (insn).full_and_partial_reg_clobbers (); find_all_hard_reg_sets (insn, &insn_used_regs, false); function_used_regs |= insn_used_regs; - } - /* Be conservative - mark fixed and global registers as used. */ - function_used_regs |= fixed_reg_set; - -#ifdef STACK_REGS - /* Handle STACK_REGS conservatively, since the df-framework does not - provide accurate information for them. */ - - for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) - SET_HARD_REG_BIT (function_used_regs, i); -#endif + if (hard_reg_set_subset_p (crtl->abi->full_and_partial_reg_clobbers (), + function_used_regs)) + return; + } - /* The information we have gathered is only interesting if it exposes a - register from the call_used_regs that is not used in this function. */ - if (hard_reg_set_subset_p (call_used_or_fixed_regs, function_used_regs)) - return; + /* Mask out fully-saved registers, so that they don't affect equality + comparisons between function_abis. */ + function_used_regs &= crtl->abi->full_and_partial_reg_clobbers (); node = cgraph_node::rtl_info (current_function_decl); gcc_assert (node != NULL); node->function_used_regs = function_used_regs; - node->function_used_regs_valid = 1; -} - -/* Get the declaration of the function called by INSN. */ - -static tree -get_call_fndecl (rtx_insn *insn) -{ - rtx note, datum; - - note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX); - if (note == NULL_RTX) - return NULL_TREE; - - datum = XEXP (note, 0); - if (datum != NULL_RTX) - return SYMBOL_REF_DECL (datum); - - return NULL_TREE; -} - -/* Return the cgraph_rtl_info of the function called by INSN. Returns NULL for - call targets that can be overwritten. */ - -static struct cgraph_rtl_info * -get_call_cgraph_rtl_info (rtx_insn *insn) -{ - tree fndecl; - - if (insn == NULL_RTX) - return NULL; - - fndecl = get_call_fndecl (insn); - if (fndecl == NULL_TREE - || !decl_binds_to_current_def_p (fndecl)) - return NULL; - - return cgraph_node::rtl_info (fndecl); -} - -/* Find hard registers used by function call instruction INSN, and return them - in REG_SET. Return DEFAULT_SET in REG_SET if not found. */ - -bool -get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set, - HARD_REG_SET default_set) -{ - if (flag_ipa_ra) - { - struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn); - if (node != NULL - && node->function_used_regs_valid) - { - *reg_set = node->function_used_regs & default_set; - return true; - } - } - *reg_set = default_set; - targetm.remove_extra_call_preserved_regs (insn, reg_set); - return false; } Index: gcc/caller-save.c =================================================================== --- gcc/caller-save.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/caller-save.c 2019-09-25 16:23:05.072580590 +0100 @@ -37,6 +37,7 @@ Software Foundation; either version 3, o #include "dumpfile.h" #include "rtl-iter.h" #include "target.h" +#include "function-abi.h" #define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD) @@ -426,7 +427,9 @@ setup_save_areas (void) freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); REG_SET_TO_HARD_REG_SET (hard_regs_to_save, &chain->live_throughout); - get_call_reg_set_usage (insn, &used_regs, call_used_or_fixed_regs); + used_regs = insn_callee_abi (insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not be needed. */ + used_regs |= fixed_reg_set; /* Record all registers set in this call insn. These don't need to be saved. N.B. the call insn might set a subreg @@ -509,7 +512,10 @@ setup_save_areas (void) REG_SET_TO_HARD_REG_SET (hard_regs_to_save, &chain->live_throughout); - get_call_reg_set_usage (insn, &used_regs, call_used_or_fixed_regs); + used_regs = insn_callee_abi (insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not + be needed. */ + used_regs |= fixed_reg_set; /* Record all registers set in this call insn. These don't need to be saved. N.B. the call insn might set a subreg @@ -838,8 +844,10 @@ save_call_clobbered_regs (void) | this_insn_sets | hard_regs_saved); hard_regs_to_save &= savable_regs; - get_call_reg_set_usage (insn, &call_def_reg_set, - call_used_or_fixed_regs); + call_def_reg_set = insn_callee_abi (insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not + be needed. */ + call_def_reg_set |= fixed_reg_set; hard_regs_to_save &= call_def_reg_set; for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) Index: gcc/cfgcleanup.c =================================================================== --- gcc/cfgcleanup.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/cfgcleanup.c 2019-09-25 16:23:05.076580558 +0100 @@ -54,6 +54,7 @@ Software Foundation; either version 3, o #include "dbgcnt.h" #include "rtl-iter.h" #include "regs.h" +#include "function-abi.h" #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) @@ -1226,10 +1227,11 @@ old_insns_match_p (int mode ATTRIBUTE_UN } } - HARD_REG_SET i1_used, i2_used; - - get_call_reg_set_usage (i1, &i1_used, call_used_or_fixed_regs); - get_call_reg_set_usage (i2, &i2_used, call_used_or_fixed_regs); + HARD_REG_SET i1_used = insn_callee_abi (i1).full_reg_clobbers (); + HARD_REG_SET i2_used = insn_callee_abi (i2).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not be needed. */ + i1_used |= fixed_reg_set; + i2_used |= fixed_reg_set; if (i1_used != i2_used) return dir_none; Index: gcc/cgraph.h =================================================================== --- gcc/cgraph.h 2019-09-25 16:23:04.000000000 +0100 +++ gcc/cgraph.h 2019-09-25 16:23:05.076580558 +0100 @@ -1379,7 +1379,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cg static cgraph_local_info *local_info (tree decl); /* Return local info for the compiled function. */ - static struct cgraph_rtl_info *rtl_info (tree); + static struct cgraph_rtl_info *rtl_info (const_tree); /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. Return NULL if there's no such node. */ Index: gcc/cgraph.c =================================================================== --- gcc/cgraph.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/cgraph.c 2019-09-25 16:23:05.076580558 +0100 @@ -1839,7 +1839,7 @@ cgraph_node::local_info (tree decl) /* Return local info for the compiled function. */ cgraph_rtl_info * -cgraph_node::rtl_info (tree decl) +cgraph_node::rtl_info (const_tree decl) { gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); cgraph_node *node = get (decl); @@ -1854,7 +1854,10 @@ cgraph_node::rtl_info (tree decl) return NULL; /* Allocate if it doesn't exist. */ if (node->rtl == NULL) - node->rtl = ggc_cleared_alloc<cgraph_rtl_info> (); + { + node->rtl = ggc_cleared_alloc<cgraph_rtl_info> (); + node->rtl->function_used_regs = reg_class_contents[ALL_REGS]; + } return node->rtl; } Index: gcc/df-scan.c =================================================================== --- gcc/df-scan.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/df-scan.c 2019-09-25 16:23:05.080580530 +0100 @@ -35,7 +35,7 @@ Software Foundation; either version 3, o #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ #include "dumpfile.h" #include "calls.h" - +#include "function-abi.h" /* The set of hard registers in eliminables[i].from. */ @@ -3088,13 +3088,11 @@ df_get_call_refs (class df_collection_re bool is_sibling_call; unsigned int i; HARD_REG_SET defs_generated; - HARD_REG_SET fn_reg_set_usage; CLEAR_HARD_REG_SET (defs_generated); df_find_hard_reg_defs (PATTERN (insn_info->insn), &defs_generated); is_sibling_call = SIBLING_CALL_P (insn_info->insn); - get_call_reg_set_usage (insn_info->insn, &fn_reg_set_usage, - regs_invalidated_by_call); + function_abi callee_abi = insn_callee_abi (insn_info->insn); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { @@ -3118,7 +3116,7 @@ df_get_call_refs (class df_collection_re NULL, bb, insn_info, DF_REF_REG_DEF, flags); } } - else if (TEST_HARD_REG_BIT (fn_reg_set_usage, i) + else if (callee_abi.clobbers_full_reg_p (i) /* no clobbers for regs that are the result of the call */ && !TEST_HARD_REG_BIT (defs_generated, i) && (!is_sibling_call Index: gcc/ira-lives.c =================================================================== --- gcc/ira-lives.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/ira-lives.c 2019-09-25 16:23:05.088580476 +0100 @@ -33,6 +33,7 @@ Software Foundation; either version 3, o #include "ira.h" #include "ira-int.h" #include "sparseset.h" +#include "function-abi.h" /* The code in this file is similar to one in global but the code works on the allocno basis and creates live ranges instead of @@ -1254,10 +1255,11 @@ process_bb_node_lives (ira_loop_tree_nod ira_object_t obj = ira_object_id_map[i]; a = OBJECT_ALLOCNO (obj); int num = ALLOCNO_NUM (a); - HARD_REG_SET this_call_used_reg_set; - - get_call_reg_set_usage (insn, &this_call_used_reg_set, - call_used_or_fixed_regs); + HARD_REG_SET this_call_used_reg_set + = insn_callee_abi (insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not be + needed. */ + this_call_used_reg_set |= fixed_reg_set; /* Don't allocate allocnos that cross setjmps or any call, if this function receives a nonlocal Index: gcc/lra-lives.c =================================================================== --- gcc/lra-lives.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/lra-lives.c 2019-09-25 16:23:05.088580476 +0100 @@ -43,6 +43,7 @@ Software Foundation; either version 3, o #include "sparseset.h" #include "lra-int.h" #include "target.h" +#include "function-abi.h" /* Program points are enumerated by numbers from range 0..LRA_LIVE_MAX_POINT-1. There are approximately two times more @@ -931,9 +932,11 @@ process_bb_lives (basic_block bb, int &c last_call_used_reg_set = call_used_or_fixed_regs; else { - HARD_REG_SET this_call_used_reg_set; - get_call_reg_set_usage (curr_insn, &this_call_used_reg_set, - call_used_or_fixed_regs); + HARD_REG_SET this_call_used_reg_set + = insn_callee_abi (curr_insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not + be needed. */ + this_call_used_reg_set |= fixed_reg_set; bool flush = (! hard_reg_set_empty_p (last_call_used_reg_set) && (last_call_used_reg_set Index: gcc/postreload.c =================================================================== --- gcc/postreload.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/postreload.c 2019-09-25 16:23:05.088580476 +0100 @@ -40,6 +40,7 @@ Software Foundation; either version 3, o #include "cselib.h" #include "tree-pass.h" #include "dbgcnt.h" +#include "function-abi.h" static int reload_cse_noop_set_p (rtx); static bool reload_cse_simplify (rtx_insn *, rtx); @@ -1330,9 +1331,10 @@ reload_combine (void) if (CALL_P (insn)) { rtx link; - HARD_REG_SET used_regs; - - get_call_reg_set_usage (insn, &used_regs, call_used_or_fixed_regs); + HARD_REG_SET used_regs = insn_callee_abi (insn).full_reg_clobbers (); + /* ??? This preserves traditional behavior; it might not be + needed. */ + used_regs |= fixed_reg_set; for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) if (TEST_HARD_REG_BIT (used_regs, r)) Index: gcc/regcprop.c =================================================================== --- gcc/regcprop.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/regcprop.c 2019-09-25 16:23:05.088580476 +0100 @@ -35,6 +35,7 @@ #include "rtl-iter.h" #include "cfgrtl.h" #include "target.h" +#include "function-abi.h" /* The following code does forward propagation of hard register copies. The object is to eliminate as many dependencies as possible, so that @@ -1035,7 +1036,6 @@ copyprop_hardreg_forward_1 (basic_block unsigned int set_nregs = 0; unsigned int regno; rtx exp; - HARD_REG_SET regs_invalidated_by_this_call; for (exp = CALL_INSN_FUNCTION_USAGE (insn); exp; exp = XEXP (exp, 1)) { @@ -1053,11 +1053,9 @@ copyprop_hardreg_forward_1 (basic_block } } - get_call_reg_set_usage (insn, - ®s_invalidated_by_this_call, - regs_invalidated_by_call); + function_abi callee_abi = insn_callee_abi (insn); for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if ((TEST_HARD_REG_BIT (regs_invalidated_by_this_call, regno) + if ((callee_abi.clobbers_full_reg_p (regno) || (targetm.hard_regno_call_part_clobbered (insn, regno, vd->e[regno].mode))) && (regno < set_regno || regno >= set_regno + set_nregs)) Index: gcc/resource.c =================================================================== --- gcc/resource.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/resource.c 2019-09-25 16:23:05.088580476 +0100 @@ -30,6 +30,7 @@ Software Foundation; either version 3, o #include "resource.h" #include "insn-attr.h" #include "params.h" +#include "function-abi.h" /* This structure is used to record liveness information at the targets or fallthrough insns of branches. We will most likely need the information @@ -662,12 +663,10 @@ mark_set_resources (rtx x, struct resour { rtx_call_insn *call_insn = as_a <rtx_call_insn *> (x); rtx link; - HARD_REG_SET regs; res->cc = res->memory = 1; - get_call_reg_set_usage (call_insn, ®s, regs_invalidated_by_call); - res->regs |= regs; + res->regs |= insn_callee_abi (call_insn).full_reg_clobbers (); for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1)) @@ -1038,10 +1037,8 @@ mark_target_live_regs (rtx_insn *insns, predicated instruction, or if the CALL is NORETURN. */ if (GET_CODE (PATTERN (real_insn)) != COND_EXEC) { - HARD_REG_SET regs_invalidated_by_this_call; - get_call_reg_set_usage (real_insn, - ®s_invalidated_by_this_call, - regs_invalidated_by_call); + HARD_REG_SET regs_invalidated_by_this_call + = insn_callee_abi (real_insn).full_reg_clobbers (); /* CALL clobbers all call-used regs that aren't fixed except sp, ap, and fp. Do this before setting the result of the call live. */ Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c 2019-09-25 16:23:04.000000000 +0100 +++ gcc/var-tracking.c 2019-09-25 16:23:05.092580444 +0100 @@ -116,6 +116,7 @@ #include "rtl-iter.h" #include "fibonacci_heap.h" #include "print-rtl.h" +#include "function-abi.h" typedef fibonacci_heap <long, basic_block_def> bb_heap_t; typedef fibonacci_node <long, basic_block_def> bb_heap_node_t; @@ -4900,12 +4901,10 @@ dataflow_set_clear_at_call (dataflow_set { unsigned int r; hard_reg_set_iterator hrsi; - HARD_REG_SET invalidated_regs; - get_call_reg_set_usage (call_insn, &invalidated_regs, - regs_invalidated_by_call); + function_abi callee_abi = insn_callee_abi (call_insn); - EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi) + EXECUTE_IF_SET_IN_HARD_REG_SET (callee_abi.full_reg_clobbers (), 0, r, hrsi) var_regno_delete (set, r); if (MAY_HAVE_DEBUG_BIND_INSNS)