This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: 4.2 reload infrastructure to fix PR target/21623


Before deciding on how to best install an interim patch for 4.1, I would like
us to agree on the interface we are going to use for 4.2 - at least inasmuch as
it would matter for portability of code from the interim patch to the permanent
solution.
Is the attached patch OK for 4.2 once we get into phase 1?
The sh-elf specific part is included here not to be included in the review,
but to illustrate a possible use of the new interface, and to document what
I have exactly tested for sh-elf.
I have regression tested the code on i686-pc-linux-gnu native and X sh-elf;
the documentation change I've tested later with 'make doc' .
2005-10-06  J"orn Rennecke <joern.rennecke@st.com>

	* regclass.c (FORBIDDEN_INC_DEC_CLASSES): Replace 
	SECONDARY_INPUT_RELOAD_CLASS / SECONDARY_OUTPUT_RELOAD_CLASS test 
	with HAVE_SECONDARY_RELOAD test.
	(memory_move_secondary_cost, init_reg_autoinc): Remove
	SECONDARY_INPUT_RELOAD_CLASS / SECONDARY_OUTPUT_RELOAD_CLASS tests.
	Replace SECONDARY_{IN,OUT}PUT_RELOAD_CLASS use with
	secondary_reload_class call.
	(copy_cost): Likewise.
	* reload.c (push_secondary_reload): Use secondary_reload target hook.
	(secondary_reload_class): New function.
	(push_reload): Replace
	SECONDARY_INPUT_RELOAD_CLASS / SECONDARY_OUTPUT_RELOAD_CLASS test
	with HAVE_SECONDARY_RELOAD test.
	Replace SECONDARY_{IN,OUT}PUT_RELOAD_CLASS use with
	secondary_reload_class call.
	* reload.h (SECONDARY_INPUT_RELOAD_CLASS): Also define if not
	otherwise defined, and HAVE_SECONDARY_RELOADS is defined.
	(SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
	(secondary_reload_class): Declare.
	* reload1.c: Include target.h.
	(choose_reload_regs): Replace SECONDARY_INPUT_RELOAD_CLASS test with
	HAVE_SECONDARY_RELOAD test. Replace SECONDARY_INPUT_RELOAD_CLASS use
	with secondary_reload_class call.
	(emit_input_reload_insns): Likewise.  Use secondary_reload target hook.
	For (icode != CODE_FOR_nothing) case, check number of operands, and
	decode constraints.
	(emit_output_reload_insns): Replace SECONDARY_OUTPUT_RELOAD_CLASS use
        with secondary_reload_class call.
	* target-def.h (TARGET_SECONDARY_RELOAD): Provide default definition.
	(TARGET_INITIALIZER) Add TARGET_SECONDARY_RELOAD.
	* target.h (secondary_reload_info): New struct / typedef.
	(struct gcc_target): New member secondary_reload.
	* targhooks.c Include reload.h, optabs.h and recog.h.
	(default_secondary_reload): New function.
	* targhooks.h (default_secondary_reload): Declare.
	* doc/tm.texi: Document secondary_reload target hook.  Update
	description of SECONDARY_*RELOAD_CLASS and reload_{in,out}<mode>.
	* doc/md.texi: Likewise.

	* sh-protos.h (sh_secondary_reload): Declare.
	* sh.c (TARGET_SECONDARY_RELOAD): Override.
	(sh_secondary_reload): New function.
	* sh.h (SECONDARY_INOUT_RELOAD_CLASS): Don't define.
	(SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
	(SECONDARY_INPUT_RELOAD_CLASS): Likewise.
	(HAVE_SECONDARY_RELOADS): Define.
	* sh.md (reload_indf): Rename to:
	(reload_indf__frn).
	(reload_outdf): Rename to:
	(reload_outdf__RnFRm).
	(reload_insf): Rename to:
	(reload_insf__frn).
	(reload_insi): Rename to:
	(reload_insi__i_fpul).
	(reload_insi__r_fpul, reload_outsi__fpul_r): New expanders.

Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.206
diff -p -u -F^( -r1.206 regclass.c
--- regclass.c	25 Jun 2005 02:00:52 -0000	1.206
+++ regclass.c	6 Oct 2005 19:16:22 -0000
@@ -54,11 +54,9 @@ static void init_reg_autoinc (void);
    reloads, we are not allowed to use classes requiring secondary
    reloads for pseudos auto-incremented since reload can't handle it.  */
 
-#ifdef AUTO_INC_DEC
-#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
+#if defined(AUTO_INC_DEC) && defined(HAVE_SECONDARY_RELOADS)
 #define FORBIDDEN_INC_DEC_CLASSES
 #endif
-#endif
 
 /* Register tables used by many passes.  */
 
@@ -622,22 +620,7 @@ memory_move_secondary_cost (enum machine
   rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode];
 
 
-  if (in)
-    {
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-      altclass = SECONDARY_INPUT_RELOAD_CLASS (class, mode, mem);
-#else
-      altclass = NO_REGS;
-#endif
-    }
-  else
-    {
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-      altclass = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, mem);
-#else
-      altclass = NO_REGS;
-#endif
-    }
+  altclass = secondary_reload_class (in ? 1 : 0, class, mode, mem);
 
   if (altclass == NO_REGS)
     return 0;
@@ -1175,6 +1158,8 @@ init_reg_autoinc (void)
 		 m = (enum machine_mode) ((int) m + 1))
 	      if (HARD_REGNO_MODE_OK (j, m))
 		{
+		  enum reg_class base_class = MODE_BASE_REG_CLASS (VOIDmode);
+
 		  PUT_MODE (r, m);
 
 		  /* If a register is not directly suitable for an
@@ -1182,21 +1167,8 @@ init_reg_autoinc (void)
 		     requires secondary reloads, disallow its class from
 		     being used in such addresses.  */
 
-		  if ((0
-#ifdef SECONDARY_RELOAD_CLASS
-		       || (SECONDARY_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
-			   != NO_REGS)
-#else
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-		       || (SECONDARY_INPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
-			   != NO_REGS)
-#endif
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-		       || (SECONDARY_OUTPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
-			   != NO_REGS)
-#endif
-#endif
-		       )
+		  if ((secondary_reload_class (1, base_class, m, r)
+		       || secondary_reload_class (1, base_class, m, r))
 		      && ! auto_inc_dec_reg_p (r, m))
 		    forbidden_inc_dec_class[i] = 1;
 		}
@@ -1900,15 +1872,8 @@ copy_cost (rtx x, enum machine_mode mode
      cost is that to load the input into the intermediate register, then
      to copy them.  We use a special value of TO_P to avoid recursion.  */
 
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-  if (to_p == 1)
-    secondary_class = SECONDARY_INPUT_RELOAD_CLASS (class, mode, x);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-  if (! to_p)
-    secondary_class = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x);
-#endif
+  if (to_p == 1 || ! to_p)
+    secondary_class = secondary_reload_class (to_p, class, mode, x);
 
   if (secondary_class != NO_REGS)
     return (move_cost[mode][(int) secondary_class][(int) class]
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.275
diff -p -u -F^( -r1.275 reload.c
--- reload.c	5 Aug 2005 16:06:35 -0000	1.275
+++ reload.c	6 Oct 2005 19:16:25 -0000
@@ -301,6 +301,7 @@ push_secondary_reload (int in_p, rtx x, 
 		       enum insn_code *picode)
 {
   enum reg_class class = NO_REGS;
+  enum reg_class scratch_class;
   enum machine_mode mode = reload_mode;
   enum insn_code icode = CODE_FOR_nothing;
   enum reg_class t_class = NO_REGS;
@@ -308,6 +309,9 @@ push_secondary_reload (int in_p, rtx x, 
   enum insn_code t_icode = CODE_FOR_nothing;
   enum reload_type secondary_type;
   int s_reload, t_reload = -1;
+  const char *insn_constraint;
+  char insn_letter;
+  secondary_reload_info sri;
 
   if (type == RELOAD_FOR_INPUT_ADDRESS
       || type == RELOAD_FOR_OUTPUT_ADDRESS
@@ -339,31 +343,14 @@ push_secondary_reload (int in_p, rtx x, 
       && reg_equiv_mem[REGNO (x)] != 0)
     x = reg_equiv_mem[REGNO (x)];
 
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-  if (in_p)
-    class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-  if (! in_p)
-    class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
+  sri.icode = CODE_FOR_nothing;
+  class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+  icode = sri.icode;
 
   /* If we don't need any secondary registers, done.  */
-  if (class == NO_REGS)
+  if (class == NO_REGS && icode == CODE_FOR_nothing)
     return -1;
 
-  /* Get a possible insn to use.  If the predicate doesn't accept X, don't
-     use the insn.  */
-
-  icode = (in_p ? reload_in_optab[(int) reload_mode]
-	   : reload_out_optab[(int) reload_mode]);
-
-  if (icode != CODE_FOR_nothing
-      && insn_data[(int) icode].operand[in_p].predicate
-      && (! (insn_data[(int) icode].operand[in_p].predicate) (x, reload_mode)))
-    icode = CODE_FOR_nothing;
-
   /* If we will be using an insn, see if it can directly handle the reload
      register we will be using.  If it can, the secondary reload is for a
      scratch register.  If it can't, we will use the secondary reload for
@@ -379,40 +366,60 @@ push_secondary_reload (int in_p, rtx x, 
 
       enum reg_class insn_class;
 
-      if (insn_data[(int) icode].operand[!in_p].constraint[0] == 0)
+      /* ??? It would be useful to be able to handle only two, or more than
+	 three, operands, but for now we can only handle the case of having
+	 exactly three: output, input and one temp/scratch.  */
+      gcc_assert (insn_data[(int) icode].n_operands == 3);
+
+      insn_constraint = insn_data[(int) icode].operand[!in_p].constraint;
+      if (!*insn_constraint)
 	insn_class = ALL_REGS;
       else
 	{
-	  const char *insn_constraint
-	    = &insn_data[(int) icode].operand[!in_p].constraint[in_p];
-	  char insn_letter = *insn_constraint;
+	  if (in_p)
+	    {
+	      gcc_assert (*insn_constraint == '=');
+	      insn_constraint++;
+	    }
+	  insn_letter = *insn_constraint;
 	  insn_class
 	    = (insn_letter == 'r' ? GENERAL_REGS
 	       : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
 					    insn_constraint));
 
           gcc_assert (insn_class != NO_REGS);
-	  gcc_assert (!in_p
-		      || insn_data[(int) icode].operand[!in_p].constraint[0]
-			 == '=');
 	}
 
-      /* The scratch register's constraint must start with "=&".  */
-      gcc_assert (insn_data[(int) icode].operand[2].constraint[0] == '='
-		  && insn_data[(int) icode].operand[2].constraint[1] == '&');
+      insn_constraint = insn_data[(int) icode].operand[2].constraint;
+      gcc_assert (*insn_constraint == '=');
+      insn_constraint++;
+      if (*insn_constraint == '&')
+	insn_constraint++;
+      insn_letter = *insn_constraint;
+      scratch_class = (insn_letter == 'r' ? GENERAL_REGS
+		       : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+						    insn_constraint));
 
-      if (reg_class_subset_p (reload_class, insn_class))
-	mode = insn_data[(int) icode].operand[2].mode;
+      /* ???  If insn_data[(int) icode].operand[!in_p].constraint denotes a
+	 register class, and X doesn't match that class, we should recurse.  */
+
+      if (class == NO_REGS && reg_class_subset_p (reload_class, insn_class))
+	{
+	  class = scratch_class;
+	  mode = insn_data[(int) icode].operand[2].mode;
+	}
       else
 	{
-	  const char *t_constraint
-	    = &insn_data[(int) icode].operand[2].constraint[2];
-	  char t_letter = *t_constraint;
-	  class = insn_class;
+	  if (class == NO_REGS)
+	    class = insn_class;
+	  else
+	    {
+	      /* ??? We should push another reload if the classes
+		 don't match.  */
+	      gcc_assert (reg_class_subset_p (class, insn_class));
+	    }
 	  t_mode = insn_data[(int) icode].operand[2].mode;
-	  t_class = (t_letter == 'r' ? GENERAL_REGS
-		     : REG_CLASS_FROM_CONSTRAINT ((unsigned char) t_letter,
-						  t_constraint));
+	  t_class = scratch_class;
 	  t_icode = icode;
 	  icode = CODE_FOR_nothing;
 	}
@@ -581,6 +588,35 @@ push_secondary_reload (int in_p, rtx x, 
   *picode = icode;
   return s_reload;
 }
+
+enum reg_class
+secondary_reload_class (int in_p, enum reg_class class,
+			enum machine_mode mode, rtx x)
+{
+  enum insn_code icode;
+  const char *insn_constraint;
+  char insn_letter;
+  secondary_reload_info sri;
+
+  sri.icode = CODE_FOR_nothing;
+  class = targetm.secondary_reload (in_p, x, class, mode, &sri);
+  icode = sri.icode;
+
+  if (icode == CODE_FOR_nothing || class != NO_REGS)
+    return class;
+
+  gcc_assert (insn_data[(int) icode].n_operands >= 3);
+  insn_constraint = insn_data[(int) icode].operand[2].constraint;
+  gcc_assert (*insn_constraint == '=');
+  insn_constraint++;
+  if (*insn_constraint == '&')
+    insn_constraint++;
+  insn_letter = *insn_constraint;
+  if (insn_letter == 'r')
+    return GENERAL_REGS;
+  return REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+				    insn_constraint);
+}
 #endif /* HAVE_SECONDARY_RELOADS */
 
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -1058,11 +1094,10 @@ push_reload (rtx in, rtx out, rtx *inloc
 		       != (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
 						[GET_MODE (SUBREG_REG (in))]))
 		  || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-	  || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
-	      && (SECONDARY_INPUT_RELOAD_CLASS (class,
-						GET_MODE (SUBREG_REG (in)),
-						SUBREG_REG (in))
+#ifdef HAVE_SECONDARY_RELOADS
+	  || (secondary_reload_class (1, class, inmode, in) != NO_REGS
+	      && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
+					  SUBREG_REG (in))
 		  == NO_REGS))
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1154,11 +1189,10 @@ push_reload (rtx in, rtx out, rtx *inloc
 		       != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
 						[GET_MODE (SUBREG_REG (out))]))
 		  || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-	  || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
-	      && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
-						 GET_MODE (SUBREG_REG (out)),
-						 SUBREG_REG (out))
+#ifdef HAVE_SECONDARY_RELOADS
+	  || (secondary_reload_class (0, class, outmode, out) != NO_REGS
+	      && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
+					  SUBREG_REG (out))
 		  == NO_REGS))
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1310,14 +1344,14 @@ push_reload (rtx in, rtx out, rtx *inloc
 	 and IN or CLASS and OUT.  Get the icode and push any required reloads
 	 needed for each of them if so.  */
 
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
       if (in != 0)
 	secondary_in_reload
 	  = push_secondary_reload (1, in, opnum, optional, class, inmode, type,
 				   &secondary_in_icode);
 #endif
 
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
       if (out != 0 && GET_CODE (out) != SCRATCH)
 	secondary_out_reload
 	  = push_secondary_reload (0, out, opnum, optional, class, outmode,
Index: reload.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.h,v
retrieving revision 1.54
diff -p -u -F^( -r1.54 reload.h
--- reload.h	25 Jun 2005 02:00:54 -0000	1.54
+++ reload.h	6 Oct 2005 19:16:25 -0000
@@ -28,6 +28,13 @@ Software Foundation, 51 Franklin Street,
   SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
   SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
+#elif defined(HAVE_SECONDARY_RELOADS)
+#ifndef SECONDARY_INPUT_RELOAD_CLASS
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) NO_REGS
+#endif
+#ifndef SECONDARY_OUTPUT_RELOAD_CLASS
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) NO_REGS
+#endif
 #endif
 
 /* If either macro is defined, show that we need secondary reloads.  */
@@ -252,6 +259,9 @@ extern void compute_use_by_pseudos (HARD
 
 /* Functions from reload.c:  */
 
+extern enum reg_class secondary_reload_class (int, enum reg_class,
+					      enum machine_mode, rtx);
+
 /* Return a memory location that will be used to copy X in mode MODE.
    If we haven't already made a location for this mode in this insn,
    call find_reloads_address on the location being returned.  */
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.482
diff -p -u -F^( -r1.482 reload1.c
--- reload1.c	7 Sep 2005 07:52:48 -0000	1.482
+++ reload1.c	6 Oct 2005 19:16:28 -0000
@@ -43,6 +43,7 @@ Software Foundation, 51 Franklin Street,
 #include "toplev.h"
 #include "except.h"
 #include "tree.h"
+#include "target.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -5496,9 +5497,9 @@ choose_reload_regs (struct insn_chain *c
 			     enough.  */
 			  || ((REGISTER_MOVE_COST (mode, last_class, class)
 			       < MEMORY_MOVE_COST (mode, class, 1))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-			      && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
-								last_reg)
+#ifdef HAVE_SECONDARY_RELOADS
+			      && (secondary_reload_class (1, class, mode,
+							  last_reg)
 				  == NO_REGS)
 #endif
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -6209,7 +6210,7 @@ emit_input_reload_insns (struct insn_cha
   if (mode == VOIDmode)
     mode = rl->inmode;
 
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
   /* If we need a secondary register for this operation, see if
      the value is already in a register in that class.  Don't
      do this if the secondary register will be used as a scratch
@@ -6259,9 +6260,8 @@ emit_input_reload_insns (struct insn_cha
 	       && (REGISTER_MOVE_COST (mode, REGNO_REG_CLASS (regno),
 				       rl->class)
 		   >= MEMORY_MOVE_COST (mode, rl->class, 1)))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
-	      || (SECONDARY_INPUT_RELOAD_CLASS (rl->class,
-						mode, oldequiv)
+#ifdef HAVE_SECONDARY_RELOADS
+	      || (secondary_reload_class (1, rl->class, mode, oldequiv)
 		  != NO_REGS)
 #endif
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -6449,7 +6449,7 @@ emit_input_reload_insns (struct insn_cha
 
   /* We can't do that, so output an insn to load RELOADREG.  */
 
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
   /* If we have a secondary reload, pick up the secondary register
      and icode, if any.  If OLDEQUIV and OLD are different or
      if this is an in-out reload, recompute whether or not we
@@ -6521,24 +6521,52 @@ emit_input_reload_insns (struct insn_cha
       if ((old != oldequiv && ! rtx_equal_p (old, oldequiv))
 	  || (rl->in != 0 && rl->out != 0))
 	{
-	  enum reg_class new_class
-	    = SECONDARY_INPUT_RELOAD_CLASS (rl->class,
-					    mode, real_oldequiv);
+	  secondary_reload_info sri;
+	  enum reg_class new_class;
 
-	  if (new_class == NO_REGS)
+	  sri.icode = CODE_FOR_nothing;
+	  new_class = targetm.secondary_reload (1, real_oldequiv, rl->class,
+						mode, &sri);
+
+	  if (new_class == NO_REGS && sri.icode == CODE_FOR_nothing)
 	    second_reload_reg = 0;
 	  else
 	    {
-	      enum insn_code new_icode;
+	      enum insn_code new_icode = sri.icode;
 	      enum machine_mode new_mode;
+	      const char *constraint;
+	      char letter;
+
+	      /* ??? The old code incorrectly assumed that the
+		SECONDARY_RELOAD_CLASS will always return the scratch
+		register, and that there was no problem with matching the
+		constraint of operand[0].  */
+	      if (insn_data[(int) icode].n_operands != 3)
+		goto failure;
+	      constraint = &insn_data[(int) new_icode].operand[0].constraint[1];
+	      if (*constraint == '&')
+		constraint++;
+	      new_class = (letter == 'r' ? GENERAL_REGS
+			   : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
+							constraint));
+	      if (! TEST_HARD_REG_BIT (reg_class_contents[(int) new_class],
+				       REGNO (rl->reg_rtx)))
+	      constraint = &insn_data[(int) new_icode].operand[2].constraint[1];
+	      if (*constraint == '&')
+		constraint++;
+	      letter = *constraint;
+	      new_class = (letter == 'r' ? GENERAL_REGS
+			   : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
+							constraint));
 
 	      if (! TEST_HARD_REG_BIT (reg_class_contents[(int) new_class],
 				       REGNO (second_reload_reg)))
+	      failure:
 		oldequiv = old, real_oldequiv = real_old;
 	      else
 		{
-		  new_icode = reload_in_optab[(int) mode];
 		  if (new_icode != CODE_FOR_nothing
+			/* ??? md.texi says this does not exist.  */
 		      && ((insn_data[(int) new_icode].operand[0].predicate
 			   && ! ((*insn_data[(int) new_icode].operand[0].predicate)
 				 (reloadreg, mode)))
@@ -6554,6 +6582,8 @@ emit_input_reload_insns (struct insn_cha
 
 		  if (GET_MODE (second_reload_reg) != new_mode)
 		    {
+		      /* ??? should check HARD_REGNO_NREGS if NEW_MODE will
+			 need more hard registers than we have.  */
 		      if (!HARD_REGNO_MODE_OK (REGNO (second_reload_reg),
 					       new_mode))
 			oldequiv = old, real_oldequiv = real_old;
@@ -6682,7 +6712,7 @@ emit_output_reload_insns (struct insn_ch
   if (GET_MODE (reloadreg) != mode)
     reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
 
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
 
   /* If we need two reload regs, set RELOADREG to the intermediate
      one, since it will be stored into OLD.  We might need a secondary
@@ -6696,9 +6726,7 @@ emit_output_reload_insns (struct insn_ch
 	  && reg_equiv_mem[REGNO (old)] != 0)
 	real_old = reg_equiv_mem[REGNO (old)];
 
-      if ((SECONDARY_OUTPUT_RELOAD_CLASS (rl->class,
-					  mode, real_old)
-	   != NO_REGS))
+      if (secondary_reload_class (0, rl->class, mode, real_old) != NO_REGS)
 	{
 	  rtx second_reloadreg = reloadreg;
 	  reloadreg = rld[rl->secondary_out_reload].reg_rtx;
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.133
diff -p -u -F^( -r1.133 target-def.h
--- target-def.h	24 Aug 2005 07:13:07 -0000	1.133
+++ target-def.h	6 Oct 2005 19:16:28 -0000
@@ -474,6 +474,10 @@ Foundation, 51 Franklin Street, Fifth Fl
 #define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 0
 #endif
 
+#ifndef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD default_secondary_reload
+#endif
+
 
 /* C++ specific.  */
 #ifndef TARGET_CXX_GUARD_TYPE
@@ -597,6 +601,7 @@ Foundation, 51 Franklin Street, Fifth Fl
   TARGET_INVALID_CONVERSION,			\
   TARGET_INVALID_UNARY_OP,			\
   TARGET_INVALID_BINARY_OP,			\
+  TARGET_SECONDARY_RELOAD,			\
   TARGET_CXX,					\
   TARGET_UNWIND_TABLES_DEFAULT,			\
   TARGET_HAVE_NAMED_SECTIONS,			\
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.144
diff -p -u -F^( -r1.144 target.h
--- target.h	14 Jul 2005 07:39:55 -0000	1.144
+++ target.h	6 Oct 2005 19:16:28 -0000
@@ -51,6 +51,12 @@ Foundation, 51 Franklin Street, Fifth Fl
 #include "insn-modes.h"
 
 struct stdarg_info;
+/* The struct used by the secondary_reload target hook.  */
+typedef struct secondary_reload_info
+{
+  enum machine_mode icode;
+} secondary_reload_info;
+
 
 struct gcc_target
 {
@@ -622,6 +628,11 @@ struct gcc_target
      is not permitted on TYPE1 and TYPE2, NULL otherwise.  */
   const char *(*invalid_binary_op) (int op, tree type1, tree type2);
 
+  /* Return the class for a secondary reload, and fill in extra information.  */
+  enum reg_class (*secondary_reload) (int, rtx, enum reg_class,
+				      enum machine_mode,
+				      struct secondary_reload_info *);
+
   /* Functions specific to the C++ frontend.  */
   struct cxx {
     /* Return the integer type used for guard variables.  */
Index: targhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.c,v
retrieving revision 2.46
diff -p -u -F^( -r2.46 targhooks.c
--- targhooks.c	14 Jul 2005 07:39:55 -0000	2.46
+++ targhooks.c	6 Oct 2005 19:16:28 -0000
@@ -62,6 +62,9 @@ Software Foundation, 51 Franklin Street,
 #include "tm_p.h"
 #include "target-def.h"
 #include "ggc.h"
+#include "reload.h"
+#include "optabs.h"
+#include "recog.h"
 
 
 void
@@ -439,4 +442,78 @@ default_function_value (tree ret_type AT
 #endif
 }
 
+enum reg_class
+default_secondary_reload (int in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
+			  enum reg_class reload_class ATTRIBUTE_UNUSED,
+			  enum machine_mode reload_mode ATTRIBUTE_UNUSED,
+			  secondary_reload_info *sri)
+{
+  enum reg_class class = NO_REGS;
+
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+  if (in_p)
+    class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
+#endif
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+  if (! in_p)
+    class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
+#endif
+  if (class != NO_REGS)
+    {
+      enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
+			      : reload_out_optab[(int) reload_mode]);
+
+      if (icode != CODE_FOR_nothing
+	  && insn_data[(int) icode].operand[in_p].predicate
+	  && ! insn_data[(int) icode].operand[in_p].predicate (x, reload_mode))
+	icode = CODE_FOR_nothing;
+      else if (icode != CODE_FOR_nothing)
+	{
+	  const char *insn_constraint;
+	  char insn_letter;
+	  enum reg_class insn_class, scratch_class;
+
+	  gcc_assert (insn_data[(int) icode].n_operands == 3);
+	  sri->icode = icode;
+	  insn_constraint = insn_data[(int) icode].operand[!in_p].constraint;
+	  if (!*insn_constraint)
+	    insn_class = ALL_REGS;
+	  else
+	    {
+	      if (in_p)
+		{
+		  gcc_assert (*insn_constraint == '=');
+		  insn_constraint++;
+		}
+	      insn_letter = *insn_constraint;
+	      insn_class
+		= (insn_letter == 'r' ? GENERAL_REGS
+		   : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+						insn_constraint));
+	      gcc_assert (insn_class != NO_REGS);
+	    }
+
+	  insn_constraint = insn_data[(int) icode].operand[2].constraint;
+	  /* The scratch register's constraint must start with "=&".  */
+	  gcc_assert (insn_constraint[0] == '=' && insn_constraint[1] == '&');
+	  insn_constraint += 2;
+	  insn_letter = *insn_constraint;
+	  scratch_class
+	    = (insn_letter == 'r' ? GENERAL_REGS
+	       : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+					    insn_constraint));
+
+	  if (reg_class_subset_p (reload_class, insn_class))
+	    {
+	      gcc_assert (scratch_class == class);
+	      class = NO_REGS;
+	    }
+	  else
+	    class = insn_class;
+
+        }
+    }
+  return class;
+}
+
 #include "gt-targhooks.h"
Index: targhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.h,v
retrieving revision 2.33
diff -p -u -F^( -r2.33 targhooks.h
--- targhooks.h	14 Jul 2005 07:39:56 -0000	2.33
+++ targhooks.h	6 Oct 2005 19:16:28 -0000
@@ -68,4 +68,7 @@ extern const char *hook_invalid_arg_for_
   (tree, tree, tree);
 extern bool hook_bool_rtx_commutative_p (rtx, int);
 extern rtx default_function_value (tree, tree, bool);
+extern enum reg_class default_secondary_reload (int, rtx, enum reg_class,
+						enum machine_mode,
+						struct secondary_reload_info *);
 
Index: config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.65
diff -p -u -F^( -r1.65 sh-protos.h
--- config/sh/sh-protos.h	29 Jun 2005 01:24:25 -0000	1.65
+++ config/sh/sh-protos.h	6 Oct 2005 19:16:30 -0000
@@ -165,6 +165,10 @@ extern int shmedia_cleanup_truncate (rtx
 
 extern int sh_contains_memref_p (rtx);
 extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
+struct secondary_reload_info;
+extern enum reg_class sh_secondary_reload (int, rtx, enum reg_class,
+					   enum machine_mode,
+					   struct secondary_reload_info *);
 
 #endif /* ! GCC_SH_PROTOS_H */
 
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.347
diff -p -u -F^( -r1.347 sh.c
--- config/sh/sh.c	5 Sep 2005 12:45:22 -0000	1.347
+++ config/sh/sh.c	6 Oct 2005 19:16:33 -0000
@@ -500,6 +500,9 @@ static int hard_regs_intersect_p (HARD_R
 #define TARGET_ADJUST_UNROLL_MAX sh_adjust_unroll_max
 #endif
 
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD sh_secondary_reload
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -10619,6 +10622,107 @@ shmedia_prepare_call_address (rtx fnaddr
   return fnaddr;
 }
 
+enum reg_class
+sh_secondary_reload (int in_p, rtx x, enum reg_class class,
+		     enum machine_mode mode, secondary_reload_info *sri)
+{
+  if (in_p)
+    {
+      if (REGCLASS_HAS_FP_REG (class)
+	  && ! TARGET_SHMEDIA
+	  && immediate_operand ((x), mode)
+	  && ! ((fp_zero_operand (x) || fp_one_operand (x))
+		&& mode == SFmode && fldi_ok ()))
+	switch (mode)
+	  {
+	  case SFmode:
+	    sri->icode = CODE_FOR_reload_insf__frn;
+	    return NO_REGS;
+	  case DFmode:
+	    sri->icode = CODE_FOR_reload_indf__frn;
+	    return NO_REGS;
+	  case SImode:
+	    sri->icode = CODE_FOR_reload_insi__i_fpul;
+	    return FPUL_REGS;
+	  default:
+	    abort ();
+	  }
+      if (class == FPUL_REGS
+          && ((GET_CODE (x) == REG
+               && (REGNO (x) == MACL_REG || REGNO (x) == MACH_REG
+                   || REGNO (x) == T_REG))
+              || GET_CODE (x) == PLUS))
+        return GENERAL_REGS;
+      if (class == FPUL_REGS && immediate_operand (x, mode))
+	{
+	  if (GET_CODE (x) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (x)))
+	    return GENERAL_REGS;
+	  sri->icode = CODE_FOR_reload_insi__i_fpul;
+	  return NO_REGS;
+	}
+      if (class == FPSCR_REGS
+          && ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+              || (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
+        return GENERAL_REGS;
+      if (REGCLASS_HAS_FP_REG (class)
+          && TARGET_SHMEDIA
+          && immediate_operand (x, mode)
+          && x != CONST0_RTX (GET_MODE (x))
+          && GET_MODE (x) != V4SFmode)
+        return GENERAL_REGS;
+      if ((mode == QImode || mode == HImode)
+          && TARGET_SHMEDIA && inqhi_operand (x, mode))
+	{
+	  sri->icode = ((mode == QImode)
+			? CODE_FOR_reload_inqi : CODE_FOR_reload_inhi);
+	  return NO_REGS;
+	}
+      if (TARGET_SHMEDIA && class == GENERAL_REGS
+          && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+        return TARGET_REGS;
+    } /* end of input-only processing.  */
+
+  if (((REGCLASS_HAS_FP_REG (class)
+	&& (GET_CODE (x) == REG
+	    && (GENERAL_OR_AP_REGISTER_P (REGNO (x))
+		|| (FP_REGISTER_P (REGNO (x)) && mode == SImode
+		    && TARGET_FMOVD))))
+       || (REGCLASS_HAS_GENERAL_REG (class)
+	   && GET_CODE (x) == REG
+	   && FP_REGISTER_P (REGNO (x))))
+      && ! TARGET_SHMEDIA
+      && (mode == SFmode || mode == SImode))
+    return FPUL_REGS;
+  if ((class == FPUL_REGS
+       || (REGCLASS_HAS_FP_REG (class)
+           && ! TARGET_SHMEDIA && mode == SImode))
+      && (GET_CODE (x) == MEM
+          || (GET_CODE (x) == REG
+              && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+                  || REGNO (x) == T_REG
+                  || system_reg_operand (x, VOIDmode)))))
+    {
+      if (class == FPUL_REGS)
+	return GENERAL_REGS;
+      sri->icode = (in_p ? CODE_FOR_reload_insi__r_fpul
+		    : CODE_FOR_reload_outsi__fpul_r);
+      return FPUL_REGS;
+    }
+  if ((class == TARGET_REGS
+       || (TARGET_SHMEDIA && class == SIBCALL_REGS))
+      && !EXTRA_CONSTRAINT_Csy (x)
+      && (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
+    return GENERAL_REGS;
+  if ((class == MAC_REGS || class == PR_REGS)
+      && GET_CODE (x) == REG && ! GENERAL_REGISTER_P (REGNO (x))
+      && class != REGNO_REG_CLASS (REGNO (x)))
+    return GENERAL_REGS;
+  if (class != GENERAL_REGS && GET_CODE (x) == REG
+      && TARGET_REGISTER_P (REGNO (x)))
+    return GENERAL_REGS;
+  return NO_REGS;
+}
+
 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
 
 /* This defines the storage for the variable part of a -mboard= option.
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.277
diff -p -u -F^( -r1.277 sh.h
--- config/sh/sh.h	12 Sep 2005 13:23:10 -0000	1.277
+++ config/sh/sh.h	6 Oct 2005 19:16:36 -0000
@@ -1594,6 +1594,7 @@ ((C) == 'G' ? (fp_zero_operand (VALUE) &
    ? GENERAL_REGS \
    : (CLASS)) \
 
+#if 0
 #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
   ((((REGCLASS_HAS_FP_REG (CLASS) 					\
       && (GET_CODE (X) == REG						\
@@ -1665,6 +1666,9 @@ ((C) == 'G' ? (fp_zero_operand (VALUE) &
       && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X)))		\
    ? TARGET_REGS							\
    : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
+#else
+#define HAVE_SECONDARY_RELOADS
+#endif
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
Index: config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.200
diff -p -u -F^( -r1.200 sh.md
--- config/sh/sh.md	13 Sep 2005 22:03:18 -0000	1.200
+++ config/sh/sh.md	6 Oct 2005 19:16:39 -0000
@@ -5845,15 +5845,15 @@ (define_split
 	      (clobber (scratch:SI))])]
   "")
 
-(define_expand "reload_indf"
-  [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
+(define_expand "reload_indf__frn"
+  [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
 		   (match_operand:DF 1 "immediate_operand" "FQ"))
 	      (use (reg:PSI FPSCR_REG))
 	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
   "TARGET_SH1"
   "")
 
-(define_expand "reload_outdf"
+(define_expand "reload_outdf__RnFRm"
   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
 		   (match_operand:DF 1 "register_operand" "af,r"))
 	      (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
@@ -6475,7 +6475,7 @@ (define_insn "mov_nop"
   [(set_attr "length" "0")
    (set_attr "type" "nil")])
 
-(define_expand "reload_insf"
+(define_expand "reload_insf__frn"
   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
 		   (match_operand:SF 1 "immediate_operand" "FQ"))
 	      (use (reg:PSI FPSCR_REG))
@@ -6483,13 +6483,25 @@ (define_expand "reload_insf"
   "TARGET_SH1"
   "")
 
-(define_expand "reload_insi"
+(define_expand "reload_insi__i_fpul"
   [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
 		   (match_operand:SI 1 "immediate_operand" "i"))
 	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
   "TARGET_SH1"
   "")
 
+(define_expand "reload_insi__r_fpul"
+  [(set (match_operand:SI 2 "" "=r") (match_operand:SI 1 "" ""))
+   (set (match_operand:SI 0 "" "=y") (match_dup 2))]
+  "TARGET_SH1"
+  "")
+
+(define_expand "reload_outsi__fpul_r"
+  [(set (match_operand:SI 2 "" "=r") (match_operand:SI 1 "" "y"))
+   (set (match_operand:SI 0 "" "") (match_dup 2))]
+  "TARGET_SH1"
+  "")
+
 (define_expand "ptabs"
   [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
   "TARGET_SHMEDIA"
Index: doc/md.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/md.texi,v
retrieving revision 1.146
diff -p -u -r1.146 md.texi
--- doc/md.texi	22 Aug 2005 16:12:13 -0000	1.146
+++ doc/md.texi	7 Oct 2005 20:33:38 -0000
@@ -2917,10 +2917,7 @@ If a scratch register is required to mov
 it can be allocated using @code{gen_reg_rtx} prior to life analysis.
 
 If there are cases which need scratch registers during or after reload,
-you must define @code{SECONDARY_INPUT_RELOAD_CLASS} and/or
-@code{SECONDARY_OUTPUT_RELOAD_CLASS} to detect them, and provide
-patterns @samp{reload_in@var{m}} or @samp{reload_out@var{m}} to handle
-them.  @xref{Register Classes}.
+you must provide an appropriate secondary_reload target hook.
 
 @findex no_new_pseudos
 The global variable @code{no_new_pseudos} can be used to determine if it
@@ -2950,6 +2947,9 @@ reload into a floating point register.
 @cindex @code{reload_out} instruction pattern
 @item @samp{reload_in@var{m}}
 @itemx @samp{reload_out@var{m}}
+These named patterns have been obsoleted by the target hook
+@code{secondary_reload}.
+
 Like @samp{mov@var{m}}, but used when a scratch register is required to
 move between operand 0 and operand 1.  Operand 2 describes the scratch
 register.  See the discussion of the @code{SECONDARY_RELOAD_CLASS}
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.446
diff -p -u -r1.446 tm.texi
--- doc/tm.texi	19 Aug 2005 21:16:20 -0000	1.446
+++ doc/tm.texi	7 Oct 2005 20:33:43 -0000
@@ -2409,9 +2409,7 @@ Don't define this macro unless the targe
 require the macro to do something nontrivial.
 @end defmac
 
-@defmac SECONDARY_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
-@defmacx SECONDARY_INPUT_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
-@defmacx SECONDARY_OUTPUT_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
+@deftypefn {Target Hook} enum reg_class TARGET_SECONDARY_RELOAD (int @var{in_p}, rtx @var{x}, enum reg_class @var{reload_class}, enum machine_mode @var{reload_mode}, secondary_reload_info *@var{sri})
 Many machines have some registers that cannot be copied directly to or
 from memory or even from other types of registers.  An example is the
 @samp{MQ} register, which on most machines, can only be copied to or
@@ -2422,7 +2420,59 @@ and those with certain symbolic address 
 PIC)@.  In some cases, both an intermediate and a scratch register are
 required.
 
-You should define these macros to indicate to the reload phase that it may
+For input reloads, this target hook is called with nonzero @var{in_p},
+and @var{x} is an rtx that needs to be copied to a register in of class
+@var{reload_class} in @var{reload_mode}.  For output reloads, this target
+hook is called with zero @var{in_p}, and a register of class @var{reload_mode}
+needs to be copied to rtx @var{x} in @var{reload_mode}.
+
+If an intermediate register is needed, return the largest register class all
+of whose registers can be used as an intermediate register.  Otherwise,
+return NO_REGS.
+
+If you need a scratch register, you should assign the instruction code of
+a suitable pattern to @var{sri->icode}.  Operand 0 of this pattern should
+be the input, and operand 1 the output.  Operands from operand 2 onward
+are for scratch registers.
+Currently, only a single scratch operand is supported by the implementation
+of this interface, although it is planned to support multiple scratch
+operands, or having no scratch operand at all.
+
+Define constraints for the reload register and scratch register that
+contain a single register class.  For input reloads, the reload register
+is matched against the constraint of operand 0, for output registers,
+against the iconstraint of operand 1.  If the hook returned NO_REGS, then
+the original reload register (whose class is @var{reload_class}) is matched
+against that constraint; otherwise, the intermediate reload register of the
+class specified by the return value of the hook is matched against that
+constraint.  The the reload register matches, no further intermediate
+reister is required; if not, another intermediate register of the class
+specified by the constraint is allocated.   However, the current
+implementation only supports one temporary register, i.e. the compiler
+will currently abort if the returned class is not NO_REGS but doesn't
+match its constraint.
+
+@var{x} might be a pseudo-register or a @code{subreg} of a
+pseudo-register, which could either be in a hard register or in memory.
+Use @code{true_regnum} to find out; it will return @minus{}1 if the pseudo is
+in memory and the hard register number if it is in a register.
+
+Scratch operands in memory (constraint @code{"=m"} / @code{"=&m"}) are
+currently not supported.  For the time being, you will have to continue
+to use @code{SECONDARY_MEMORY_NEEDED} for that purpose.
+
+In order to compile in the secondary reload handling code, you also have to
+define @code{HAVE_SECONDARY_RELOADS}.
+@end deftypefn
+
+@defmac SECONDARY_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
+@defmacx SECONDARY_INPUT_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
+@defmacx SECONDARY_OUTPUT_RELOAD_CLASS (@var{class}, @var{mode}, @var{x})
+These macros are obsolete, new ports should use the target hook 
+@code{TARGET_SECONDARY_RELOAD} instead.
+
+You were supposed to define these macros to indicate to the reload phase
+that it may
 need to allocate at least one register for a reload in addition to the
 register to contain the data.  Specifically, if copying @var{x} to a
 register @var{class} in @var{mode} requires an intermediate register,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]