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


Here is a heads up of what I have so far; I don't know if it compiles.
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/rs6000: .rs6000.md.swp
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .predicates.md.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.c	2005-09-05 13:45:22.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.c	2005-10-03 22:14:50.000000000 +0100
@@ -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 *)
+{
+  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.
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.h	2005-09-12 14:23:10.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.h	2005-10-03 22:52:22.000000000 +0100
@@ -1581,6 +1581,7 @@ extern enum reg_class reg_class_from_let
  : (C) == 'H' ? (fp_one_operand (VALUE) && fldi_ok ())	\
  : (C) == 'F')
 
+#if 0
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
@@ -1665,6 +1666,9 @@ extern enum reg_class reg_class_from_let
       && (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.
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.h.swo
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.h.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.md /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.md
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.md	2005-09-13 23:03:18.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.md	2005-09-30 21:38:02.000000000 +0100
@@ -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"
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.md.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh-protos.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh-protos.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh-protos.h	2005-06-29 02:24:25.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh-protos.h	2005-09-30 19:40:31.000000000 +0100
@@ -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 */
 
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/doc: .md.texi.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/gencodes.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/gencodes.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/gencodes.c	2005-06-25 03:00:13.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/gencodes.c	2005-09-30 19:17:15.000000000 +0100
@@ -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 */");
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/regclass.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/regclass.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/regclass.c	2005-06-25 03:00:52.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/regclass.c	2005-09-30 22:04:28.000000000 +0100
@@ -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]
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload1.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload1.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload1.c	2005-09-07 08:52:48.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload1.c	2005-10-03 23:48:28.000000000 +0100
@@ -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 = (t_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 = (t_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;
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc: reload1.c-20050930-2225
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.c	2005-08-05 17:06:35.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.c	2005-10-03 23:02:11.000000000 +0100
@@ -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,
Binary files /mnt/scratch/nightly/2005-09-28/gcc/gcc/.reload.c.swp and /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/.reload.c.swp differ
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.h	2005-06-25 03:00:54.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.h	2005-10-03 21:14:51.000000000 +0100
@@ -247,11 +247,20 @@ extern struct insn_chain *reload_insn_ch
 /* Allocate a new insn_chain structure.  */
 extern struct insn_chain *new_insn_chain (void);
 
+/* The struct used by the secondary_reload target hook.  */
+struct secondary_reload_info
+{
+  enum machine_mode *icode;
+} secondary_reload_info;
+
 extern void compute_use_by_pseudos (HARD_REG_SET *, regset);
 #endif
 
 /* 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.  */
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/target-def.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target-def.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/target-def.h	2005-08-24 08:13:07.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target-def.h	2005-10-03 21:11:53.000000000 +0100
@@ -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,			\
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/target.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/target.h	2005-07-14 08:39:55.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target.h	2005-10-03 21:12:51.000000000 +0100
@@ -622,6 +622,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.  */
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.c	2005-07-14 08:39:55.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.c	2005-10-03 22:34:57.000000000 +0100
@@ -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,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[2].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"
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.h	2005-07-14 08:39:56.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.h	2005-10-03 21:16:17.000000000 +0100
@@ -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,
+						secondary_reload_info *);
 

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