Minor reload cleanup

Bernd Schmidt bernds@cygnus.co.uk
Sun Oct 17 02:46:00 GMT 1999


> I extracted this from Bernd's recent patch.  There's no reason not to go
> ahead and get reload_mode & reload_nregs moved into struct reload.

There are more parts in that patch and some other cleanups that can be
broken out and installed first.
(In case you are wondering, the save_xxx variables were storing mostly
zeroes, and their contents can be restored by bzero and the walk of the
existing reg_rtx values).

A patch I had yesterday that included this and the part you already
installed bootstrapped on i386.

Bernd

	* reload.h (struct reload): Fix definition of mode elt.
	* reload.c (find_reloads): Compute mode and nregs fields of all
	reloads.
	* reload1.c (calculate_needs_all_insns): Simplify a bit.
	(calculate_needs): Use precomputed mode/nregs values.
	(allocate_reload_reg): Likewise.
	Break out two...
	(failed_reload, set_reload_reg): ... new functions.
	(choose_reload_regs_init): New function, mostly broken out from...
	(choose_reload_regs): ... here.  Lose all the save_xxx nonsense.
	Also lose one #if 0 block.

Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.85
diff -u -p -r1.85 reload.c
--- reload.c	1999/10/06 14:48:41	1.85
+++ reload.c	1999/10/17 09:24:27
@@ -4174,6 +4174,18 @@ find_reloads (insn, replace, ind_levels,
 	}
     }
 
+  /* Compute reload_mode and reload_nregs.  */
+  for (i = 0; i < n_reloads; i++)
+    {
+      rld[i].mode
+	= (rld[i].inmode == VOIDmode
+	   || (GET_MODE_SIZE (rld[i].outmode)
+	       > GET_MODE_SIZE (rld[i].inmode)))
+	  ? rld[i].outmode : rld[i].inmode;
+
+      rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
+    }
+
   return retval;
 }
 
Index: reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.19
diff -u -p -r1.19 reload.h
--- reload.h	1999/10/17 06:47:27	1.19
+++ reload.h	1999/10/17 09:24:28
@@ -100,9 +100,9 @@ struct reload
   enum machine_mode outmode;
 
   /* The mode of the reload register.  */
-  enum mode;
+  enum machine_mode mode;
 
-  /* the largest number of registers this reload will require.  */
+  /* The largest number of registers this reload will require.  */
   int nregs;
 
   /* Positive amount to increment or decrement by if
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.171
diff -u -p -r1.171 reload1.c
--- reload1.c	1999/10/17 06:47:27	1.171
+++ reload1.c	1999/10/17 09:24:39
@@ -422,6 +422,7 @@ static int reload_reg_free_for_value_p	P
 static int reload_reg_reaches_end_p	PROTO((int, int, enum reload_type));
 static int allocate_reload_reg		PROTO((struct insn_chain *, int, int,
 					       int));
+static void choose_reload_regs_init	PROTO((struct insn_chain *, rtx *));
 static void choose_reload_regs		PROTO((struct insn_chain *));
 static void merge_assigned_reloads	PROTO((rtx));
 static void emit_reload_insns		PROTO((struct insn_chain *));
@@ -1323,17 +1324,18 @@ calculate_needs_all_insns (global)
      int global;
 {
   struct insn_chain **pprev_reload = &insns_need_reload;
-  struct insn_chain **pchain;
+  struct insn_chain *chain;
 
   something_needs_elimination = 0;
 
-  for (pchain = &reload_insn_chain; *pchain != 0; pchain = &(*pchain)->next)
+  for (chain = reload_insn_chain; chain != 0; chain = chain->next)
     {
-      rtx insn;
-      struct insn_chain *chain;
+      rtx insn = chain->insn;
 
-      chain = *pchain;
-      insn = chain->insn;
+      /* Clear out the shortcuts, in case they were set last time through.  */
+      chain->need_elim = 0;
+      chain->need_reload = 0;
+      chain->need_operand_change = 0;
 
       /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
 	 include REG_LABEL), we need to see what effects this has on the
@@ -1357,14 +1359,7 @@ calculate_needs_all_insns (global)
 	  if (set && GET_CODE (SET_DEST (set)) == REG
 	      && reg_renumber[REGNO (SET_DEST (set))] < 0
 	      && reg_equiv_constant[REGNO (SET_DEST (set))])
-	    {
-	      /* Must clear out the shortcuts, in case they were set last
-		 time through.  */
-	      chain->need_elim = 0;
-	      chain->need_reload = 0;
-	      chain->need_operand_change = 0;
-	      continue;
-	    }
+	    continue;
 
 	  /* If needed, eliminate any eliminable registers.  */
 	  if (num_eliminable || num_eliminable_invariants)
@@ -1493,10 +1488,8 @@ calculate_needs (chain)
 	      && ! rld[i].secondary_p))
 	continue;
 
-      mode = rld[i].inmode;
-      if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-	mode = rld[i].outmode;
-      size = CLASS_MAX_NREGS (class, mode);
+      mode = rld[i].mode;
+      size = rld[i].nregs;
 
       /* Decide which time-of-use to count this reload for.  */
       switch (rld[i].when_needed)
@@ -5361,6 +5354,78 @@ reload_reg_free_for_value_p (regno, opnu
   return 1;
 }
 
+/* Give an error message saying we failed to find a reload for INSN,
+   and clear out reload R.  */
+static void
+failed_reload (insn, r)
+     rtx insn;
+     int r;
+{
+  if (asm_noperands (PATTERN (insn)) < 0)
+    /* It's the compiler's fault.  */
+    fatal_insn ("Could not find a spill register", insn);
+
+  /* It's the user's fault; the operand's mode and constraint
+     don't match.  Disable this reload so we don't crash in final.  */
+  error_for_asm (insn,
+		 "`asm' operand constraint incompatible with operand size");
+  rld[r].in = 0;
+  rld[r].out = 0;
+  rld[r].reg_rtx = 0;
+  rld[r].optional = 1;
+  rld[r].secondary_p = 1;
+}
+
+/* I is the index in SPILL_REG_RTX of the reload register we are to allocate
+   for reload R.  If it's valid, get an rtx for it.  Return nonzero if
+   successful.  */
+static int
+set_reload_reg (i, r)
+     int i, r;
+{
+  int regno;
+  rtx reg = spill_reg_rtx[i];
+
+  if (reg == 0 || GET_MODE (reg) != rld[r].mode)
+    spill_reg_rtx[i] = reg
+      = gen_rtx_REG (rld[r].mode, spill_regs[i]);
+
+  regno = true_regnum (reg);
+
+  /* Detect when the reload reg can't hold the reload mode.
+     This used to be one `if', but Sequent compiler can't handle that.  */
+  if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
+    {
+      enum machine_mode test_mode = VOIDmode;
+      if (rld[r].in)
+	test_mode = GET_MODE (rld[r].in);
+      /* If rld[r].in has VOIDmode, it means we will load it
+	 in whatever mode the reload reg has: to wit, rld[r].mode.
+	 We have already tested that for validity.  */
+      /* Aside from that, we need to test that the expressions
+	 to reload from or into have modes which are valid for this
+	 reload register.  Otherwise the reload insns would be invalid.  */
+      if (! (rld[r].in != 0 && test_mode != VOIDmode
+	     && ! HARD_REGNO_MODE_OK (regno, test_mode)))
+	if (! (rld[r].out != 0
+	       && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
+	  {
+	    /* The reg is OK.  */
+	    last_spill_reg = i;
+
+	    /* Mark as in use for this insn the reload regs we use
+	       for this.  */
+	    mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
+				    rld[r].when_needed, rld[r].mode);
+
+	    rld[r].reg_rtx = reg;
+	    reload_spill_index[r] = spill_regs[i];
+	    return 1;
+	  }
+    }
+  return 0;
+}
+
 /* Find a spill register to use as a reload register for reload R.
    LAST_RELOAD is non-zero if this is the last reload for the insn being
    processed.
@@ -5378,8 +5443,7 @@ allocate_reload_reg (chain, r, last_relo
      int noerror;
 {
   rtx insn = chain->insn;
-  int i, pass, count, regno;
-  rtx new;
+  int i, pass, count;
 
   /* If we put this reload ahead, thinking it is a group,
      then insist on finding a group.  Otherwise we can grab a
@@ -5462,7 +5526,7 @@ allocate_reload_reg (chain, r, last_relo
 		 (on 68000) got us two FP regs.  If NR is 1,
 		 we would reject both of them.  */
 	      if (force_group)
-		nr = CLASS_MAX_NREGS (rld[r].class, rld[r].mode);
+		nr = rld[r].nregs;
 	      /* If we need only one reg, we have already won.  */
 	      if (nr == 1)
 		{
@@ -5478,7 +5542,7 @@ allocate_reload_reg (chain, r, last_relo
 	      if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
 		while (nr > 1)
 		  {
-		    regno = regnum + nr - 1;
+		    int regno = regnum + nr - 1;
 		    if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
 			  && spill_reg_order[regno] >= 0
 			  && reload_reg_free_p (regno, rld[r].opnum,
@@ -5505,107 +5569,32 @@ allocate_reload_reg (chain, r, last_relo
 	return 0;
       goto failure;
     }
-
-  /* I is the index in SPILL_REG_RTX of the reload register we are to
-     allocate.  Get an rtx for it and find its register number.  */
-
-  new = spill_reg_rtx[i];
-
-  if (new == 0 || GET_MODE (new) != rld[r].mode)
-    spill_reg_rtx[i] = new
-      = gen_rtx_REG (rld[r].mode, spill_regs[i]);
-
-  regno = true_regnum (new);
-
-  /* Detect when the reload reg can't hold the reload mode.
-     This used to be one `if', but Sequent compiler can't handle that.  */
-  if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
-    {
-      enum machine_mode test_mode = VOIDmode;
-      if (rld[r].in)
-	test_mode = GET_MODE (rld[r].in);
-      /* If rld[r].in has VOIDmode, it means we will load it
-	 in whatever mode the reload reg has: to wit, rld[r].mode.
-	 We have already tested that for validity.  */
-      /* Aside from that, we need to test that the expressions
-	 to reload from or into have modes which are valid for this
-	 reload register.  Otherwise the reload insns would be invalid.  */
-      if (! (rld[r].in != 0 && test_mode != VOIDmode
-	     && ! HARD_REGNO_MODE_OK (regno, test_mode)))
-	if (! (rld[r].out != 0
-	       && ! HARD_REGNO_MODE_OK (regno, GET_MODE (rld[r].out))))
-	  {
-	    /* The reg is OK.  */
-	    last_spill_reg = i;
-
-	    /* Mark as in use for this insn the reload regs we use
-	       for this.  */
-	    mark_reload_reg_in_use (spill_regs[i], rld[r].opnum,
-				    rld[r].when_needed, rld[r].mode);
 
-	    rld[r].reg_rtx = new;
-	    reload_spill_index[r] = spill_regs[i];
-	    return 1;
-	  }
-    }
+  if (set_reload_reg (i, r))
+    return 1;
 
   /* The reg is not OK.  */
   if (noerror)
     return 0;
 
  failure:
-  if (asm_noperands (PATTERN (insn)) < 0)
-    /* It's the compiler's fault.  */
-    fatal_insn ("Could not find a spill register", insn);
+  failed_reload (insn, r);
 
-  /* It's the user's fault; the operand's mode and constraint
-     don't match.  Disable this reload so we don't crash in final.  */
-  error_for_asm (insn,
-		 "`asm' operand constraint incompatible with operand size");
-  rld[r].in = 0;
-  rld[r].out = 0;
-  rld[r].reg_rtx = 0;
-  rld[r].optional = 1;
-  rld[r].secondary_p = 1;
-
   return 1;
 }
 
-/* Assign hard reg targets for the pseudo-registers we must reload
-   into hard regs for this insn.
-   Also output the instructions to copy them in and out of the hard regs.
-
-   For machines with register classes, we are responsible for
-   finding a reload reg in the proper class.  */
-
+/* Initialize all the tables needed to allocate reload registers.
+   CHAIN is the insn currently being processed; SAVE_RELOAD_REG_RTX
+   is the array we use to restore the reg_rtx field for every reload.  */
 static void
-choose_reload_regs (chain)
+choose_reload_regs_init (chain, save_reload_reg_rtx)
      struct insn_chain *chain;
+     rtx *save_reload_reg_rtx;
 {
-  rtx insn = chain->insn;
-  register int i, j;
-  int max_group_size = 1;
-  enum reg_class group_class = NO_REGS;
-  int inheritance;
-  int pass;
+  int i;
 
-  rtx save_reload_reg_rtx[MAX_RELOADS];
-  char save_reload_inherited[MAX_RELOADS];
-  rtx save_reload_inheritance_insn[MAX_RELOADS];
-  rtx save_reload_override_in[MAX_RELOADS];
-  int save_reload_spill_index[MAX_RELOADS];
-  HARD_REG_SET save_reload_reg_used;
-  HARD_REG_SET save_reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_input[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_output[MAX_RECOG_OPERANDS];
-  HARD_REG_SET save_reload_reg_used_in_op_addr;
-  HARD_REG_SET save_reload_reg_used_in_op_addr_reload;
-  HARD_REG_SET save_reload_reg_used_in_insn;
-  HARD_REG_SET save_reload_reg_used_in_other_addr;
-  HARD_REG_SET save_reload_reg_used_at_all;
+  for (i = 0; i < n_reloads; i++)
+    rld[i].reg_rtx = save_reload_reg_rtx[i];
 
   bzero (reload_inherited, MAX_RELOADS);
   bzero ((char *) reload_inheritance_insn, MAX_RELOADS * sizeof (rtx));
@@ -5640,28 +5629,36 @@ choose_reload_regs (chain)
 
   IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
 
-#if 0  /* Not needed, now that we can always retry without inheritance.  */
-  /* See if we have more mandatory reloads than spill regs.
-     If so, then we cannot risk optimizations that could prevent
-     reloads from sharing one spill register.
+  CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
 
-     Since we will try finding a better register than reload_reg_rtx
-     unless it is equal to reload_in or reload_out, count such reloads.  */
+  for (i = 0; i < n_reloads; i++)
+    /* If we have already decided to use a certain register,
+       don't use it in another way.  */
+    if (rld[i].reg_rtx)
+      mark_reload_reg_in_use (REGNO (rld[i].reg_rtx), rld[i].opnum,
+			      rld[i].when_needed, rld[i].mode);
+}
 
-  {
-    int tem = 0;
-    for (j = 0; j < n_reloads; j++)
-      if (! rld[j].optional
-	  && (rld[j].in != 0 || rld[j].out != 0 || rld[j].secondary_p)
-	  && (rld[j].reg_rtx == 0
-	      || (! rtx_equal_p (rld[j].reg_rtx, rld[j].in)
-		  && ! rtx_equal_p (rld[j].reg_rtx, rld[j].out))))
-	tem++;
-    if (tem > n_spills)
-      must_reuse = 1;
-  }
-#endif
+/* Assign hard reg targets for the pseudo-registers we must reload
+   into hard regs for this insn.
+   Also output the instructions to copy them in and out of the hard regs.
+
+   For machines with register classes, we are responsible for
+   finding a reload reg in the proper class.  */
+
+static void
+choose_reload_regs (chain)
+     struct insn_chain *chain;
+{
+  rtx insn = chain->insn;
+  register int i, j;
+  int max_group_size = 1;
+  enum reg_class group_class = NO_REGS;
+  int inheritance;
+  int pass;
 
+  rtx save_reload_reg_rtx[MAX_RELOADS];
+
   /* In order to be certain of getting the registers we need,
      we must sort the reloads into order of increasing register class.
      Then our grabbing of reload registers will parallel the process
@@ -5676,13 +5673,6 @@ choose_reload_regs (chain)
       reload_order[j] = j;
       reload_spill_index[j] = -1;
 
-      rld[j].mode = ((rld[j].inmode == VOIDmode
-		      || (GET_MODE_SIZE (rld[j].outmode)
-			  > GET_MODE_SIZE (rld[j].inmode)))
-		     ? rld[j].outmode : rld[j].inmode);
-
-      rld[j].nregs = CLASS_MAX_NREGS (rld[j].class, rld[j].mode);
-
       if (rld[j].nregs > 1)
 	{
 	  max_group_size = MAX (rld[j].nregs, max_group_size);
@@ -5690,53 +5680,11 @@ choose_reload_regs (chain)
 	}
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
-      /* If we have already decided to use a certain register,
-	 don't use it in another way.  */
-      if (rld[j].reg_rtx)
-	mark_reload_reg_in_use (REGNO (rld[j].reg_rtx), rld[j].opnum,
-				rld[j].when_needed, rld[j].mode);
     }
 
   if (n_reloads > 1)
     qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
 
-  bcopy (reload_inherited, save_reload_inherited, sizeof reload_inherited);
-  bcopy ((char *) reload_inheritance_insn,
-	 (char *) save_reload_inheritance_insn,
-	 sizeof reload_inheritance_insn);
-  bcopy ((char *) reload_override_in, (char *) save_reload_override_in,
-	 sizeof reload_override_in);
-  bcopy ((char *) reload_spill_index, (char *) save_reload_spill_index,
-	 sizeof reload_spill_index);
-  COPY_HARD_REG_SET (save_reload_reg_used, reload_reg_used);
-  COPY_HARD_REG_SET (save_reload_reg_used_at_all, reload_reg_used_at_all);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr,
-		     reload_reg_used_in_op_addr);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr_reload,
-		     reload_reg_used_in_op_addr_reload);
-
-  COPY_HARD_REG_SET (save_reload_reg_used_in_insn,
-		     reload_reg_used_in_insn);
-  COPY_HARD_REG_SET (save_reload_reg_used_in_other_addr,
-		     reload_reg_used_in_other_addr);
-
-  for (i = 0; i < reload_n_operands; i++)
-    {
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output[i],
-			 reload_reg_used_in_output[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input[i],
-			 reload_reg_used_in_input[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_input_addr[i],
-			 reload_reg_used_in_input_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_inpaddr_addr[i],
-			 reload_reg_used_in_inpaddr_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_output_addr[i],
-			 reload_reg_used_in_output_addr[i]);
-      COPY_HARD_REG_SET (save_reload_reg_used_in_outaddr_addr[i],
-			 reload_reg_used_in_outaddr_addr[i]);
-    }
-
   /* If -O, try first with inheritance, then turning it off.
      If not -O, don't do inheritance.
      Using inheritance when not optimizing leads to paradoxes
@@ -5745,6 +5693,8 @@ choose_reload_regs (chain)
 
   for (inheritance = optimize > 0; inheritance >= 0; inheritance--)
     {
+      choose_reload_regs_init (chain, save_reload_reg_rtx);
+
       /* Process the reloads in order of preference just found.
 	 Beyond this point, subregs can be found in reload_reg_rtx.
 
@@ -5763,8 +5713,6 @@ choose_reload_regs (chain)
 	 Then make a second pass over the reloads to allocate any reloads
 	 that haven't been given registers yet.  */
 
-      CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
-
       for (j = 0; j < n_reloads; j++)
 	{
 	  register int r = reload_order[j];
@@ -6187,45 +6133,6 @@ choose_reload_regs (chain)
 	break;
 
       /* Loop around and try without any inheritance.  */
-      /* First undo everything done by the failed attempt
-	 to allocate with inheritance.  */
-      for (i = 0; i < n_reloads; i++)
-	rld[i].reg_rtx = save_reload_reg_rtx[i];
-      bcopy ((char *) save_reload_inherited, (char *) reload_inherited,
-	     sizeof reload_inherited);
-      bcopy ((char *) save_reload_inheritance_insn,
-	     (char *) reload_inheritance_insn,
-	     sizeof reload_inheritance_insn);
-      bcopy ((char *) save_reload_override_in, (char *) reload_override_in,
-	     sizeof reload_override_in);
-      bcopy ((char *) save_reload_spill_index, (char *) reload_spill_index,
-	     sizeof reload_spill_index);
-      COPY_HARD_REG_SET (reload_reg_used, save_reload_reg_used);
-      COPY_HARD_REG_SET (reload_reg_used_at_all, save_reload_reg_used_at_all);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr,
-			 save_reload_reg_used_in_op_addr);
-      COPY_HARD_REG_SET (reload_reg_used_in_op_addr_reload,
-			 save_reload_reg_used_in_op_addr_reload);
-      COPY_HARD_REG_SET (reload_reg_used_in_insn,
-			 save_reload_reg_used_in_insn);
-      COPY_HARD_REG_SET (reload_reg_used_in_other_addr,
-			 save_reload_reg_used_in_other_addr);
-
-      for (i = 0; i < reload_n_operands; i++)
-	{
-	  COPY_HARD_REG_SET (reload_reg_used_in_input[i],
-			     save_reload_reg_used_in_input[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_output[i],
-			     save_reload_reg_used_in_output[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_input_addr[i],
-			     save_reload_reg_used_in_input_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_inpaddr_addr[i],
-			     save_reload_reg_used_in_inpaddr_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_output_addr[i],
-			     save_reload_reg_used_in_output_addr[i]);
-	  COPY_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i],
-			     save_reload_reg_used_in_outaddr_addr[i]);
-	}
     }
 
   /* If we thought we could inherit a reload, because it seemed that



More information about the Gcc-patches mailing list