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]

Basic block boundaries, again


Here's a patch that fixes caller-save to update basic_block_head and
basic_block_end when it inserts new insns.

Bernd

	* caller-save.c (insert_save_restore): Break this function up
	into new functions insert_restore, insert_save and insert_one_insn.
	All callers changed.
	(insert_restore): New function, mostly broken out of
	insert_save_restore.
	(insert_save): Likewise.
	(insert_one_insn): Likewise.
	(restore_referenced_regs): New argument BLOCK.  All callers changed.
	(save_call_clobbered_regs): Don't keep track of basic block boundaries
	in this function, do it in insert_one_insn instead.

Index: caller-save.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/caller-save.c,v
retrieving revision 1.1.1.13
diff -u -p -r1.1.1.13 caller-save.c
--- caller-save.c	1998/10/01 14:38:55	1.1.1.13
+++ caller-save.c	1998/10/02 10:04:42
@@ -82,9 +82,14 @@ 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));
-static int insert_save_restore		PROTO((rtx, int, int,
+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 insert_one_insn		PROTO((rtx, int, enum rtx_code,
+					       enum machine_mode, rtx, int));
 
 /* Initialize for caller-save.
 
@@ -358,7 +363,6 @@ save_call_clobbered_regs (insn_mode)
   for (b = 0; b < n_basic_blocks; b++)
     {
       regset regs_live = basic_block_live_at_start[b];
-      rtx prev_block_last = PREV_INSN (basic_block_head[b]);
       int i, j;
       int regno;
 
@@ -399,7 +403,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);
+		restore_referenced_regs (PATTERN (insn), insn, insn_mode, b);
 
 	      /* NB: the normal procedure is to first enliven any
 		 registers set by insn, then deaden any registers that
@@ -449,8 +453,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_restore (insn, 1, regno, 
-						    insn_mode, 0);
+		      regno += insert_save (insn, 1, regno, insn_mode, b);
 
 		  /* Put the information for this CALL_INSN on top of what
 		     we already had.  */
@@ -489,13 +492,9 @@ save_call_clobbered_regs (insn_mode)
       if (n_regs_saved)
 	for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	  if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
-	    regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
-				  ? insn : NEXT_INSN (insn)), 0,
-				  regno, insn_mode, MOVE_MAX / UNITS_PER_WORD);
-
-      /* If we added any insns at the start of the block, update the start
-	 of the block to point at those insns.  */
-      basic_block_head[b] = NEXT_INSN (prev_block_last);
+	    regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
+				     regno, insn_mode,
+				     MOVE_MAX / UNITS_PER_WORD, b);
     }
 }
 
@@ -562,10 +561,11 @@ clear_reg_live (reg)
    INSN_MODE is the mode to assign to any insns that we add.  */
 
 static void
-restore_referenced_regs (x, insn, insn_mode)
+restore_referenced_regs (x, insn, insn_mode, block)
      rtx x;
      rtx insn;
      enum machine_mode insn_mode;
+     int block;
 {
   enum rtx_code code = GET_CODE (x);
   char *fmt;
@@ -584,11 +584,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);
+				 insn, insn_mode, block);
       else if (regno >= FIRST_PSEUDO_REGISTER
 	       && reg_equiv_address[regno] != 0)
 	restore_referenced_regs (reg_equiv_address[regno],
-				 insn, insn_mode);
+				 insn, insn_mode, block);
 
       /* Otherwise if this is a hard register, restore any piece of it that
 	 is currently saved.  */
@@ -597,13 +597,13 @@ restore_referenced_regs (x, insn, insn_m
 	{
 	  int numregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
 	  /* Save at most SAVEREGS at a time.  This can not be larger than
-	     MOVE_MAX, because that causes insert_save_restore to fail.  */
+	     MOVE_MAX, because that causes insert_restore to fail.  */
 	  int saveregs = MIN (numregs, MOVE_MAX / UNITS_PER_WORD);
 	  int endregno = regno + numregs;
 
 	  for (i = regno; i < endregno; i++)
 	    if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
-	      i += insert_save_restore (insn, 0, i, insn_mode, saveregs);
+	      i += insert_restore (insn, 1, i, insn_mode, saveregs, block);
 	}
 
       return;
@@ -613,18 +613,18 @@ 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);
+	restore_referenced_regs (XEXP (x, i), insn, insn_mode, 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);
+	  restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode, block);
     }
 }
 
-/* Insert a sequence of insns to save or restore, SAVE_P says which,
-   REGNO.  Place these insns in front of INSN.  INSN_MODE is the mode
+/* 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 (when SAVE_P == 0).  It should
-   never be less than 1 since we only work with entire 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,16 +635,19 @@ restore_referenced_regs (x, insn, insn_m
    Return the extra number of registers saved.  */
 
 static int
-insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
+insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
      rtx insn;
-     int save_p;
+     int before_p;
      int regno;
      enum machine_mode insn_mode;
      int maxrestore;
+     int block;
 {
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
   int numregs = 0;
+  int i, j, k;
+  int ok;
 
   /* A common failure mode if register status is not correct in the RTL
      is for this routine to be called with a REGNO we didn't expect to
@@ -656,108 +659,159 @@ insert_save_restore (insn, save_p, regno
   if (regno_save_mem[regno][1] == 0)
     abort ();
 
-#ifdef HAVE_cc0
-  /* If INSN references CC0, put our insns in front of the insn that sets
-     CC0.  This is always safe, since the only way we could be passed an
-     insn that references CC0 is for a restore, and doing a restore earlier
-     isn't a problem.  We do, however, assume here that CALL_INSNs don't
-     reference CC0.  Guard against non-INSN's like CODE_LABEL.  */
-
-  if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
-      && reg_referenced_p (cc0_rtx, PATTERN (insn)))
-    insn = prev_nonnote_insn (insn);
-#endif
-
   /* Get the pattern to emit and update our status.  */
-  if (save_p)
+
+  /* See if we can restore `maxrestore' registers at once.  Work
+     backwards to the single register case.  */
+  for (i = maxrestore; i > 0; i--)
     {
-      int i, j, k;
-      int ok;
+      ok = 1;
+      if (regno_save_mem[regno][i])
+	for (j = 0; j < i; j++)
+	  {
+	    if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
+	      ok = 0;
+	  }
+      else
+	continue;
 
-      /* See if we can save several registers with a single instruction.  
-	 Work backwards to the single register case.  */
-      for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
+      /* Must do this one restore at a time */
+      if (! ok)
+	continue;
+	    
+      pat = gen_rtx_SET (VOIDmode,
+			 gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), 
+				      regno), 
+			 regno_save_mem[regno][i]);
+      code = reg_restore_code[regno][i];
+
+
+      /* Clear status for all registers we restored.  */
+      for (k = 0; k < i; k++)
 	{
-	  ok = 1;
-	  if (regno_save_mem[regno][i] != 0)
-	    for (j = 0; j < i; j++)
-	      {
-		if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
-		    || ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
-		    || TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
-		  ok = 0;
-	      }
-	  else 
-	    continue;
+	  CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
+	  n_regs_saved--;
+	}
 
-	  /* Must do this one save at a time */
-	  if (! ok)
-	    continue;
+      numregs = i;
+      break;
+    }
 
-          pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
-			     gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
-					  regno));
-          code = reg_save_code[regno][i];
+  insert_one_insn (insn, before_p, code, insn_mode, pat, block);
 
-	  /* Set hard_regs_saved for all the registers we saved.  */
-	  for (k = 0; k < i; k++)
-	    {
-	      SET_HARD_REG_BIT (hard_regs_saved, regno + k);
-	      SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
-	      n_regs_saved++;
-	    }
+  /* Tell our callers how many extra registers we saved/restored */
+  return numregs - 1;
+}
 
-	  numregs = i;
-	  break;
-        }
-    }
-  else
-    {
-      int i, j, k;
-      int ok;
+/* Like insert_restore, but emit code to save REGNO.  */
+static int
+insert_save (insn, before_p, regno, insn_mode, block)
+     rtx insn;
+     int before_p;
+     int regno;
+     enum machine_mode insn_mode;
+     int block;
+{
+  rtx pat = NULL_RTX;
+  enum insn_code code = CODE_FOR_nothing;
+  int numregs = 0;
+  int i, j, k;
+  int ok;
 
-      /* See if we can restore `maxrestore' registers at once.  Work
-	 backwards to the single register case.  */
-      for (i = maxrestore; i > 0; i--)
-	{
-	  ok = 1;
-	  if (regno_save_mem[regno][i])
-	    for (j = 0; j < i; j++)
-	      {
-	  	if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
-		  ok = 0;
-	      }
-	  else
-	    continue;
+  /* A common failure mode if register status is not correct in the RTL
+     is for this routine to be called with a REGNO we didn't expect to
+     save.  That will cause us to write an insn with a (nil) SET_DEST
+     or SET_SRC.  Instead of doing so and causing a crash later, check
+     for this common case and abort here instead.  This will remove one
+     step in debugging such problems.  */
 
-	  /* Must do this one restore at a time */
-	  if (! ok)
-	    continue;
-	    
-          pat = gen_rtx_SET (VOIDmode,
-			     gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), 
-					  regno), 
-			 regno_save_mem[regno][i]);
-          code = reg_restore_code[regno][i];
+  if (regno_save_mem[regno][1] == 0)
+    abort ();
 
+  /* Get the pattern to emit and update our status.  */
 
-	  /* Clear status for all registers we restored.  */
-	  for (k = 0; k < i; k++)
-	    {
-	      CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
-	      n_regs_saved--;
-	    }
+  /* See if we can save several registers with a single instruction.  
+     Work backwards to the single register case.  */
+  for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
+    {
+      ok = 1;
+      if (regno_save_mem[regno][i] != 0)
+	for (j = 0; j < i; j++)
+	  {
+	    if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
+		|| ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
+		|| TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
+	      ok = 0;
+	  }
+      else 
+	continue;
 
-	  numregs = i;
-	  break;
-        }
+      /* Must do this one save at a time */
+      if (! ok)
+	continue;
+
+      pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
+			 gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
+				      regno));
+      code = reg_save_code[regno][i];
+
+      /* Set hard_regs_saved for all the registers we saved.  */
+      for (k = 0; k < i; k++)
+	{
+	  SET_HARD_REG_BIT (hard_regs_saved, regno + k);
+	  SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
+	  n_regs_saved++;
+	}
+
+      numregs = i;
+      break;
     }
-  /* Emit the insn and set the code and mode.  */
 
-  insn = emit_insn_before (pat, insn);
-  PUT_MODE (insn, insn_mode);
-  INSN_CODE (insn) = code;
+  insert_one_insn (insn, before_p, code, insn_mode, 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.  */
+static void
+insert_one_insn (insn, before_p, code, mode, pat, block)
+     rtx insn;
+     int before_p;
+     enum rtx_code code;
+     enum machine_mode mode;
+     rtx pat;
+     int block;
+{
+  rtx insert_point = insn;
+  rtx new;
+#ifdef HAVE_cc0
+  /* If INSN references CC0, put our insns in front of the insn that sets
+     CC0.  This is always safe, since the only way we could be passed an
+     insn that references CC0 is for a restore, and doing a restore earlier
+     isn't a problem.  We do, however, assume here that CALL_INSNs don't
+     reference CC0.  Guard against non-INSN's like CODE_LABEL.  */
+
+  if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
+      && before_p
+      && reg_referenced_p (cc0_rtx, PATTERN (insn)))
+    insert_point = prev_nonnote_insn (insn);
+#endif
+
+  if (before_p)
+    {
+      new = emit_insn_before (pat, insert_point);
+      if (insert_point == basic_block_head[block])
+	basic_block_head[block] = new;
+    }
+  else
+    {
+      new = emit_insn_after (pat, insert_point);
+      if (insert_point == basic_block_end[block])
+	basic_block_end[block] = new;
+    }
+    
+  PUT_MODE (new, mode);
+  INSN_CODE (new) = code;
 }


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