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]

Local spill patches, caller-save part


Here's one more broken out part of my local spill changes.  This one modifies
the code that handles caller-saves that need a spill register.  Instead of
special-casing this in reload/calculate_needs_all_insns, all the caller save
insns are emitted earlier so that find_reloads sees them like any other insn.
This requires deleting them on each iteration if we can tell that another
iteration will be run.  On the whole, I think this approach is cleaner; the
special-case code can't easily be converted to deal with local spilling, and
this patch makes caller-save.c function quite independent from reload.

This patch is not very well tested yet.  Its equivalent in my larger patch
(reload-v5) has had complete c-torture runs on i586-linux and
sparc-sun-solaris2.6; this one has only a partial test on the latter target.


Bernd

	* caller-save.c (restore_referenced_regs): Lose mode argument.
	(insert_save): Lose mode argument.
	(insert_restore): Lose mode argument.
	(insert_one_insn): Lose mode argument.
	(save_call_clobbered_regs): Lose mode argument.
	(setup_save_areas): Take no argument and return void.  All callers
	changed.
	Don't verify validity of memory addresses.
	* reload.h (setup_save_ares): Adjust prototype.
	(save_call_clobbered_regs): Likewise.
	* reload1.c (delete_caller_save_insns): New function.
	(caller_save_spill_class): Delete variable.
	(caller_save_group_size): Delete variable.
	(reload): Call setup_save_areas and save_call_clobbered_regs
	in the main loop, before calling calculate_needs_all_insns.
	Don't call save_call_clobbered_regs after the loop.
	Call delete_caller_save_insns at the end of an iteration if
	something changed.
	Delete code to manage caller_save_spill_class.
	Emit the final note before setting reload_first_uid.
	Simplify test that determines whether reload_as_needed gets run.
	(calculate_needs): Delete code to manage caller_save_spill_class.

Index: caller-save.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/caller-save.c,v
retrieving revision 1.11
diff -u -p -r1.11 caller-save.c
--- caller-save.c	1998/10/02 10:25:57	1.11
+++ caller-save.c	1998/10/06 15:48:21
@@ -82,14 +82,11 @@ int n_regs_saved;
 
 static void set_reg_live		PROTO((rtx, rtx));
 static void clear_reg_live		PROTO((rtx));
-static void restore_referenced_regs	PROTO((rtx, rtx, enum machine_mode,
-					       int));
-static int insert_restore		PROTO((rtx, int, int,
-					       enum machine_mode, int, int));
-static int insert_save			PROTO((rtx, int, int,
-					       enum machine_mode, int));
+static void restore_referenced_regs	PROTO((rtx, rtx, int));
+static int insert_restore		PROTO((rtx, int, int, int, int));
+static int insert_save			PROTO((rtx, int, int, int));
 static void insert_one_insn		PROTO((rtx, int, enum rtx_code,
-					       enum machine_mode, rtx, int));
+					       rtx, int));
 
 /* Initialize for caller-save.
 
@@ -234,13 +231,6 @@ init_save_areas ()
    overestimate slightly (especially if some of these registers are later
    used as spill registers), but it should not be significant.
 
-   Then perform register elimination in the addresses of the save area
-   locations; return 1 if all eliminated addresses are strictly valid.
-   We assume that our caller has set up the elimination table to the
-   worst (largest) possible offsets.
-
-   Set *PCHANGED to 1 if we had to allocate some memory for the save area.  
-
    Future work:
 
      In the fallback case we should iterate backwards across all possible
@@ -253,15 +243,12 @@ init_save_areas ()
      machine independent since they might be saving non-consecutive 
      registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
 
-int
-setup_save_areas (pchanged)
-     int *pchanged;
+void
+setup_save_areas ()
 {
   int i, j, k;
   HARD_REG_SET hard_regs_used;
-  int ok = 1;
 
-
   /* Allocate space in the save area for the largest multi-register
      pseudos first, then work backwards to single register
      pseudos.  */
@@ -334,28 +321,16 @@ setup_save_areas (pchanged)
 		regno_save_mem[i+k][1] 
 		  = adj_offsettable_operand (temp, k * UNITS_PER_WORD);
 	      }
-	    *pchanged = 1;
 	  }
       }
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
-      if (regno_save_mem[i][j] != 0)
-	ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]),
-				       XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0));
-
-  return ok;
+  return;
 }
 
-/* Find the places where hard regs are live across calls and save them.
+/* Find the places where hard regs are live across calls and save them.  */
 
-   INSN_MODE is the mode to assign to any insns that we add.  This is used
-   by reload to determine whether or not reloads or register eliminations
-   need be done on these insns.  */
-
 void
-save_call_clobbered_regs (insn_mode)
-     enum machine_mode insn_mode;
+save_call_clobbered_regs ()
 {
   rtx insn;
   int b;
@@ -403,7 +378,7 @@ save_call_clobbered_regs (insn_mode)
 		 any of them.  We must restore them before the insn if so.  */
 
 	      if (n_regs_saved)
-		restore_referenced_regs (PATTERN (insn), insn, insn_mode, b);
+		restore_referenced_regs (PATTERN (insn), insn, b);
 
 	      /* NB: the normal procedure is to first enliven any
 		 registers set by insn, then deaden any registers that
@@ -453,7 +428,7 @@ save_call_clobbered_regs (insn_mode)
 			/* It must not be set by this instruction.  */
 		        && ! TEST_HARD_REG_BIT (this_call_sets, regno)
 		        && ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
-		      regno += insert_save (insn, 1, regno, insn_mode, b);
+		      regno += insert_save (insn, 1, regno, b);
 
 		  /* Put the information for this CALL_INSN on top of what
 		     we already had.  */
@@ -493,7 +468,7 @@ save_call_clobbered_regs (insn_mode)
 	for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	  if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
 	    regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
-				     regno, insn_mode,
+				     regno,
 				     MOVE_MAX / UNITS_PER_WORD, b);
     }
 }
@@ -557,14 +532,13 @@ clear_reg_live (reg)
 }      
 
 /* If any register currently residing in the save area is referenced in X,
-   which is part of INSN, emit code to restore the register in front of INSN.
-   INSN_MODE is the mode to assign to any insns that we add.  */
+   which is part of INSN, emit code to restore the register in front of
+   INSN.  */
 
 static void
-restore_referenced_regs (x, insn, insn_mode, block)
+restore_referenced_regs (x, insn, block)
      rtx x;
      rtx insn;
-     enum machine_mode insn_mode;
      int block;
 {
   enum rtx_code code = GET_CODE (x);
@@ -584,11 +558,11 @@ restore_referenced_regs (x, insn, insn_m
       if (regno >= FIRST_PSEUDO_REGISTER
 	  && reg_equiv_mem[regno] != 0)
 	restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
-				 insn, insn_mode, block);
+				 insn, block);
       else if (regno >= FIRST_PSEUDO_REGISTER
 	       && reg_equiv_address[regno] != 0)
 	restore_referenced_regs (reg_equiv_address[regno],
-				 insn, insn_mode, block);
+				 insn, block);
 
       /* Otherwise if this is a hard register, restore any piece of it that
 	 is currently saved.  */
@@ -603,7 +577,7 @@ restore_referenced_regs (x, insn, insn_m
 
 	  for (i = regno; i < endregno; i++)
 	    if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
-	      i += insert_restore (insn, 1, i, insn_mode, saveregs, block);
+	      i += insert_restore (insn, 1, i, saveregs, block);
 	}
 
       return;
@@ -613,18 +587,17 @@ restore_referenced_regs (x, insn, insn_m
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-	restore_referenced_regs (XEXP (x, i), insn, insn_mode, block);
+	restore_referenced_regs (XEXP (x, i), insn, block);
       else if (fmt[i] == 'E')
 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-	  restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode, block);
+	  restore_referenced_regs (XVECEXP (x, i, j), insn, block);
     }
 }
 
 /* Insert a sequence of insns to restore REGNO.  Place these insns in front
-   of or after INSN (determined by BEFORE_P).  INSN_MODE is the mode
-   to assign to these insns.   MAXRESTORE is the maximum number of registers
-   which should be restored during this call.  It should never be less than
-   1 since we only work with entire registers.
+   of or after INSN (determined by BEFORE_P).   MAXRESTORE is the maximum
+   number of registers which should be restored during this call.  It should
+   never be less than 1 since we only work with entire registers.
 
    Note that we have verified in init_caller_save that we can do this
    with a simple SET, so use it.  Set INSN_CODE to what we save there
@@ -635,11 +608,10 @@ restore_referenced_regs (x, insn, insn_m
    Return the extra number of registers saved.  */
 
 static int
-insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
+insert_restore (insn, before_p, regno, maxrestore, block)
      rtx insn;
      int before_p;
      int regno;
-     enum machine_mode insn_mode;
      int maxrestore;
      int block;
 {
@@ -697,7 +669,7 @@ insert_restore (insn, before_p, regno, i
       break;
     }
 
-  insert_one_insn (insn, before_p, code, insn_mode, pat, block);
+  insert_one_insn (insn, before_p, code, pat, block);
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
@@ -705,11 +677,10 @@ insert_restore (insn, before_p, regno, i
 
 /* Like insert_restore, but emit code to save REGNO.  */
 static int
-insert_save (insn, before_p, regno, insn_mode, block)
+insert_save (insn, before_p, regno, block)
      rtx insn;
      int before_p;
      int regno;
-     enum machine_mode insn_mode;
      int block;
 {
   rtx pat = NULL_RTX;
@@ -767,20 +738,18 @@ insert_save (insn, before_p, regno, insn
       break;
     }
 
-  insert_one_insn (insn, before_p, code, insn_mode, pat, block);
+  insert_one_insn (insn, before_p, code, pat, block);
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
 }
 
-/* Emit one insn, set the code and mode, and update basic block
-   boundaries.  */
+/* Emit one insn, set the code, and update basic block boundaries.  */
 static void
-insert_one_insn (insn, before_p, code, mode, pat, block)
+insert_one_insn (insn, before_p, code, pat, block)
      rtx insn;
      int before_p;
      enum rtx_code code;
-     enum machine_mode mode;
      rtx pat;
      int block;
 {
@@ -811,7 +780,6 @@ insert_one_insn (insn, before_p, code, m
       if (insert_point == basic_block_end[block])
 	basic_block_end[block] = new;
     }
-    
-  PUT_MODE (new, mode);
+
   INSN_CODE (new) = code;
 }
Index: reload.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.h,v
retrieving revision 1.10
diff -u -p -r1.10 reload.h
--- reload.h	1998/10/06 00:39:20	1.10
+++ reload.h	1998/10/06 15:48:25
@@ -327,7 +327,7 @@ extern void init_caller_save PROTO((void
 extern void init_save_areas PROTO((void));
 
 /* Allocate save areas for any hard registers that might need saving.  */
-extern int setup_save_areas PROTO((int *));
+extern void setup_save_areas PROTO((void));
 
 /* Find the places where hard regs are live across calls and save them.  */
-extern void save_call_clobbered_regs PROTO((enum machine_mode));
+extern void save_call_clobbered_regs PROTO((void));
Index: reload1.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload1.c,v
retrieving revision 1.72
diff -u -p -r1.72 reload1.c
--- reload1.c	1998/10/06 00:39:22	1.72
+++ reload1.c	1998/10/06 15:48:43
@@ -371,6 +372,7 @@ static void count_possible_groups	PROTO(
 static int modes_equiv_for_class_p	PROTO((enum machine_mode,
 					       enum machine_mode,
 					       enum reg_class));
+static void delete_caller_save_insns	PROTO((rtx));
 static void spill_failure		PROTO((rtx));
 static int new_spill_reg		PROTO((int, int, int *, int *, int,
 					       FILE *));
@@ -566,10 +568,6 @@ static int something_needs_reloads;
 /* Set during calculate_needs if an insn needs register elimination.  */
 static int something_needs_elimination;
 
-/* Indicate whether caller saves need a spill register.  */
-static enum reg_class caller_save_spill_class = NO_REGS;
-static int caller_save_group_size = 1;
-
 /* For each class, number of reload regs needed in that class.
    This is the maximum over all insns of the needs in that class
    of the individual insn.  */
@@ -644,12 +642,13 @@ reload (first, global, dumpfile)
 
   reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
 
+  /* Make sure that the last insn in the chain
+     is not something that needs reloading.  */
+  emit_note (NULL_PTR, NOTE_INSN_DELETED);
+
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
 
-  caller_save_spill_class = NO_REGS;
-  caller_save_group_size = 1;
-
   for (i = 0; i < N_REG_CLASSES; i++)
     basic_block_needs[i] = 0;
 
@@ -687,10 +686,6 @@ reload (first, global, dumpfile)
 	  regs_ever_live[i] = 1;
       }
 
-  /* Make sure that the last insn in the chain
-     is not something that needs reloading.  */
-  emit_note (NULL_PTR, NOTE_INSN_DELETED);
-
   /* Find all the pseudo registers that didn't get hard regs
      but do have known equivalent constants or memory slots.
      These include parameters (known equivalent to parameter slots)
@@ -986,18 +983,26 @@ reload (first, global, dumpfile)
 	      }
 	  }
 
+      /* Insert code to save and restore call-clobbered hard regs
+	 around calls.  Tell if what mode to use so that we will process
+	 those insns in reload_as_needed if we have to.  */
+
+      if (caller_save_needed)
+	setup_save_areas ();
+
+      if (starting_frame_size != get_frame_size ())
+	something_changed = 1;
+
       /* If we allocated another pseudo to the stack, redo elimination
 	 bookkeeping.  */
       if (something_changed)
 	continue;
-
-      /* If caller-saves needs a group, initialize the group to include
-	 the size and mode required for caller-saves.  */
 
-      if (caller_save_group_size > 1)
+      if (caller_save_needed)
 	{
-	  group_mode[(int) caller_save_spill_class] = Pmode;
-	  group_size[(int) caller_save_spill_class] = caller_save_group_size;
+	  save_call_clobbered_regs ();
+	  /* That might have allocated new insn_chain structures.  */
+	  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
 	}
 
       something_changed |= calculate_needs_all_insns (first, global);
@@ -1010,32 +1015,6 @@ reload (first, global, dumpfile)
       if (dumpfile)
 	dump_needs (dumpfile);
 
-      /* If we have caller-saves, set up the save areas and see if caller-save
-	 will need a spill register.  */
-
-      if (caller_save_needed)
-	{
-	  /* Set the offsets for setup_save_areas.  */
-	  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
-	       ep++)
-	    ep->previous_offset = ep->max_offset;
-
-	  if ( ! setup_save_areas (&something_changed)
-	      && caller_save_spill_class  == NO_REGS)
-	    {
-	      /* The class we will need depends on whether the machine
-		 supports the sum of two registers for an address; see
-	      find_address_reloads for details.  */
-
-	      caller_save_spill_class
-		= (double_reg_address_ok ? reload_address_index_reg_class
-		   : reload_address_base_reg_class);
-	      caller_save_group_size
-		= CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
-	      something_changed = 1;
-	    }
-	}
-
       {
 	HARD_REG_SET to_spill;
 	CLEAR_HARD_REG_SET (to_spill);
@@ -1098,6 +1077,9 @@ reload (first, global, dumpfile)
       something_changed |= find_reload_regs (global, dumpfile);
       if (failure)
 	goto failed;
+
+      if (something_changed)
+	delete_caller_save_insns (first);
     }
 
   /* If global-alloc was run, notify it of any register eliminations we have
@@ -1107,15 +1089,6 @@ reload (first, global, dumpfile)
       if (ep->can_eliminate)
 	mark_elimination (ep->from, ep->to);
 
-  /* Insert code to save and restore call-clobbered hard regs
-     around calls.  Tell if what mode to use so that we will process
-     those insns in reload_as_needed if we have to.  */
-
-  if (caller_save_needed)
-    save_call_clobbered_regs (num_eliminable ? QImode
-			      : caller_save_spill_class != NO_REGS ? HImode
-			      : VOIDmode);
-
   /* If a pseudo has no hard reg, delete the insns that made the equivalence.
      If that insn didn't set the register (i.e., it copied the register to
      memory), just delete that insn instead of the equivalencing insn plus
@@ -1141,9 +1114,7 @@ reload (first, global, dumpfile)
      by generating move instructions to move the must-be-register
      values into or out of the reload registers.  */
 
-  if (something_needs_reloads || something_needs_elimination
-      || (caller_save_needed && num_eliminable)
-      || caller_save_spill_class != NO_REGS)
+  if (something_needs_reloads || something_needs_elimination)
     reload_as_needed (first, global);
 
   /* If we were able to eliminate the frame pointer, show that it is no
@@ -1384,13 +1468,7 @@ calculate_needs_all_insns (first, global
 	      something_needs_elimination = 1;
 	    }
 
-	  /* If this insn has no reloads, we need not do anything except
-	     in the case of a CALL_INSN when we have caller-saves and
-	     caller-save needs reloads.  */
-
-	  if (n_reloads != 0
-	      || (GET_CODE (insn) == CALL_INSN
-		  && caller_save_spill_class != NO_REGS))
+	  if (n_reloads != 0)
 	    something_changed |= calculate_needs (this_block, insn,
 						  avoid_return_reg, global);
 	}
@@ -1650,75 +1728,6 @@ calculate_needs (this_block, insn, avoid
 		insn_needs.other_addr.groups[i]);
     }
 
-  /* If this is a CALL_INSN and caller-saves will need
-     a spill register, act as if the spill register is
-     needed for this insn.   However, the spill register
-     can be used by any reload of this insn, so we only
-     need do something if no need for that class has
-     been recorded.
-
-     The assumption that every CALL_INSN will trigger a
-     caller-save is highly conservative, however, the number
-     of cases where caller-saves will need a spill register but
-     a block containing a CALL_INSN won't need a spill register
-     of that class should be quite rare.
-
-     If a group is needed, the size and mode of the group will
-     have been set up at the beginning of this loop.  */
-
-  if (GET_CODE (insn) == CALL_INSN
-      && caller_save_spill_class != NO_REGS)
-    {
-      int j;
-      /* See if this register would conflict with any reload that
-	 needs a group or any reload that needs a nongroup.  */
-      int nongroup_need = 0;
-      int *caller_save_needs;
-
-      for (j = 0; j < n_reloads; j++)
-	if (reg_classes_intersect_p (caller_save_spill_class,
-				     reload_reg_class[j])
-	    && ((CLASS_MAX_NREGS
-		 (reload_reg_class[j],
-		  (GET_MODE_SIZE (reload_outmode[j])
-		   > GET_MODE_SIZE (reload_inmode[j]))
-		  ? reload_outmode[j] : reload_inmode[j])
-		 > 1)
-		|| reload_nongroup[j]))
-	  {
-	    nongroup_need = 1;
-	    break;
-	  }
-
-      caller_save_needs 
-	= (caller_save_group_size > 1
-	   ? insn_needs.other.groups
-	   : insn_needs.other.regs[nongroup_need]); 
-
-      if (caller_save_needs[(int) caller_save_spill_class] == 0)
-	{
-	  register enum reg_class *p
-	    = reg_class_superclasses[(int) caller_save_spill_class];
-
-	  caller_save_needs[(int) caller_save_spill_class]++;
-
-	  while (*p != LIM_REG_CLASSES)
-	    caller_save_needs[(int) *p++] += 1;
-	}
-
-      /* Show that this basic block will need a register of
-	 this class.  */
-
-      if (global
-	  && ! (basic_block_needs[(int) caller_save_spill_class]
-		[this_block]))
-	{
-	  basic_block_needs[(int) caller_save_spill_class]
-	    [this_block] = 1;
-	  something_changed = 1;
-	}
-    }
-
   /* If this insn stores the value of a function call,
      and that value is in a register that has been spilled,
      and if the insn needs a reload in a class
@@ -2163,6 +2172,47 @@ dump_needs (dumpfile)
 		 max_groups[i], max_groups[i] == 1 ? "" : "s",
 		 mode_name[(int) group_mode[i]],
 		 reg_class_names[i], INSN_UID (max_groups_insn[i]));
+    }
+}
+
+/* Delete all insns that were inserted by emit_caller_save_insns during
+   this iteration.  */
+static void
+delete_caller_save_insns (first)
+     rtx first;
+{
+  rtx insn = first;
+  int b = -1;
+
+  while (insn != 0)
+    {
+      if (b + 1 != n_basic_blocks
+	  && basic_block_head[b + 1] == insn)
+	b++;
+
+      while (insn != 0 && INSN_UID (insn) >= reload_first_uid)
+	{
+	  rtx next = NEXT_INSN (insn);
+	  rtx prev = PREV_INSN (insn);
+
+	  if (insn == basic_block_head[b])
+	    basic_block_head[b] = next;
+	  if (insn == basic_block_end[b])
+	    basic_block_end[b] = prev;
+
+	  if (next != 0)
+	    PREV_INSN (next) = prev;
+	  if (prev != 0)
+	    NEXT_INSN (prev) = next;
+
+	  insn = next;
+
+	  if (b + 1 != n_basic_blocks
+	      && basic_block_head[b + 1] == insn)
+	    b++;
+	}
+      if (insn != 0)
+	insn = NEXT_INSN (insn);
     }
 }
 



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