The SVE patches change the size of a machine_mode from a compile-time
constant to a runtime invariant.  However, target-specific code can
continue to treat the modes as constant-sized if the target only has
constant-sized modes.

The main snag with this approach is that target-independent code still
uses macros from the target .h file.  This patch is one of several that
converts a target macro to a hook.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by checking that there were no extra warnings or changes in
testsuite assembly output for at least one target per CPU.  OK to install?

Richard


2017-08-28  Richard Sandiford  <richard.sandif...@linaro.org>
            Alan Hayward  <alan.hayw...@arm.com>
            David Sherwood  <david.sherw...@arm.com>

gcc/
        * target.def (hard_regno_call_part_clobbered): New hook.
        * doc/tm.texi.in (HARD_REGNO_CALL_PART_CLOBBERED): Replace with...
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): ...this hook.
        * doc/tm.texi: Regenerate.
        * hooks.h (hook_bool_uint_mode_false): Declare.
        * hooks.c (hook_bool_uint_mode_false): New function.
        * regs.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * cselib.c (cselib_process_insn): Use
        targetm.hard_regno_call_part_clobbered instead of
        HARD_REGNO_CALL_PART_CLOBBERED.
        * ira-conflicts.c (ira_build_conflicts): Likewise.
        * ira-costs.c (ira_tune_allocno_costs): Likewise.
        * lra-constraints.c (need_for_call_save_p): Likewise.
        * lra-lives.c: Include target.h.
        (check_pseudos_live_through_calls): Use
        targetm.hard_regno_call_part_clobbered instead of
        HARD_REGNO_CALL_PART_CLOBBERED.
        * regcprop.c: Include target.h.
        (copyprop_hardreg_forward_1): Use
        targetm.hard_regno_call_part_clobbered instead of
        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 (deps_analyze_insn): Likewise.
        * sel-sched.c (init_regs_for_mode): Likewise.
        (mark_unavailable_hard_regs): Likewise.
        * targhooks.c (default_dwarf_frame_reg_mode): Likewise.
        * config/aarch64/aarch64.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered):
        New function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/avr/avr.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/avr/avr-protos.h (avr_hard_regno_call_part_clobbered):
        Delete.
        * config/avr/avr.c (avr_hard_regno_call_part_clobbered): Make static
        and return a bool.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/i386/i386.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/i386/i386.c (ix86_hard_regno_call_part_clobbered): New
        function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/mips/mips.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/mips/mips.c (mips_hard_regno_call_part_clobbered): New
        function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/powerpcspe/powerpcspe.h (HARD_REGNO_CALL_PART_CLOBBERED):
        Delete.
        * config/powerpcspe/powerpcspe.c
        (rs6000_hard_regno_call_part_clobbered): New function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/rs6000/rs6000.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/rs6000/rs6000.c (rs6000_hard_regno_call_part_clobbered):
        New function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/s390/s390.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * config/s390/s390.c (s390_hard_regno_call_part_clobbered): New
        function.
        (TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
        * config/sh/sh.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
        * system.h (HARD_REGNO_CALL_PART_CLOBBERED): Poison.

Index: gcc/target.def
===================================================================
--- gcc/target.def      2017-08-28 09:36:09.610827107 +0100
+++ gcc/target.def      2017-08-28 09:36:10.075827140 +0100
@@ -5395,6 +5395,19 @@ The default version of this hook always
  bool, (unsigned int regno),
  default_hard_regno_scratch_ok)
 
+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 a call.  For example, if the low 32 bits of @var{regno} are\n\
+preserved across a call but higher bits are clobbered, this hook should\n\
+return true for a 64-bit mode but false for a 32-bit mode.\n\
+\n\
+The default implementation returns false, which is correct\n\
+for targets that don't have partly call-clobbered registers.",
+ bool, (unsigned int regno, machine_mode mode),
+ hook_bool_uint_mode_false)
+
 /* 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  2017-08-28 09:36:09.610827107 +0100
+++ gcc/doc/tm.texi.in  2017-08-28 09:36:10.070827139 +0100
@@ -1698,16 +1698,10 @@ This macro is optional.  If not specifie
 of @code{CALL_USED_REGISTERS}.
 @end defmac
 
-@defmac HARD_REGNO_CALL_PART_CLOBBERED (@var{regno}, @var{mode})
 @cindex call-used register
 @cindex call-clobbered register
 @cindex call-saved register
-A C expression that is nonzero if it is not permissible to store a
-value of mode @var{mode} in hard register number @var{regno} across a
-call without some part of it being clobbered.  For most machines this
-macro need not be defined.  It is only required for machines that do not
-preserve the entire contents of a register across a call.
-@end defmac
+@hook TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 
 @findex fixed_regs
 @findex call_used_regs
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     2017-08-28 09:36:09.610827107 +0100
+++ gcc/doc/tm.texi     2017-08-28 09:36:10.069827139 +0100
@@ -1869,16 +1869,19 @@ This macro is optional.  If not specifie
 of @code{CALL_USED_REGISTERS}.
 @end defmac
 
-@defmac HARD_REGNO_CALL_PART_CLOBBERED (@var{regno}, @var{mode})
 @cindex call-used register
 @cindex call-clobbered register
 @cindex call-saved register
-A C expression that is nonzero if it is not permissible to store a
-value of mode @var{mode} in hard register number @var{regno} across a
-call without some part of it being clobbered.  For most machines this
-macro need not be defined.  It is only required for machines that do not
-preserve the entire contents of a register across a call.
-@end defmac
+@deftypefn {Target Hook} bool TARGET_HARD_REGNO_CALL_PART_CLOBBERED (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 a call.  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.
+
+The default implementation returns false, which is correct
+for targets that don't have partly call-clobbered registers.
+@end deftypefn
 
 @findex fixed_regs
 @findex call_used_regs
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h 2017-08-28 09:36:09.610827107 +0100
+++ gcc/hooks.h 2017-08-28 09:36:10.070827139 +0100
@@ -38,6 +38,7 @@ extern bool hook_bool_const_rtx_insn_con
                                                          const rtx_insn *);
 extern bool hook_bool_mode_uhwi_false (machine_mode,
                                       unsigned HOST_WIDE_INT);
+extern bool hook_bool_uint_mode_false (unsigned int, machine_mode);
 extern bool hook_bool_tree_false (tree);
 extern bool hook_bool_const_tree_false (const_tree);
 extern bool hook_bool_tree_true (tree);
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c 2017-08-28 09:36:09.610827107 +0100
+++ gcc/hooks.c 2017-08-28 09:36:10.070827139 +0100
@@ -126,6 +126,13 @@ hook_bool_mode_uhwi_false (machine_mode,
   return false;
 }
 
+/* Generic hook that takes (unsigned int, machine_mode) and returns false.  */
+bool
+hook_bool_uint_mode_false (unsigned int, machine_mode)
+{
+  return false;
+}
+
 /* Generic hook that takes (FILE *, const char *) and does nothing.  */
 void
 hook_void_FILEptr_constcharptr (FILE *, const char *)
Index: gcc/regs.h
===================================================================
--- gcc/regs.h  2017-08-28 09:36:09.610827107 +0100
+++ gcc/regs.h  2017-08-28 09:36:10.072827140 +0100
@@ -193,12 +193,6 @@ #define HARD_REGNO_CALLER_SAVE_MODE(REGN
   choose_hard_reg_mode (REGNO, NREGS, false)
 #endif
 
-/* Registers that get partially clobbered by a call in a given mode.
-   These must not be call used registers.  */
-#ifndef HARD_REGNO_CALL_PART_CLOBBERED
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
-#endif
-
 /* Target-dependent globals.  */
 struct target_regs {
   /* For each starting hard register, the number of consecutive hard
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c        2017-08-28 09:36:09.610827107 +0100
+++ gcc/cselib.c        2017-08-28 09:36:10.068827139 +0100
@@ -2660,8 +2660,8 @@ cselib_process_insn (rtx_insn *insn)
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (call_used_regs[i]
            || (REG_VALUES (i) && REG_VALUES (i)->elt
-               && HARD_REGNO_CALL_PART_CLOBBERED (i,
-                     GET_MODE (REG_VALUES (i)->elt->val_rtx))))
+               && (targetm.hard_regno_call_part_clobbered
+                   (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
Index: gcc/ira-conflicts.c
===================================================================
--- gcc/ira-conflicts.c 2017-08-28 09:36:09.610827107 +0100
+++ gcc/ira-conflicts.c 2017-08-28 09:36:10.070827139 +0100
@@ -743,6 +743,7 @@ ira_build_conflicts (void)
       for (i = 0; i < n; i++)
        {
          ira_object_t obj = ALLOCNO_OBJECT (a, i);
+         machine_mode obj_mode = obj->allocno->mode;
          rtx allocno_reg = regno_reg_rtx [ALLOCNO_REGNO (a)];
 
          if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
@@ -804,8 +805,8 @@ ira_build_conflicts (void)
                 regs must conflict with them.  */
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (!TEST_HARD_REG_BIT (call_used_reg_set, regno)
-                   && HARD_REGNO_CALL_PART_CLOBBERED (regno,
-                                                      obj->allocno->mode))
+                   && targetm.hard_regno_call_part_clobbered (regno,
+                                                              obj_mode))
                  {
                    SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno);
                    SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c     2017-08-28 09:36:09.610827107 +0100
+++ gcc/ira-costs.c     2017-08-28 09:36:10.071827140 +0100
@@ -2341,7 +2341,8 @@ ira_tune_allocno_costs (void)
                                                   *crossed_calls_clobber_regs)
                  && (ira_hard_reg_set_intersection_p (regno, mode,
                                                       call_used_reg_set)
-                     || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+                     || targetm.hard_regno_call_part_clobbered (regno,
+                                                                mode)))
                cost += (ALLOCNO_CALL_FREQ (a)
                         * (ira_memory_move_cost[mode][rclass][0]
                            + ira_memory_move_cost[mode][rclass][1]));
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c       2017-08-28 09:36:09.610827107 +0100
+++ gcc/lra-constraints.c       2017-08-28 09:36:10.071827140 +0100
@@ -5287,8 +5287,8 @@ need_for_call_save_p (int regno)
               ? lra_reg_info[regno].actual_call_used_reg_set
               : call_used_reg_set,
               PSEUDO_REGNO_MODE (regno), reg_renumber[regno])
-             || HARD_REGNO_CALL_PART_CLOBBERED (reg_renumber[regno],
-                                                PSEUDO_REGNO_MODE (regno))));
+             || (targetm.hard_regno_call_part_clobbered
+                 (reg_renumber[regno], PSEUDO_REGNO_MODE (regno)))));
 }
 
 /* Global registers occurring in the current EBB.  */
Index: gcc/lra-lives.c
===================================================================
--- gcc/lra-lives.c     2017-08-28 09:36:09.610827107 +0100
+++ gcc/lra-lives.c     2017-08-28 09:36:10.072827140 +0100
@@ -42,6 +42,7 @@ Software Foundation; either version 3, o
 #include "cfganal.h"
 #include "sparseset.h"
 #include "lra-int.h"
+#include "target.h"
 
 /* Program points are enumerated by numbers from range
    0..LRA_LIVE_MAX_POINT-1.  There are approximately two times more
@@ -575,7 +576,8 @@ check_pseudos_live_through_calls (int re
                    last_call_used_reg_set);
 
   for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++)
-    if (HARD_REGNO_CALL_PART_CLOBBERED (hr, PSEUDO_REGNO_MODE (regno)))
+    if (targetm.hard_regno_call_part_clobbered (hr,
+                                               PSEUDO_REGNO_MODE (regno)))
       SET_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, hr);
   lra_reg_info[regno].call_p = true;
   if (! sparseset_bit_p (pseudos_live_through_setjumps, regno))
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c      2017-08-28 09:36:09.610827107 +0100
+++ gcc/regcprop.c      2017-08-28 09:36:10.072827140 +0100
@@ -34,6 +34,7 @@
 #include "tree-pass.h"
 #include "rtl-iter.h"
 #include "cfgrtl.h"
+#include "target.h"
 
 /* The following code does forward propagation of hard register copies.
    The object is to eliminate as many dependencies as possible, so that
@@ -1049,7 +1050,8 @@ copyprop_hardreg_forward_1 (basic_block
                                  regs_invalidated_by_call);
          for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
            if ((TEST_HARD_REG_BIT (regs_invalidated_by_this_call, regno)
-                || HARD_REGNO_CALL_PART_CLOBBERED (regno, vd->e[regno].mode))
+                || (targetm.hard_regno_call_part_clobbered
+                    (regno, vd->e[regno].mode)))
                && (regno < set_regno || regno >= set_regno + set_nregs))
              kill_value_regno (regno, 1, vd);
 
Index: gcc/reginfo.c
===================================================================
--- gcc/reginfo.c       2017-08-28 09:36:09.610827107 +0100
+++ gcc/reginfo.c       2017-08-28 09:36:10.072827140 +0100
@@ -637,7 +637,8 @@ choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
        && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (regno, mode))
        && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -646,7 +647,8 @@ choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
        && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (regno, mode))
        && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -655,7 +657,8 @@ choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
        && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (regno, mode))
        && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -664,7 +667,8 @@ choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
        && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (regno, mode))
        && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -677,7 +681,8 @@ choose_hard_reg_mode (unsigned int regno
       mode = (machine_mode) m;
       if ((unsigned) hard_regno_nregs[regno][mode] == nregs
          && HARD_REGNO_MODE_OK (regno, mode)
-         && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+         && (!call_saved
+             || !targetm.hard_regno_call_part_clobbered (regno, mode)))
        return mode;
     }
 
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c     2017-08-28 09:36:09.610827107 +0100
+++ gcc/regrename.c     2017-08-28 09:36:10.072827140 +0100
@@ -338,9 +338,9 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSE
     if ((! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
         && ! DEBUG_INSN_P (tmp->insn))
        || (this_head->need_caller_save_reg
-           && ! (HARD_REGNO_CALL_PART_CLOBBERED
+           && ! (targetm.hard_regno_call_part_clobbered
                  (reg, GET_MODE (*tmp->loc)))
-           && (HARD_REGNO_CALL_PART_CLOBBERED
+           && (targetm.hard_regno_call_part_clobbered
                (new_reg, GET_MODE (*tmp->loc)))))
       return false;
 
Index: gcc/reload.c
===================================================================
--- gcc/reload.c        2017-08-28 09:36:09.610827107 +0100
+++ gcc/reload.c        2017-08-28 09:36:10.073827140 +0100
@@ -6922,13 +6922,14 @@ find_equiv_reg (rtx goal, rtx_insn *insn
          if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
            for (i = 0; i < nregs; ++i)
              if (call_used_regs[regno + i]
-                 || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
+                 || targetm.hard_regno_call_part_clobbered (regno + i, mode))
                return 0;
 
          if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
            for (i = 0; i < valuenregs; ++i)
              if (call_used_regs[valueno + i]
-                 || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
+                 || targetm.hard_regno_call_part_clobbered (valueno + i,
+                                                            mode))
                return 0;
        }
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c       2017-08-28 09:36:09.610827107 +0100
+++ gcc/reload1.c       2017-08-28 09:36:10.074827140 +0100
@@ -8276,7 +8276,8 @@ emit_reload_insns (struct insn_chain *ch
                           : out_regno + k);
                      reg_reloaded_insn[regno + k] = insn;
                      SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+                     if (targetm.hard_regno_call_part_clobbered (regno + k,
+                                                                 mode))
                        SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
                                          regno + k);
                      else
@@ -8355,7 +8356,8 @@ emit_reload_insns (struct insn_chain *ch
                           : in_regno + k);
                      reg_reloaded_insn[regno + k] = insn;
                      SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+                     if (targetm.hard_regno_call_part_clobbered (regno + k,
+                                                                 mode))
                        SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
                                          regno + k);
                      else
@@ -8469,8 +8471,8 @@ emit_reload_insns (struct insn_chain *ch
                      reg_reloaded_insn[src_regno + k] = store_insn;
                      CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + k);
                      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + k);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + k,
-                                                         mode))
+                     if (targetm.hard_regno_call_part_clobbered
+                         (src_regno + k, mode))
                        SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
                                          src_regno + k);
                      else
Index: gcc/sched-deps.c
===================================================================
--- gcc/sched-deps.c    2017-08-28 09:36:09.610827107 +0100
+++ gcc/sched-deps.c    2017-08-28 09:36:10.074827140 +0100
@@ -3706,7 +3706,8 @@ deps_analyze_insn (struct deps_desc *dep
              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 (HARD_REGNO_CALL_PART_CLOBBERED (i, reg_raw_mode[i])
+           else if (targetm.hard_regno_call_part_clobbered (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
Index: gcc/sel-sched.c
===================================================================
--- gcc/sel-sched.c     2017-08-28 09:36:09.610827107 +0100
+++ gcc/sel-sched.c     2017-08-28 09:36:10.075827140 +0100
@@ -1102,7 +1102,7 @@ init_regs_for_mode (machine_mode mode)
       if (i >= 0)
         continue;
 
-      if (HARD_REGNO_CALL_PART_CLOBBERED (cur_reg, mode))
+      if (targetm.hard_regno_call_part_clobbered (cur_reg, mode))
         SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode],
                           cur_reg);
 
@@ -1251,7 +1251,7 @@ mark_unavailable_hard_regs (def_t def, s
 
   /* Exclude registers that are partially call clobbered.  */
   if (def->crosses_call
-      && ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+      && !targetm.hard_regno_call_part_clobbered (regno, mode))
     AND_COMPL_HARD_REG_SET (reg_rename_p->available_for_renaming,
                             sel_hrd.regs_for_call_clobbered[mode]);
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c     2017-08-28 09:36:09.610827107 +0100
+++ gcc/targhooks.c     2017-08-28 09:36:10.076827140 +0100
@@ -1736,7 +1736,7 @@ default_dwarf_frame_reg_mode (int regno)
 {
   machine_mode save_mode = reg_raw_mode[regno];
 
-  if (HARD_REGNO_CALL_PART_CLOBBERED (regno, save_mode))
+  if (targetm.hard_regno_call_part_clobbered (regno, save_mode))
     save_mode = choose_hard_reg_mode (regno, 1, true);
   return save_mode;
 }
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h        2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/aarch64/aarch64.h        2017-08-28 09:36:10.053827138 +0100
@@ -888,12 +888,6 @@ #define SHIFT_COUNT_TRUNCATED (!TARGET_S
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
 
-/* Callee only saves lower 64-bits of a 128-bit register.  Tell the
-   compiler the callee clobbers the top 64-bits when restoring the
-   bottom 64-bits.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
-               (FP_REGNUM_P (REGNO) && GET_MODE_SIZE (MODE) > 8)
-
 #undef SWITCHABLE_TARGET
 #define SWITCHABLE_TARGET 1
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c        2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/aarch64/aarch64.c        2017-08-28 09:36:10.053827138 +0100
@@ -1115,6 +1115,16 @@ aarch64_hard_regno_mode_ok (unsigned reg
   return 0;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
+   the lower 64 bits of a 128-bit register.  Tell the compiler the callee
+   clobbers the top 64 bits when restoring the bottom 64 bits.  */
+
+static bool
+aarch64_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  return FP_REGNUM_P (regno) && GET_MODE_SIZE (mode) > 8;
+}
+
 /* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
 machine_mode
 aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs,
@@ -15644,6 +15654,10 @@ #define TARGET_OMIT_STRUCT_RETURN_REG tr
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  aarch64_hard_regno_call_part_clobbered
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h        2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr.h        2017-08-28 09:36:10.054827138 +0100
@@ -285,9 +285,6 @@ #define REGNO_MODE_CODE_OK_FOR_BASE_P(nu
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)     \
-  avr_hard_regno_call_part_clobbered (REGNO, MODE)
-
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define STACK_PUSH_CODE POST_DEC
Index: gcc/config/avr/avr-protos.h
===================================================================
--- gcc/config/avr/avr-protos.h 2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr-protos.h 2017-08-28 09:36:10.053827138 +0100
@@ -46,7 +46,6 @@ extern void avr_init_cumulative_args (CU
 #endif /* TREE_CODE */
 
 #ifdef RTX_CODE
-extern int avr_hard_regno_call_part_clobbered (unsigned, machine_mode);
 extern const char *output_movqi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movhi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movsisf (rtx_insn *insn, rtx operands[], int *l);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c        2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr.c        2017-08-28 09:36:10.054827138 +0100
@@ -12186,9 +12186,9 @@ avr_hard_regno_mode_ok (int regno, machi
 }
 
 
-/* Implement `HARD_REGNO_CALL_PART_CLOBBERED'.  */
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
 
-int
+static bool
 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
 {
   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
@@ -14693,6 +14693,10 @@ #define TARGET_CONDITIONAL_REGISTER_USAG
 
 #undef  TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
+#undef  TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  avr_hard_regno_call_part_clobbered
+
 #undef  TARGET_CASE_VALUES_THRESHOLD
 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/i386/i386.h      2017-08-28 09:36:10.059827139 +0100
@@ -1214,12 +1214,6 @@ #define HARD_REGNO_CALLER_SAVE_MODE(REGN
                           || MASK_REGNO_P (REGNO)) ? SImode            \
    : (MODE))
 
-/* The only ABI that saves SSE registers across calls is Win64 (thus no
-   need to check the current ABI here), and with AVX enabled Win64 only
-   guarantees that the low 16 bytes are saved.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)             \
-  (SSE_REGNO_P (REGNO) && GET_MODE_SIZE (MODE) > 16)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/i386/i386.c      2017-08-28 09:36:10.058827139 +0100
@@ -41397,6 +41397,17 @@ ix86_hard_regno_mode_ok (int regno, mach
   return false;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The only ABI that
+   saves SSE registers across calls is Win64 (thus no need to check the
+   current ABI here), and with AVX enabled Win64 only guarantees that
+   the low 16 bytes are saved.  */
+
+static bool
+ix86_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16;
+}
+
 /* A subroutine of ix86_modes_tieable_p.  Return true if MODE is a
    tieable integer mode.  */
 
@@ -53239,6 +53250,10 @@ #define TARGET_MAX_NOCE_IFCVT_SEQ_COST i
 #undef TARGET_NOCE_CONVERSION_PROFITABLE_P
 #define TARGET_NOCE_CONVERSION_PROFITABLE_P ix86_noce_conversion_profitable_p
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  ix86_hard_regno_call_part_clobbered
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/mips/mips.h      2017-08-28 09:36:10.060827139 +0100
@@ -1971,14 +1971,6 @@ #define HARD_REGNO_RENAME_OK(OLD_REG, NE
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   mips_hard_regno_caller_save_mode (REGNO, NREGS, MODE)
 
-/* Odd-numbered single-precision registers are not considered callee-saved
-   for o32 FPXX as they will be clobbered when run on an FR=1 FPU.
-   MSA vector registers with MODE > 64 bits are part clobbered too.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)                    \
-  ((TARGET_FLOATXX && hard_regno_nregs[REGNO][MODE] == 1               \
-   && FP_REG_P (REGNO) && ((REGNO) & 1))                               \
-   || (ISA_HAS_MSA && FP_REG_P (REGNO) && GET_MODE_SIZE (MODE) > 8))
-
 #define MODES_TIEABLE_P mips_modes_tieable_p
 
 /* Register to use for pushing function arguments.  */
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/mips/mips.c      2017-08-28 09:36:10.060827139 +0100
@@ -12857,6 +12857,26 @@ mips_hard_regno_scratch_ok (unsigned int
   return true;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  Odd-numbered
+   single-precision registers are not considered callee-saved for o32
+   FPXX as they will be clobbered when run on an FR=1 FPU.  MSA vector
+   registers with MODE > 64 bits are part clobbered too.  */
+
+static bool
+mips_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_FLOATXX
+      && hard_regno_nregs[regno][mode] == 1
+      && FP_REG_P (regno)
+      && (regno & 1) != 0)
+    return true;
+
+  if (ISA_HAS_MSA && FP_REG_P (regno) && GET_MODE_SIZE (mode) > 8)
+    return true;
+
+  return false;
+}
+
 /* Implement HARD_REGNO_NREGS.  */
 
 unsigned int
@@ -22557,6 +22577,10 @@ #define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK mips_hard_regno_scratch_ok
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  mips_hard_regno_call_part_clobbered
+
 /* The architecture reserves bit 0 for MIPS16 so use bit 1 for descriptors.  */
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h  2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/powerpcspe/powerpcspe.h  2017-08-28 09:36:10.064827139 +0100
@@ -1302,13 +1302,6 @@ #define HARD_REGNO_CALLER_SAVE_MODE(REGN
    ? DImode                                                            \
    : choose_hard_reg_mode ((REGNO), (NREGS), false))
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)                    \
-  (((TARGET_32BIT && TARGET_POWERPC64                                  \
-     && (GET_MODE_SIZE (MODE) > 4)                                     \
-     && INT_REGNO_P (REGNO)) ? 1 : 0)                                  \
-   || (TARGET_VSX && FP_REGNO_P (REGNO)                                        
\
-       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
-
 #define VSX_VECTOR_MODE(MODE)          \
         ((MODE) == V4SFmode            \
          || (MODE) == V2DFmode)        \
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c  2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/powerpcspe/powerpcspe.c  2017-08-28 09:36:10.063827139 +0100
@@ -1972,6 +1972,10 @@ #define TARGET_OPTAB_SUPPORTED_P rs6000_
 
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
+
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  rs6000_hard_regno_call_part_clobbered
 
 
 /* Processor table.  */
@@ -2157,6 +2161,26 @@ rs6000_hard_regno_mode_ok (int regno, ma
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
+
+static bool
+rs6000_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_32BIT
+      && TARGET_POWERPC64
+      && GET_MODE_SIZE (mode) > 4
+      && INT_REGNO_P (regno))
+    return true;
+
+  if (TARGET_VSX
+      && FP_REGNO_P (regno)
+      && GET_MODE_SIZE (mode) > 8
+      && !FLOAT128_2REG_P (mode))
+    return true;
+
+  return false;
+}
+
 /* Print interesting facts about registers.  */
 static void
 rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h  2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/rs6000/rs6000.h  2017-08-28 09:36:10.067827139 +0100
@@ -1240,13 +1240,6 @@ #define HARD_REGNO_CALLER_SAVE_MODE(REGN
    ? DImode                                                            \
    : choose_hard_reg_mode ((REGNO), (NREGS), false))
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)                    \
-  (((TARGET_32BIT && TARGET_POWERPC64                                  \
-     && (GET_MODE_SIZE (MODE) > 4)                                     \
-     && INT_REGNO_P (REGNO)) ? 1 : 0)                                  \
-   || (TARGET_VSX && FP_REGNO_P (REGNO)                                        
\
-       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
-
 #define VSX_VECTOR_MODE(MODE)          \
         ((MODE) == V4SFmode            \
          || (MODE) == V2DFmode)        \
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/rs6000/rs6000.c  2017-08-28 09:36:10.066827139 +0100
@@ -1963,6 +1963,9 @@ #define TARGET_GET_FUNCTION_VERSIONS_DIS
 #undef TARGET_OPTION_FUNCTION_VERSIONS
 #define TARGET_OPTION_FUNCTION_VERSIONS common_function_versions
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  rs6000_hard_regno_call_part_clobbered
 
 
 /* Processor table.  */
@@ -2125,6 +2128,26 @@ rs6000_hard_regno_mode_ok (int regno, ma
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
+
+static bool
+rs6000_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_32BIT
+      && TARGET_POWERPC64
+      && GET_MODE_SIZE (mode) > 4
+      && INT_REGNO_P (regno))
+    return true;
+
+  if (TARGET_VSX
+      && FP_REGNO_P (regno)
+      && GET_MODE_SIZE (mode) > 8
+      && !FLOAT128_2REG_P (mode))
+    return true;
+
+  return false;
+}
+
 /* Print interesting facts about registers.  */
 static void
 rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/s390/s390.h      2017-08-28 09:36:10.068827139 +0100
@@ -509,19 +509,6 @@ #define MODES_TIEABLE_P(MODE1, MODE2)              \
    (((MODE1) == SFmode || (MODE1) == DFmode)   \
    == ((MODE2) == SFmode || (MODE2) == DFmode))
 
-/* When generating code that runs in z/Architecture mode,
-   but conforms to the 31-bit ABI, GPRs can hold 8 bytes;
-   the ABI guarantees only that the lower 4 bytes are
-   saved across calls, however.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)                    \
-  ((!TARGET_64BIT && TARGET_ZARCH                                      \
-    && GET_MODE_SIZE (MODE) > 4                                                
\
-    && (((REGNO) >= 6 && (REGNO) <= 15) || (REGNO) == 32))             \
-   || (TARGET_VX                                                       \
-       && GET_MODE_SIZE (MODE) > 8                                     \
-       && (((TARGET_64BIT && (REGNO) >= 24 && (REGNO) <= 31))          \
-          || (!TARGET_64BIT && ((REGNO) == 18 || (REGNO) == 19)))))
-
 /* Maximum number of registers to represent a value of mode MODE
    in a register of class CLASS.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)                                           
\
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c      2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/s390/s390.c      2017-08-28 09:36:10.068827139 +0100
@@ -10476,6 +10476,29 @@ s390_hard_regno_scratch_ok (unsigned int
   return true;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  When generating
+   code that runs in z/Architecture mode, but conforms to the 31-bit
+   ABI, GPRs can hold 8 bytes; the ABI guarantees only that the lower 4
+   bytes are saved across calls, however.  */
+
+static bool
+s390_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (!TARGET_64BIT
+      && TARGET_ZARCH
+      && GET_MODE_SIZE (mode) > 4
+      && ((regno >= 6 && regno <= 15) || regno == 32))
+    return true;
+
+  if (TARGET_VX
+      && GET_MODE_SIZE (mode) > 8
+      && (((TARGET_64BIT && regno >= 24 && regno <= 31))
+         || (!TARGET_64BIT && (regno == 18 || regno == 19))))
+    return true;
+
+  return false;
+}
+
 /* Maximum number of registers to represent a value of mode MODE
    in a register of class RCLASS.  */
 
@@ -15877,6 +15900,10 @@ #define TARGET_CANONICALIZE_COMPARISON s
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK s390_hard_regno_scratch_ok
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  s390_hard_regno_call_part_clobbered
+
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE s390_attribute_table
 
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h  2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/sh/sh.h  2017-08-28 09:36:10.068827139 +0100
@@ -811,8 +811,6 @@ #define CALL_REALLY_USED_REGISTERS
   1,      1,      0,      0,                                           \
 }
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO,MODE) (false)
-
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
Index: gcc/system.h
===================================================================
--- gcc/system.h        2017-08-28 09:36:09.610827107 +0100
+++ gcc/system.h        2017-08-28 09:36:10.075827140 +0100
@@ -904,7 +904,8 @@ #define realloc xrealloc
        ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE          \
        LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE     \
        CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P              \
-       STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD
+       STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD                        \
+       HARD_REGNO_CALL_PART_CLOBBERED
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */

Reply via email to