Turn SECONDARY_MEMORY_NEEDED_MODE into a target hook

Message ID 87wp53ah59.fsf@linaro.org
State New
Headers show
Series
  • Turn SECONDARY_MEMORY_NEEDED_MODE into a target hook
Related show

Commit Message

Richard Sandiford Sept. 12, 2017, 6:47 p.m.
It feels like SECONDARY_MEMORY_NEEDED and SECONDARY_MEMORY_NEEDED_MODE
should be a single hook that returns the memory mode if memory is needed
and an empty opt_mode otherwise.  The snag is this code in reload.c:

      /* If we need a memory location to copy between the two reload regs,
         set it up now.  Note that we do the input case before making
         the reload and the output case after.  This is due to the
         way reloads are output.  */

      if (in_p && icode == CODE_FOR_nothing
          && SECONDARY_MEMORY_NEEDED (rclass, reload_class, mode))
        {
          get_secondary_mem (x, reload_mode, opnum, type);

          /* We may have just added new reloads.  Make sure we add
             the new reload at the end.  */
          s_reload = n_reloads;
        }

where we use "mode" to test whether a secondary reload is needed but pass
"reload_mode" to get_secondary_mem (and thus SECONDARY_MEMORY_NEEDED_MODE).
This difference appears to come from:

Thu Aug 21 17:56:06 1997  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

        * reload.c (push_secondary_reload): If SECONDARY_MEM_NEEDED,
        call get_secondary_mem for input before adding reload and
        for output after.
        (push_reload): Likewise.

which sounds like it was just moving the code, but also changed the
get_secondary_mem mode argument from "mode" to "reload_mode".

It seems unlikely that the two modes should be different, but it's not
obvious which one is right.  The corresponding code for output reloads
uses "mode" consistently, like the input code did before the patch above:

      if (! in_p && icode == CODE_FOR_nothing
          && SECONDARY_MEMORY_NEEDED (reload_class, rclass, mode))
        get_secondary_mem (x, mode, opnum, type);

while the main secondary_reload hook uses "reload_mode":

  rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class,
                                                      reload_mode, &sri);

The difference only matters for reloads of paradoxical subregs that need
to go through secondary memory, which is hardly a common case.  In the
end the whole thing seemed too delicate to change, so the patch instead
just converts the macro to a hook with its current interface.

There is also a change for LRA.  Previously the code was:

    if (sclass == NO_REGS && dclass == NO_REGS)
      return false;
  #ifdef SECONDARY_MEMORY_NEEDED
    if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
  #ifdef SECONDARY_MEMORY_NEEDED_MODE
        && ((sclass != NO_REGS && dclass != NO_REGS)
            || GET_MODE (src) != SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (src)))
  #endif
        )
      {
        *sec_mem_p = true;
        return false;
      }
  #endif

This allows reloads to and from memory (class == NO_REGS) to use
secondary memory reloads.  It comes from:

2013-05-24  Vladimir Makarov  <vmakarov@redhat.com>

        * lra-constraints.c (emit_spill_move): Use smaller mode for
        mem-mem moves.
        (check_and_process_move): Consider mem-reg moves for secondary
        too.
        (curr_insn_transform): Don't lose insns emitted before for
        secondary memory moves.
        (inherit_in_ebb): Mark defined reg.  Add usage only if it is not a
        reg set up in the current insn.

But the positioning of the second ifdef meant that defining
SECONDARY_MEMORY_NEEDED_MODE to its default value was not a no-op:

(1) if a target does define SECONDARY_MEMORY_NEEDED_MODE, only cases
    that need a different memory mode would use secondary memory reloads.
    Cases that need the same memory mode would not use secondary reloads.

(2) if a target doesn't define SECONDARY_MEMORY_NEEDED_MODE, we would
    always use secondary memory reloads for mem<->reg and reg<->mem,
    even though the secondary memory would have the same mode as the
    memory that we're moving to or from.

(1) seems like the correct behaviour, since in (2) there's nothing to
distinguish the secondary memory from the original; we'd just get
a redundant mem<->mem move.

The default is different for reload and LRA.  For LRA the default is
to use the original mode, while reload promotes smaller-than-word
integral modes to word mode:

  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
    mode = mode_for_size (BITS_PER_WORD,
                          GET_MODE_CLASS (mode), 0).require ();

Some of the ports that have switched to LRA seemed to have
SECONDARY_MEMORY_NEEDED_MDOEs based on the old reload definition,
and still referred to the reload.c:get_secondary_mem function in
the comments.  The patch just keeps them as-is.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by comparing the testsuite assembly output on at least one
target per CPU directory.  OK to install?

Richard


2017-09-12  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* target.def (secondary_memory_needed_mode): New hook:
	* targhooks.c (default_secondary_memory_needed_mode): Declare.
	* targhooks.h (default_secondary_memory_needed_mode): New function.
	* doc/tm.texi.in (SECONDARY_MEMORY_NEEDED_MODE): Replace with...
	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): ...this.
	* doc/tm.texi: Regenerate.
	* lra-constraints.c (check_and_process_move): Use
	targetm.secondary_memory_needed_mode instead of
	TARGET_SECONDARY_MEMORY_NEEDED_MODE.
	(curr_insn_transform): Likewise.
	* reload.c (get_secondary_mem): Likewise.
	* config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
	* config/alpha/alpha.c (alpha_secondary_memory_needed_mode): New
	function.
	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
	* config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
	* config/i386/i386.c (ix86_secondary_memory_needed_mode): New function.
	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
	* config/powerpcspe/powerpcspe.h (SECONDARY_MEMORY_NEEDED_MODE):
	Delete.
	* config/powerpcspe/powerpcspe-protos.h
	(rs6000_secondary_memory_needed_mode): Delete.
	* config/powerpcspe/powerpcspe.c
	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
	(rs6000_secondary_memory_needed_mode): Make static.
	* config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
	* config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_mode):
	Delete.
	* config/rs6000/rs6000.c (TARGET_SECONDARY_MEMORY_NEEDED_MODE):
	Redefine.
	(rs6000_secondary_memory_needed_mode): Make static.
	* config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
	* config/s390/s390.c (s390_secondary_memory_needed_mode): New function.
	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
	* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
	* config/sparc/sparc.c (TARGET_SECONDARY_MEMORY_NEEDED_MODE):
	Redefine.
	(sparc_secondary_memory_needed_mode): New function.
	* system.h (TARGET_SECONDARY_MEMORY_NEEDED_MODE): Poison.

Comments

Jeff Law Sept. 12, 2017, 10:30 p.m. | #1
On 09/12/2017 12:47 PM, Richard Sandiford wrote:
> It feels like SECONDARY_MEMORY_NEEDED and SECONDARY_MEMORY_NEEDED_MODE
> should be a single hook that returns the memory mode if memory is needed
> and an empty opt_mode otherwise.  The snag is this code in reload.c:
> 
>       /* If we need a memory location to copy between the two reload regs,
>          set it up now.  Note that we do the input case before making
>          the reload and the output case after.  This is due to the
>          way reloads are output.  */
> 
>       if (in_p && icode == CODE_FOR_nothing
>           && SECONDARY_MEMORY_NEEDED (rclass, reload_class, mode))
>         {
>           get_secondary_mem (x, reload_mode, opnum, type);
> 
>           /* We may have just added new reloads.  Make sure we add
>              the new reload at the end.  */
>           s_reload = n_reloads;
>         }
> 
> where we use "mode" to test whether a secondary reload is needed but pass
> "reload_mode" to get_secondary_mem (and thus SECONDARY_MEMORY_NEEDED_MODE).
> This difference appears to come from:
> 
> Thu Aug 21 17:56:06 1997  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
> 
>         * reload.c (push_secondary_reload): If SECONDARY_MEM_NEEDED,
>         call get_secondary_mem for input before adding reload and
>         for output after.
>         (push_reload): Likewise.
> 
> which sounds like it was just moving the code, but also changed the
> get_secondary_mem mode argument from "mode" to "reload_mode".
> 
> It seems unlikely that the two modes should be different, but it's not
> obvious which one is right.  The corresponding code for output reloads
> uses "mode" consistently, like the input code did before the patch above:
> 
>       if (! in_p && icode == CODE_FOR_nothing
>           && SECONDARY_MEMORY_NEEDED (reload_class, rclass, mode))
>         get_secondary_mem (x, mode, opnum, type);
> 
> while the main secondary_reload hook uses "reload_mode":
> 
>   rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class,
>                                                       reload_mode, &sri);
> 
> The difference only matters for reloads of paradoxical subregs that need
> to go through secondary memory, which is hardly a common case.  In the
> end the whole thing seemed too delicate to change, so the patch instead
> just converts the macro to a hook with itscurrent interface.


I wandered my private gcc2 archives, for Aug 1997, but didn't see
anything obviously relevant.  I don't have archives for the old gcc-bugs
list -- even if we had them and the change was in response to a bug
reported there I don't think we typically posted anything that would
allow us to map backwards from the change to the bug.

Note that Jim had changed some of this code a bit earlier in a way that
might be relevant:

commit c03001748750bec11636c34e93d77be19da49054
Author: wilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Sep 25 00:44:04 1996 +0000

    (push_secondary_reload): Do strip paradoxical SUBREG
    even if reload_class is CLASS_CANNOT_CHANGE_SIZE.  Change reload_mode
    to mode in SECONDARY_MEMORY_NEEDED and get_secondary_mem calls.


    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@12841
138bc75d-0d04-0410-961f-82ee72b054a4

But nothing in the gcc2 archives about that patch either.


I won't even try to guess what's going on here.  As you note, the safe
thing to do is preserve current behavior.  We can always go back
independently and try to make this consistent and see what falls out.
Given the age, whatever port and attribute of the port in question may
be a dead end in processor architecture and no longer relevant.


> 
> There is also a change for LRA.  Previously the code was:
> 
>     if (sclass == NO_REGS && dclass == NO_REGS)
>       return false;
>   #ifdef SECONDARY_MEMORY_NEEDED
>     if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
>   #ifdef SECONDARY_MEMORY_NEEDED_MODE
>         && ((sclass != NO_REGS && dclass != NO_REGS)
>             || GET_MODE (src) != SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (src)))
>   #endif
>         )
>       {
>         *sec_mem_p = true;
>         return false;
>       }
>   #endif
> 
> This allows reloads to and from memory (class == NO_REGS) to use
> secondary memory reloads.  It comes from:
> 
> 2013-05-24  Vladimir Makarov  <vmakarov@redhat.com>
> 
>         * lra-constraints.c (emit_spill_move): Use smaller mode for
>         mem-mem moves.
>         (check_and_process_move): Consider mem-reg moves for secondary
>         too.
>         (curr_insn_transform): Don't lose insns emitted before for
>         secondary memory moves.
>         (inherit_in_ebb): Mark defined reg.  Add usage only if it is not a
>         reg set up in the current insn.
> 
> But the positioning of the second ifdef meant that defining
> SECONDARY_MEMORY_NEEDED_MODE to its default value was not a no-op:
> 
> (1) if a target does define SECONDARY_MEMORY_NEEDED_MODE, only cases
>     that need a different memory mode would use secondary memory reloads.
>     Cases that need the same memory mode would not use secondary reloads.
> 
> (2) if a target doesn't define SECONDARY_MEMORY_NEEDED_MODE, we would
>     always use secondary memory reloads for mem<->reg and reg<->mem,
>     even though the secondary memory would have the same mode as the
>     memory that we're moving to or from.
> 
> (1) seems like the correct behaviour, since in (2) there's nothing to
> distinguish the secondary memory from the original; we'd just get
> a redundant mem<->mem move.
> 
> The default is different for reload and LRA.  For LRA the default is
> to use the original mode, while reload promotes smaller-than-word
> integral modes to word mode:
And what most ports seem to do is avoid that promotion to word_mode!
For example on a 64 bit target, we may need a secondary memory reload
for a 32 bit object which we can often handle just fine.  At least
that's the impression I get from scanning the uses.

> 
>   if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
>     mode = mode_for_size (BITS_PER_WORD,
>                           GET_MODE_CLASS (mode), 0).require ();
> 
> Some of the ports that have switched to LRA seemed to have
> SECONDARY_MEMORY_NEEDED_MDOEs based on the old reload definition,
> and still referred to the reload.c:get_secondary_mem function in
> the comments.  The patch just keeps them as-is.
Seems like the safe thing to do, but may be ripe for some cleanups.

> 
> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
> Also tested by comparing the testsuite assembly output on at least one
> target per CPU directory.  OK to install?
> 
> Richard
> 
> 
> 2017-09-12  Richard Sandiford  <richard.sandiford@linaro.org>
> 	    Alan Hayward  <alan.hayward@arm.com>
> 	    David Sherwood  <david.sherwood@arm.com>
> 
> gcc/
> 	* target.def (secondary_memory_needed_mode): New hook:
> 	* targhooks.c (default_secondary_memory_needed_mode): Declare.
> 	* targhooks.h (default_secondary_memory_needed_mode): New function.
> 	* doc/tm.texi.in (SECONDARY_MEMORY_NEEDED_MODE): Replace with...
> 	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): ...this.
> 	* doc/tm.texi: Regenerate.
> 	* lra-constraints.c (check_and_process_move): Use
> 	targetm.secondary_memory_needed_mode instead of
> 	TARGET_SECONDARY_MEMORY_NEEDED_MODE.
> 	(curr_insn_transform): Likewise.
> 	* reload.c (get_secondary_mem): Likewise.
> 	* config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
> 	* config/alpha/alpha.c (alpha_secondary_memory_needed_mode): New
> 	function.
> 	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
> 	* config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
> 	* config/i386/i386.c (ix86_secondary_memory_needed_mode): New function.
> 	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
> 	* config/powerpcspe/powerpcspe.h (SECONDARY_MEMORY_NEEDED_MODE):
> 	Delete.
> 	* config/powerpcspe/powerpcspe-protos.h
> 	(rs6000_secondary_memory_needed_mode): Delete.
> 	* config/powerpcspe/powerpcspe.c
> 	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
> 	(rs6000_secondary_memory_needed_mode): Make static.
> 	* config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
> 	* config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_mode):
> 	Delete.
> 	* config/rs6000/rs6000.c (TARGET_SECONDARY_MEMORY_NEEDED_MODE):
> 	Redefine.
> 	(rs6000_secondary_memory_needed_mode): Make static.
> 	* config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
> 	* config/s390/s390.c (s390_secondary_memory_needed_mode): New function.
> 	(TARGET_SECONDARY_MEMORY_NEEDED_MODE): Redefine.
> 	* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Delete.
> 	* config/sparc/sparc.c (TARGET_SECONDARY_MEMORY_NEEDED_MODE):
> 	Redefine.
> 	(sparc_secondary_memory_needed_mode): New function.
> 	* system.h (TARGET_SECONDARY_MEMORY_NEEDED_MODE): Poison.
OK.
jeff

Patch

Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-12 14:29:25.265529315 +0100
+++ gcc/target.def	2017-09-12 19:42:13.226875090 +0100
@@ -5265,6 +5265,30 @@  forwarding logic, you can set @code{sri-
   secondary_reload_info *sri),
  default_secondary_reload)
 
+DEFHOOK
+(secondary_memory_needed_mode,
+ "If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory\n\
+when moving between two particular registers of mode @var{mode},\n\
+this hook specifies the mode that the memory should have.\n\
+\n\
+The default depends on @code{TARGET_LRA_P}.  Without LRA, the default\n\
+is to use a word-sized mode for integral modes that are smaller than a\n\
+a word.  This is right thing to do on most machines because it ensures\n\
+that all bits of the register are copied and prevents accesses to the\n\
+registers in a narrower mode, which some machines prohibit for\n\
+floating-point registers.\n\
+\n\
+However, this default behavior is not correct on some machines, such as\n\
+the DEC Alpha, that store short integers in floating-point registers\n\
+differently than in integer registers.  On those machines, the default\n\
+widening will not work correctly and you must define this hook to\n\
+suppress that widening in some cases.  See the file @file{alpha.c} for\n\
+details.\n\
+\n\
+With LRA, the default is to use @var{mode} unmodified.",
+ machine_mode, (machine_mode mode),
+ default_secondary_memory_needed_mode)
+
 /* Given an rtx X being reloaded into a reg required to be in class CLASS,
    return the class of reg to actually use.  */
 DEFHOOK
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-12 14:29:25.265529315 +0100
+++ gcc/targhooks.c	2017-09-12 19:42:13.226875090 +0100
@@ -1129,6 +1129,18 @@  default_secondary_reload (bool in_p ATTR
   return rclass;
 }
 
+/* The default implementation of TARGET_SECONDARY_MEMORY_NEEDED_MODE.  */
+
+machine_mode
+default_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (!targetm.lra_p ()
+      && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+      && INTEGRAL_MODE_P (mode))
+    return mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* By default, if flag_pic is true, then neither local nor global relocs
    should be placed in readonly memory.  */
 
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-09-12 14:29:25.265529315 +0100
+++ gcc/targhooks.h	2017-09-12 19:42:13.226875090 +0100
@@ -159,6 +159,7 @@  extern bool default_different_addr_displ
 extern reg_class_t default_secondary_reload (bool, rtx, reg_class_t,
 					     machine_mode,
 					     secondary_reload_info *);
+extern machine_mode default_secondary_memory_needed_mode (machine_mode);
 extern void default_target_option_override (void);
 extern void hook_void_bitmap (bitmap);
 extern int default_reloc_rw_mask (void);
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-09-12 14:29:25.263529402 +0100
+++ gcc/doc/tm.texi.in	2017-09-12 19:42:13.224976512 +0100
@@ -2324,29 +2324,7 @@  Do not define this macro if you do not d
 @code{SECONDARY_MEMORY_NEEDED}.
 @end defmac
 
-@defmac SECONDARY_MEMORY_NEEDED_MODE (@var{mode})
-When the compiler needs a secondary memory location to copy between two
-registers of mode @var{mode}, it normally allocates sufficient memory to
-hold a quantity of @code{BITS_PER_WORD} bits and performs the store and
-load operations in a mode that many bits wide and whose class is the
-same as that of @var{mode}.
-
-This is right thing to do on most machines because it ensures that all
-bits of the register are copied and prevents accesses to the registers
-in a narrower mode, which some machines prohibit for floating-point
-registers.
-
-However, this default behavior is not correct on some machines, such as
-the DEC Alpha, that store short integers in floating-point registers
-differently than in integer registers.  On those machines, the default
-widening will not work correctly and you must define this macro to
-suppress that widening in some cases.  See the file @file{alpha.h} for
-details.
-
-Do not define this macro if you do not define
-@code{SECONDARY_MEMORY_NEEDED} or if widening @var{mode} to a mode that
-is @code{BITS_PER_WORD} bits wide is correct for your machine.
-@end defmac
+@hook TARGET_SECONDARY_MEMORY_NEEDED_MODE
 
 @hook TARGET_CLASS_LIKELY_SPILLED_P
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-12 14:29:25.263529402 +0100
+++ gcc/doc/tm.texi	2017-09-12 19:42:13.224976512 +0100
@@ -2747,29 +2747,27 @@  Do not define this macro if you do not d
 @code{SECONDARY_MEMORY_NEEDED}.
 @end defmac
 
-@defmac SECONDARY_MEMORY_NEEDED_MODE (@var{mode})
-When the compiler needs a secondary memory location to copy between two
-registers of mode @var{mode}, it normally allocates sufficient memory to
-hold a quantity of @code{BITS_PER_WORD} bits and performs the store and
-load operations in a mode that many bits wide and whose class is the
-same as that of @var{mode}.
+@deftypefn {Target Hook} machine_mode TARGET_SECONDARY_MEMORY_NEEDED_MODE (machine_mode @var{mode})
+If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory
+when moving between two particular registers of mode @var{mode},
+this hook specifies the mode that the memory should have.
 
-This is right thing to do on most machines because it ensures that all
-bits of the register are copied and prevents accesses to the registers
-in a narrower mode, which some machines prohibit for floating-point
-registers.
+The default depends on @code{TARGET_LRA_P}.  Without LRA, the default
+is to use a word-sized mode for integral modes that are smaller than a
+a word.  This is right thing to do on most machines because it ensures
+that all bits of the register are copied and prevents accesses to the
+registers in a narrower mode, which some machines prohibit for
+floating-point registers.
 
 However, this default behavior is not correct on some machines, such as
 the DEC Alpha, that store short integers in floating-point registers
 differently than in integer registers.  On those machines, the default
-widening will not work correctly and you must define this macro to
-suppress that widening in some cases.  See the file @file{alpha.h} for
+widening will not work correctly and you must define this hook to
+suppress that widening in some cases.  See the file @file{alpha.c} for
 details.
 
-Do not define this macro if you do not define
-@code{SECONDARY_MEMORY_NEEDED} or if widening @var{mode} to a mode that
-is @code{BITS_PER_WORD} bits wide is correct for your machine.
-@end defmac
+With LRA, the default is to use @var{mode} unmodified.
+@end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_CLASS_LIKELY_SPILLED_P (reg_class_t @var{rclass})
 A target hook which returns @code{true} if pseudos that have been assigned
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	2017-09-12 14:28:56.396825056 +0100
+++ gcc/lra-constraints.c	2017-09-12 19:42:13.225925801 +0100
@@ -1203,11 +1203,9 @@  check_and_process_move (bool *change_p,
     return false;
 #ifdef SECONDARY_MEMORY_NEEDED
   if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
       && ((sclass != NO_REGS && dclass != NO_REGS)
-	  || GET_MODE (src) != SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (src)))
-#endif
-      )
+	  || (GET_MODE (src)
+	      != targetm.secondary_memory_needed_mode (GET_MODE (src)))))
     {
       *sec_mem_p = true;
       return false;
@@ -3940,11 +3938,7 @@  curr_insn_transform (bool check_only_p)
 		  && curr_static_id->operand[in].type == OP_IN);
       rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest;
       rld_mode = GET_MODE (rld);
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
-      sec_mode = SECONDARY_MEMORY_NEEDED_MODE (rld_mode);
-#else
-      sec_mode = rld_mode;
-#endif
+      sec_mode = targetm.secondary_memory_needed_mode (rld_mode);
       new_reg = lra_create_new_reg (sec_mode, NULL_RTX,
 				    NO_REGS, "secondary");
       /* If the mode is changed, it should be wider.  */
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2017-09-12 14:28:56.398824964 +0100
+++ gcc/reload.c	2017-09-12 19:42:13.225925801 +0100
@@ -574,13 +574,7 @@  get_secondary_mem (rtx x ATTRIBUTE_UNUSE
      locations do not support short load and stores from all registers
      (e.g., FP registers).  */
 
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
-  mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
-#else
-  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
-    mode = mode_for_size (BITS_PER_WORD,
-			  GET_MODE_CLASS (mode), 0).require ();
-#endif
+  mode = targetm.secondary_memory_needed_mode (mode);
 
   /* If we already have made a MEM for this operand in MODE, return it.  */
   if (secondary_memlocs_elim[(int) mode][opnum] != 0)
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-09-12 14:29:25.224531114 +0100
+++ gcc/config/alpha/alpha.h	2017-09-12 19:42:13.211686464 +0100
@@ -486,16 +486,6 @@  #define SECONDARY_MEMORY_NEEDED(CLASS1,C
  (! TARGET_FIX && (((CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS) \
                    || ((CLASS2) == FLOAT_REGS && (CLASS1) != FLOAT_REGS)))
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  If MODE is floating-point, use it.  Otherwise,
-   widen to a word like the default.  This is needed because we always
-   store integers in FP registers in quadword format.  This whole
-   area is very tricky! */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE)		\
-   : GET_MODE_SIZE (MODE) >= 4 ? (MODE)			\
-   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require ())
-
 /* Return the class of registers that cannot change mode from FROM to TO.  */
 
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)		\
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2017-09-11 17:10:56.054131183 +0100
+++ gcc/config/alpha/alpha.c	2017-09-12 19:42:13.211686464 +0100
@@ -1688,6 +1688,21 @@  alpha_secondary_reload (bool in_p, rtx x
 
   return NO_REGS;
 }
+
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.  If MODE is
+   floating-point, use it.  Otherwise, widen to a word like the default.
+   This is needed because we always store integers in FP registers in
+   quadword format.  This whole area is very tricky!  */
+
+static machine_mode
+alpha_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return mode;
+  if (GET_MODE_SIZE (mode) >= 4)
+    return mode;
+  return mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0).require ();
+}
 
 /* Given SEQ, which is an INSN list, look for any MEMs in either
    a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and
@@ -10062,6 +10077,8 @@  #define TARGET_INSTANTIATE_DECLS alpha_i
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD alpha_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE alpha_secondary_memory_needed_mode
 
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-09-12 14:29:25.236530587 +0100
+++ gcc/config/i386/i386.h	2017-09-12 19:42:13.215483620 +0100
@@ -1524,14 +1524,6 @@  #define BASE_REG_CLASS GENERAL_REGS
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
   ix86_secondary_memory_needed ((CLASS1), (CLASS2), (MODE), 1)
 
-/* Get_secondary_mem widens integral modes to BITS_PER_WORD.
-   There is no need to emit full 64 bit move on 64 bit targets
-   for integral modes that can be moved using 32 bit move.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
-  (GET_MODE_BITSIZE (MODE) < 32 && INTEGRAL_MODE_P (MODE)	\
-   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
-   : MODE)
-
 /* Return a class of registers that cannot change FROM mode to TO mode.  */
 
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-12 14:29:25.236530587 +0100
+++ gcc/config/i386/i386.c	2017-09-12 19:42:13.215483620 +0100
@@ -41162,6 +41162,20 @@  ix86_secondary_memory_needed (enum reg_c
   return inline_secondary_memory_needed (class1, class2, mode, strict);
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens integral modes to BITS_PER_WORD.
+   There is no need to emit full 64 bit move on 64 bit targets
+   for integral modes that can be moved using 32 bit move.  */
+
+static machine_mode
+ix86_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_BITSIZE (mode) < 32 && INTEGRAL_MODE_P (mode))
+    return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* Implement the TARGET_CLASS_MAX_NREGS hook.
 
    On the 80386, this is the size of MODE in words,
@@ -53206,6 +53220,8 @@  #define TARGET_INSTANTIATE_DECLS ix86_in
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD ix86_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE ix86_secondary_memory_needed_mode
 
 #undef TARGET_CLASS_MAX_NREGS
 #define TARGET_CLASS_MAX_NREGS ix86_class_max_nregs
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-09-12 14:29:25.250529973 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-09-12 19:42:13.219280777 +0100
@@ -1611,13 +1611,6 @@  #define SECONDARY_MEMORY_NEEDED(CLASS1,C
 #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
   rs6000_secondary_memory_needed_rtx (MODE)
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  For cpus that cannot load/store SDmode values
-   from the 64-bit FP registers without using a full 64-bit
-   load/store, we need a wider mode.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  rs6000_secondary_memory_needed_mode (MODE)
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
Index: gcc/config/powerpcspe/powerpcspe-protos.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe-protos.h	2017-09-04 11:50:24.553468246 +0100
+++ gcc/config/powerpcspe/powerpcspe-protos.h	2017-09-12 19:42:13.216432909 +0100
@@ -154,7 +154,6 @@  extern void rs6000_emit_le_vsx_move (rtx
 extern bool valid_sf_si_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-12 14:29:25.250529973 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-12 19:42:13.218331488 +0100
@@ -1897,6 +1897,8 @@  #define TARGET_INSTANTIATE_DECLS rs6000_
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -21811,10 +21813,9 @@  rs6000_secondary_memory_needed_rtx (mach
   return ret;
 }
 
-/* Return the mode to be used for memory when a secondary memory
-   location is needed.  For SDmode values we need to use DDmode, in
-   all other cases we can use the same mode.  */
-machine_mode
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.  For SDmode values we
+   need to use DDmode, in all other cases we can use the same mode.  */
+static machine_mode
 rs6000_secondary_memory_needed_mode (machine_mode mode)
 {
   if (lra_in_progress && mode == SDmode)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-09-12 14:29:25.254529797 +0100
+++ gcc/config/rs6000/rs6000.h	2017-09-12 19:42:13.221179355 +0100
@@ -1514,13 +1514,6 @@  #define SECONDARY_RELOAD_CLASS(CLASS,MOD
 #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE)			\
   rs6000_secondary_memory_needed_ptr (CLASS1, CLASS2, MODE)
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  For cpus that cannot load/store SDmode values
-   from the 64-bit FP registers without using a full 64-bit
-   load/store, we need a wider mode.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  rs6000_secondary_memory_needed_mode (MODE)
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	2017-09-04 11:50:24.557970193 +0100
+++ gcc/config/rs6000/rs6000-protos.h	2017-09-12 19:42:13.219280777 +0100
@@ -155,7 +155,6 @@  extern void rs6000_emit_le_vsx_permute (
 extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
 extern bool valid_sf_si_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-12 14:29:25.254529797 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-12 19:42:13.221179355 +0100
@@ -1876,6 +1876,8 @@  #define TARGET_BUILTIN_RECIPROCAL rs6000
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -19238,10 +19240,9 @@  mems_ok_for_quad_peep (rtx mem1, rtx mem
   return 1;
 }
 
-/* Return the mode to be used for memory when a secondary memory
-   location is needed.  For SDmode values we need to use DDmode, in
-   all other cases we can use the same mode.  */
-machine_mode
+/* Implement TARGET_SECONDARY_RELOAD_NEEDED_MODE.  For SDmode values we
+   need to use DDmode, in all other cases we can use the same mode.  */
+static machine_mode
 rs6000_secondary_memory_needed_mode (machine_mode mode)
 {
   if (lra_in_progress && mode == SDmode)
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-09-12 14:29:25.256529710 +0100
+++ gcc/config/s390/s390.h	2017-09-12 19:42:13.223077933 +0100
@@ -599,13 +599,6 @@  #define SECONDARY_MEMORY_NEEDED(CLASS1,
    && (!TARGET_VX || (SCALAR_FLOAT_MODE_P (MODE)			\
 			  && GET_MODE_SIZE (MODE) > 8)))
 
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
-   because the movsi and movsf patterns don't handle r/f moves.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
- (GET_MODE_BITSIZE (MODE) < 32					\
-  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
-  : (MODE))
-
 
 /* Stack layout and calling conventions.  */
 
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-09-12 14:29:25.256529710 +0100
+++ gcc/config/s390/s390.c	2017-09-12 19:42:13.223077933 +0100
@@ -4409,6 +4409,19 @@  #define __SECONDARY_RELOAD_CASE(M,m)
   return NO_REGS;
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
+   because the movsi and movsf patterns don't handle r/f moves.  */
+
+static machine_mode
+s390_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_BITSIZE (mode) < 32)
+    return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* Generate code to load SRC, which is PLUS that is not a
    legitimate operand for the LA instruction, into TARGET.
    SCRATCH may be used as scratch register.  */
@@ -15959,6 +15972,8 @@  #define TARGET_PREFERRED_RELOAD_CLASS s3
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD s390_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE s390_secondary_memory_needed_mode
 
 #undef TARGET_LIBGCC_CMP_RETURN_MODE
 #define TARGET_LIBGCC_CMP_RETURN_MODE s390_libgcc_cmp_return_mode
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-09-12 14:29:25.259529578 +0100
+++ gcc/config/sparc/sparc.h	2017-09-12 19:42:13.224027222 +0100
@@ -1055,18 +1055,6 @@  #define SECONDARY_MEMORY_NEEDED(CLASS1,
        || GET_MODE_SIZE (MODE) > 8 \
        || GET_MODE_SIZE (MODE) < 4))
 
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
-   because the movsi and movsf patterns don't handle r/f moves.
-   For v8 we copy the default definition.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)				   \
-  (TARGET_ARCH64							   \
-   ? (GET_MODE_BITSIZE (MODE) < 32					   \
-      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()		   \
-      : MODE)								   \
-   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD				   \
-      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require () \
-      : MODE))
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 /* On SPARC, this is the size of MODE in words.  */
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-09-12 14:29:25.258529622 +0100
+++ gcc/config/sparc/sparc.c	2017-09-12 19:42:13.224027222 +0100
@@ -672,6 +672,7 @@  static void sparc_print_operand_address
 static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
 					   machine_mode,
 					   secondary_reload_info *);
+static machine_mode sparc_secondary_memory_needed_mode (machine_mode);
 static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
 static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
@@ -859,6 +860,8 @@  #define TARGET_PREFERRED_RELOAD_CLASS sp
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD sparc_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE sparc_secondary_memory_needed_mode
 
 #undef TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
@@ -13032,6 +13035,30 @@  sparc_secondary_reload (bool in_p, rtx x
   return NO_REGS;
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
+   because the movsi and movsf patterns don't handle r/f moves.
+   For v8 we copy the default definition.  */
+
+static machine_mode
+sparc_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (TARGET_ARCH64)
+    {
+      if (GET_MODE_BITSIZE (mode) < 32)
+	return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+      return mode;
+    }
+  else
+    {
+      if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+	return mode_for_size (BITS_PER_WORD,
+			      GET_MODE_CLASS (mode), 0).require ();
+      return mode;
+    }
+}
+
 /* Emit code to conditionally move either OPERANDS[2] or OPERANDS[3] into
    OPERANDS[0] in MODE.  OPERANDS[1] is the operator of the condition.  */
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-09-12 14:29:25.264529359 +0100
+++ gcc/system.h	2017-09-12 19:42:13.226875090 +0100
@@ -913,7 +913,7 @@  #define realloc xrealloc
 	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD			\
 	HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK		\
 	MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS	\
-	HARD_REGNO_NREGS
+	HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */