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]

Re: RFA: reload infrastructure to fix PR target/21623


Ian Lance Taylor wrote:




Seems like there must be some way to make this work. Why can't we just also return a mode, for example?

We could, but that's more work overall, when you consider all the ports that would have
to return two values.


The existing code can locate
the pattern using only the mode. I'm sure I'm missing something
obvious, but let's not get too hung up on making existing targets work
with the new mechanism.


Darn. I think I've already implemented this. Should I break it? ;-)

If I'd followed everything, this isn't something we expect people to

actually write, yes? Instead of using a name, can we just provide a
table indexed by register class?


Indee. I've found that we actually need only a number. And for actual patterns, the temp/scratch
register class is now indicated by operand 2.


I haven't yet implemented additional operands or push_secondary_reload recursion, but
exact control which reload pattern is used is already a big step.


I've attached my current work in progress. It's still missing some documentation,
and in the SH port I should probably remove SEONDARY_*RELOAD_CLASS
definitions and remove the SHmedia reloadin<mode> patterns, but at least it seems
to be happy building newlib now.
? config/sh/.sh.c.swp
? config/sh/.sh.h.swo
? config/sh/.sh.h.swp
Index: gencodes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gencodes.c,v
retrieving revision 1.51
diff -p -u -r1.51 gencodes.c
--- gencodes.c	25 Jun 2005 02:00:13 -0000	1.51
+++ gencodes.c	30 Sep 2005 21:25:33 -0000
@@ -52,6 +52,8 @@ int
 main (int argc, char **argv)
 {
   rtx desc;
+  int i;
+  const char * reg_class_names[] = REG_CLASS_NAMES;
 
   progname = "gencodes";
 
@@ -86,7 +88,11 @@ enum insn_code {");
 	gen_insn (desc, insn_code_number);
     }
 
-  puts ("  CODE_FOR_nothing\n\
+  puts ("  CODE_FOR_nothing,");
+  for (i = 0; i < N_REG_CLASSES; i++)
+    printf ("  CODE_FOR_reload__%s,\n", reg_class_names[i]);
+
+  puts ("  CODE_FOR_reload__end\n\
 };\n\
 \n\
 #endif /* GCC_INSN_CODES_H */");
Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.206
diff -p -u -r1.206 regclass.c
--- regclass.c	25 Jun 2005 02:00:52 -0000	1.206
+++ regclass.c	30 Sep 2005 21:25:33 -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 -r1.275 reload.c
--- reload.c	5 Aug 2005 16:06:35 -0000	1.275
+++ reload.c	30 Sep 2005 21:25:34 -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,8 @@ 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;
 
   if (type == RELOAD_FOR_INPUT_ADDRESS
       || type == RELOAD_FOR_OUTPUT_ADDRESS
@@ -339,30 +342,58 @@ 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
+  icode = targetm.reload_icode (in_p, x, reload_class, reload_mode);
 
   /* If we don't need any secondary registers, done.  */
-  if (class == NO_REGS)
+  if (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 (icode > CODE_FOR_nothing)
+    {
+      scratch_class = icode - CODE_FOR_reload__NO_REGS + NO_REGS;
+      icode = CODE_FOR_nothing;
+    }
+  else
+    {
+      /* It would be useful to be able to handle more operands, but for now
+	 it must be exactly three: output, input and one temp/scratch.  */
+      gcc_assert (insn_data[(int) icode].n_operands == 3);
+      insn_constraint = insn_data[(int) icode].operand[2].constraint;
+      gcc_assert (*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));
+    }
+  class = scratch_class;
+
+  /* Backward compatibility: look for reload_{in,out}<mode> pattern.  */
+  if (icode == CODE_FOR_nothing)
+    {
+      /* 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;
+      else if (icode != CODE_FOR_nothing)
+	{
+	  insn_constraint = insn_data[(int) icode].operand[2].constraint;
+	  /* The scratch register's constraint must start with "=&".  */
+	  gcc_assert (*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 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
@@ -379,40 +410,30 @@ push_secondary_reload (int in_p, rtx x, 
 
       enum reg_class insn_class;
 
-      if (insn_data[(int) icode].operand[!in_p].constraint[0] == 0)
+      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_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] == '&');
 
       if (reg_class_subset_p (reload_class, insn_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;
 	  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 +602,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;
+
+  icode = targetm.reload_icode (in_p, x, class, mode);
+
+  /* If we don't need any secondary registers, done.  */
+  if (icode == CODE_FOR_nothing)
+    return NO_REGS;
+
+  if (icode > CODE_FOR_nothing)
+    return icode - CODE_FOR_reload__NO_REGS + NO_REGS;
+
+  gcc_assert (insn_data[(int) icode].n_operands >= 3);
+  insn_constraint = insn_data[(int) icode].operand[2].constraint;
+  gcc_assert (*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 +1108,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 +1203,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 +1358,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 -r1.54 reload.h
--- reload.h	25 Jun 2005 02:00:54 -0000	1.54
+++ reload.h	30 Sep 2005 21:25:34 -0000
@@ -252,6 +252,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 -r1.482 reload1.c
--- reload1.c	7 Sep 2005 07:52:48 -0000	1.482
+++ reload1.c	30 Sep 2005 21:25:34 -0000
@@ -5496,9 +5496,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 +6209,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 +6259,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 +6448,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
@@ -6522,8 +6521,7 @@ emit_input_reload_insns (struct insn_cha
 	  || (rl->in != 0 && rl->out != 0))
 	{
 	  enum reg_class new_class
-	    = SECONDARY_INPUT_RELOAD_CLASS (rl->class,
-					    mode, real_oldequiv);
+	    = secondary_reload_class (1, rl->class, mode, real_oldequiv);
 
 	  if (new_class == NO_REGS)
 	    second_reload_reg = 0;
@@ -6682,7 +6680,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 +6694,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 -r1.133 target-def.h
--- target-def.h	24 Aug 2005 07:13:07 -0000	1.133
+++ target-def.h	30 Sep 2005 21:25:34 -0000
@@ -474,6 +474,10 @@ Foundation, 51 Franklin Street, Fifth Fl
 #define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 0
 #endif
 
+#ifndef TARGET_RELOAD_ICODE
+#define TARGET_RELOAD_ICODE default_reload_icode
+#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_RELOAD_ICODE,				\
   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 -r1.144 target.h
--- target.h	14 Jul 2005 07:39:55 -0000	1.144
+++ target.h	30 Sep 2005 21:25:34 -0000
@@ -622,6 +622,9 @@ 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 code of an expander for a secondary reload.  */
+  int (*reload_icode) (int, rtx, enum reg_class, enum machine_mode);
+
   /* 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 -r2.46 targhooks.c
--- targhooks.c	14 Jul 2005 07:39:55 -0000	2.46
+++ targhooks.c	30 Sep 2005 21:25:34 -0000
@@ -62,6 +62,8 @@ Software Foundation, 51 Franklin Street,
 #include "tm_p.h"
 #include "target-def.h"
 #include "ggc.h"
+#include "reload.h"
+#include "insn-codes.h"
 
 
 void
@@ -439,4 +441,24 @@ default_function_value (tree ret_type AT
 #endif
 }
 
+int
+default_reload_icode (int in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
+		      enum reg_class reload_class ATTRIBUTE_UNUSED,
+		      enum machine_mode reload_mode ATTRIBUTE_UNUSED)
+{
+  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)
+    return CODE_FOR_nothing;
+  return CODE_FOR_reload__NO_REGS - NO_REGS + class;
+}
+
 #include "gt-targhooks.h"
Index: targhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.h,v
retrieving revision 2.33
diff -p -u -r2.33 targhooks.h
--- targhooks.h	14 Jul 2005 07:39:56 -0000	2.33
+++ targhooks.h	30 Sep 2005 21:25:34 -0000
@@ -68,4 +68,5 @@ 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 int default_reload_icode (int, rtx, enum reg_class, enum machine_mode);
 
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 -r1.65 sh-protos.h
--- config/sh/sh-protos.h	29 Jun 2005 01:24:25 -0000	1.65
+++ config/sh/sh-protos.h	30 Sep 2005 21:25:34 -0000
@@ -165,6 +165,7 @@ extern int shmedia_cleanup_truncate (rtx
 
 extern int sh_contains_memref_p (rtx);
 extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
+extern int sh_reload_icode (int, rtx, enum reg_class, enum machine_mode);
 
 #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 -r1.347 sh.c
--- config/sh/sh.c	5 Sep 2005 12:45:22 -0000	1.347
+++ config/sh/sh.c	30 Sep 2005 21:25:35 -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_RELOAD_ICODE
+#define TARGET_RELOAD_ICODE sh_reload_icode
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -10619,6 +10622,89 @@ shmedia_prepare_call_address (rtx fnaddr
   return fnaddr;
 }
 
+int
+sh_reload_icode (int in_p, rtx x, enum reg_class class, enum machine_mode mode)
+{
+  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: return CODE_FOR_reload_insf__frn;
+	  case DFmode: return CODE_FOR_reload_indf__frn;
+	  case SImode: return CODE_FOR_reload_insi__i_fpul;
+	  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 CODE_FOR_reload__GENERAL_REGS;
+      if (class == FPUL_REGS && immediate_operand (x, mode))
+        return (GET_CODE (x) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (x))
+		? CODE_FOR_reload__GENERAL_REGS
+		: CODE_FOR_reload_insi__i_fpul);
+      if (class == FPSCR_REGS
+          && ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+              || (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
+        return CODE_FOR_reload__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 CODE_FOR_reload__GENERAL_REGS;
+      if ((mode == QImode || mode == HImode)
+          && TARGET_SHMEDIA && inqhi_operand (x, mode))
+        return CODE_FOR_reload__GENERAL_REGS;
+      if (TARGET_SHMEDIA && class == GENERAL_REGS
+          && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+        return CODE_FOR_reload__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 (mode == DFmode ? CODE_FOR_reload_outdf__RnFRm
+	    : CODE_FOR_reload__FPUL_REGS);
+  if ((class == FPUL_REGS
+       || (REGCLASS_HAS_FP_REG (class)
+           && ! TARGET_SHMEDIA && mode == SImode)) /* ??? need expander? */
+      && (GET_CODE (x) == MEM
+          || (GET_CODE (x) == REG
+              && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+                  || REGNO (x) == T_REG
+                  || system_reg_operand (x, VOIDmode)))))
+    return (class == FPUL_REG ? CODE_FOR_reload__GENERAL_REGS
+	    : in_p ? CODE_FOR_reload_insi__r_fpul
+	    : CODE_FOR_reload_outsi__fpul_r);
+  if ((class == TARGET_REGS
+       || (TARGET_SHMEDIA && class == SIBCALL_REGS))
+      && !EXTRA_CONSTRAINT_Csy (x)
+      && (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
+    return CODE_FOR_reload__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 CODE_FOR_reload__GENERAL_REGS;
+  if (class != GENERAL_REGS && GET_CODE (x) == REG
+      && TARGET_REGISTER_P (REGNO (x)))
+    return CODE_FOR_reload__GENERAL_REGS;
+  return CODE_FOR_nothing;
+}
+
 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.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.200
diff -p -u -r1.200 sh.md
--- config/sh/sh.md	13 Sep 2005 22:03:18 -0000	1.200
+++ config/sh/sh.md	30 Sep 2005 21:25:35 -0000
@@ -5845,15 +5845,15 @@ label:
 	      (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 @@ label:
   [(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 @@ label:
   "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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]