Post-reload life analysis, v2

Bernd Schmidt crux@Pool.Informatik.RWTH-Aachen.DE
Thu Oct 8 08:02:00 GMT 1998


Here's an updated patch for post-reload life analysis.  This one should
handle fixed regs, global regs and uneliminated regs properly by marking
them as live everywhere and not creating death notes for them.  It also
fixes a minor problem where the previous patch would create a REG_UNUSED
note for every call-clobbered reg, on every call insn, and one abort when
it found a CLOBBER insn that was generated by reload outside of a basic
block.
I managed to build a Linux-2.1.124 kernel with this patch.  glibc-2.0.96
doesn't quite build, but that seems to be a different problem (an asm
that needs too many reloads).

For some reason, the part in jump.c already seems to have crept into the
egcs repository, which is fortunately harmless.  I've included it anyway
in the patch.

Bernd

	* jump.c (jump_optimize): Unconditionally use the code that was
	previously conditional on PRESERVE_DEATH_INFO_REGNO_P.
	* reload1.c (reload): When reloading is finished, delete all
	REG_DEAD and REG_UNUSED notes.
	(emit_reload_insns): Delete all code that was conditional on
	PRESERVE_DEATH_INFO_REGNO_P.

	(eliminable_regs, eliminated_regs, not_eliminated_regs): New static
	variables.
	(update_eliminables): Compute their values.
	(init_elim_table): Likewise.

	(set_regs, set_regs_nonote, used_regs, live_regs): New static
	variables.
	(find_set_and_used_regs): New function.
	(calc_reg_usage): New function.
	(reload_life_analysis): New function.
	(no_longer_dead_regs): Delete variable.
	(reload_cse_delete_death_notes): Delete function.
	(reload_cse_no_longer_dead): Delete function.
	(reload_cse_regs_1): Delete all code to handle deletion of death
	notes.
	(reload_cse_noop_set_p): Likewise.
	(reload_cse_simplify_set): Likewise.
	(reload_cse_simplify_operands): Likewise.
	(reload_cse_move2add): Likewise.

	* reorg.c (used_spill_regs): Delete declaration.
	(max_label_num_after_reload): Delete declaration.
	(find_dead_or_set_registers): Don't assume that spill regs are
	dead at a CODE_LABEL.

	* rtl.h (reload_life_analysis): Declare function.

	* rtlanal.c (dead_or_set_regno_p): Death notes are always accurate,
	even after reload.
	* sched.c (sched_analyze_insn): Likewise.
	(update_flow_info): Likewise.
	* haifa-sched.c (sched_analyze_insn): Likewise.
	(update_flow_info): Likewise.

	* tm.texi (PRESERVE_DEATH_INFO_REGNO_P): Delete documentation.
	* toplev.c (max_label_num_after_reload): Delete variable.
	(rest_of_compilation): Don't set max_label_num_after_reload.
	Call reload_life_analysis after reload_cse_regs if optimizing.
	* config/gmicro/gmicro.h: Delete comment referring to
	PRESERVE_DEATH_INFO_REGNO_P.
	* config/i386/i386.h: Likewise.
	* config/m88k/m88k.h: Likewise.
	* config/m32r/m32r.h (PRESERVE_DEATH_INFO_REGNO_P): Delete definition.
	* config/sh/sh.h: Likewise.

Index: haifa-sched.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/haifa-sched.c,v
retrieving revision 1.1.1.34
diff -u -p -r1.1.1.34 haifa-sched.c
--- haifa-sched.c	1998/09/16 12:57:04	1.1.1.34
+++ haifa-sched.c	1998/10/08 07:37:34
@@ -3767,27 +3767,6 @@ sched_analyze_insn (x, insn, loop_notes)
 
     }
 
-  /* After reload, it is possible for an instruction to have a REG_DEAD note
-     for a register that actually dies a few instructions earlier.  For
-     example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
-     In this case, we must consider the insn to use the register mentioned
-     in the REG_DEAD note.  Otherwise, we may accidentally move this insn
-     after another insn that sets the register, thus getting obviously invalid
-     rtl.  This confuses reorg which believes that REG_DEAD notes are still
-     meaningful.
-
-     ??? We would get better code if we fixed reload to put the REG_DEAD
-     notes in the right places, but that may not be worth the effort.  */
-
-  if (reload_completed)
-    {
-      rtx note;
-
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-	if (REG_NOTE_KIND (note) == REG_DEAD)
-	  sched_analyze_2 (XEXP (note, 0), insn);
-    }
-
   EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
 			     {
 			       /* reg_last_sets[r] is now a list of insns */
@@ -8007,16 +7986,7 @@ update_flow_info (notes, first, last, or
 	         register that was not needed by this instantiation of the
 	         pattern, so we can safely ignore it.  */
 	      if (insn == first)
-		{
-		  /* After reload, REG_DEAD notes come sometimes an
-		     instruction after the register actually dies.  */
-		  if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
-		    {
-		      XEXP (note, 1) = REG_NOTES (insn);
-		      REG_NOTES (insn) = note;
-		      break;
-		    }
-			
+		{			
 		  if (REG_NOTE_KIND (note) != REG_UNUSED)
 		    abort ();
 
Index: jump.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/jump.c,v
retrieving revision 1.1.1.24
diff -u -p -r1.1.1.24 jump.c
--- jump.c	1998/09/07 20:54:31	1.1.1.24
+++ jump.c	1998/10/08 07:37:34
@@ -480,12 +480,9 @@ jump_optimize (f, cross_jump, noop_moves
 				remove_death (dreg, trial);
 				break;
 			      }
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-			/* Deleting insn could lose a death-note for SREG
-			   so don't do it if final needs accurate
-			   death-notes.  */
-			if (PRESERVE_DEATH_INFO_REGNO_P (sreg)
-			    && (trial = find_regno_note (insn, REG_DEAD, sreg)))
+
+			/* Deleting insn could lose a death-note for SREG.  */
+			if ((trial = find_regno_note (insn, REG_DEAD, sreg)))
 			  {
 			    /* Change this into a USE so that we won't emit
 			       code for it, but still can keep the note.  */
@@ -497,7 +494,6 @@ jump_optimize (f, cross_jump, noop_moves
 			    XEXP (trial, 1) = NULL_RTX;
 			  }
 			else
-#endif
 			  delete_insn (insn);
 		      }
 		  }
Index: reload1.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/reload1.c,v
retrieving revision 1.1.1.45
diff -u -p -r1.1.1.45 reload1.c
--- reload1.c	1998/10/06 17:28:38	1.1.1.45
+++ reload1.c	1998/10/08 08:09:41
@@ -405,6 +405,10 @@ static void emit_reload_insns		PROTO((rt
 static void delete_output_reload	PROTO((rtx, int, rtx));
 static void inc_for_reload		PROTO((rtx, rtx, int));
 static int constraint_accepts_reg_p	PROTO((char *, rtx));
+static void find_set_and_used_regs	PROTO((rtx, int, int));
+static void calc_reg_usage		PROTO((rtx, int));
+static void find_regs_live_at_end	PROTO((HARD_REG_SET *));
+
 static void reload_cse_regs_1		PROTO((rtx));
 static void reload_cse_invalidate_regno	PROTO((int, enum machine_mode, int));
 static int reload_cse_mem_conflict_p	PROTO((rtx, rtx));
@@ -416,8 +420,6 @@ static int reload_cse_simplify_set	PROTO
 static int reload_cse_simplify_operands	PROTO((rtx));
 static void reload_cse_check_clobber	PROTO((rtx, rtx));
 static void reload_cse_record_set	PROTO((rtx, rtx));
-static void reload_cse_delete_death_notes	PROTO((rtx));
-static void reload_cse_no_longer_dead	PROTO((int, enum machine_mode));
 static void reload_combine PROTO((void));
 static void reload_combine_note_use PROTO((rtx *, rtx));
 static void reload_combine_note_store PROTO((rtx, rtx));
@@ -1211,17 +1213,13 @@ reload (first, global, dumpfile)
     }
 
   /* Make a pass over all the insns and delete all USEs which we inserted
-     only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P
-     is defined, also remove death notes for things that are no longer
-     registers or no longer die in the insn (e.g., an input and output
-     pseudo being tied).  */
+     only to tag a REG_EQUAL note on them.  Also remove all REG_DEAD and
+     REG_UNUSED notes.  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
       {
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-	rtx note, next;
-#endif
+	rtx *pnote;
 
 	if (GET_CODE (PATTERN (insn)) == USE
 	    && find_reg_note (insn, REG_EQUAL, NULL_RTX))
@@ -1231,16 +1229,16 @@ reload (first, global, dumpfile)
 	    NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 	    continue;
 	  }
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-	for (note = REG_NOTES (insn); note; note = next)
+
+	pnote = &REG_NOTES (insn);
+	while (*pnote != 0)
 	  {
-	    next = XEXP (note, 1);
-	    if (REG_NOTE_KIND (note) == REG_DEAD
-		&& (GET_CODE (XEXP (note, 0)) != REG
-		    || reg_set_p (XEXP (note, 0), PATTERN (insn))))
-	      remove_note (insn, note);
+	    if (REG_NOTE_KIND (*pnote) == REG_DEAD
+		|| REG_NOTE_KIND (*pnote) == REG_UNUSED)
+	      *pnote = XEXP (*pnote, 1);
+	    else
+	      pnote = &XEXP (*pnote, 1);
 	  }
-#endif
       }
 
   /* If we are doing stack checking, give a warning if this function's
@@ -3335,6 +3333,10 @@ eliminate_regs (x, mem_mode, insn)
   return x;
 }
 
+static HARD_REG_SET eliminable_regs;
+static HARD_REG_SET eliminated_regs;
+static HARD_REG_SET not_eliminated_regs;
+
 /* Scan INSN and eliminate all eliminable registers in it.
 
    If REPLACE is nonzero, do the replacement destructively.  Also
@@ -3737,8 +3739,12 @@ update_eliminables (pset)
      no elimination of the frame pointer that we can perform.  */
 
   frame_pointer_needed = 1;
+  CLEAR_HARD_REG_SET (eliminated_regs);
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     {
+      if (ep->can_eliminate)
+	SET_HARD_REG_BIT (eliminated_regs, ep->from);
+
       if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
 	  && ep->to != HARD_FRAME_POINTER_REGNUM)
 	frame_pointer_needed = 0;
@@ -3750,6 +3756,8 @@ update_eliminables (pset)
 	  num_eliminable--;
 	}
     }
+  COPY_HARD_REG_SET (not_eliminated_regs, eliminable_regs);
+  AND_COMPL_HARD_REG_SET (not_eliminated_regs, eliminated_regs);
 
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   /* If we didn't need a frame pointer last time, but we do now, spill
@@ -3765,6 +3773,9 @@ init_elim_table ()
 {
   struct elim_table *ep;
 
+  CLEAR_HARD_REG_SET (eliminable_regs);
+  CLEAR_HARD_REG_SET (eliminated_regs);
+
   /* Does this function require a frame pointer?  */
 
   frame_pointer_needed = (! flag_omit_frame_pointer
@@ -3802,7 +3813,12 @@ init_elim_table ()
       num_eliminable += ep->can_eliminate;
       ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
+      SET_HARD_REG_BIT (eliminable_regs, ep->from);
+      if (ep->can_eliminate)
+	SET_HARD_REG_BIT (eliminated_regs, ep->from);
     }
+  COPY_HARD_REG_SET (not_eliminated_regs, eliminable_regs);
+  AND_COMPL_HARD_REG_SET (not_eliminated_regs, eliminated_regs);
 }
 
 /* Kick all pseudos out of hard register REGNO.
@@ -6821,28 +6837,6 @@ emit_reload_insns (insn, bb)
 		gen_reload (reloadreg, oldequiv, reload_opnum[j],
 			    reload_when_needed[j]);
 
-#if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
-	      /* We may have to make a REG_DEAD note for the secondary reload
-		 register in the insns we just made.  Find the last insn that
-		 mentioned the register.  */
-	      if (! special && second_reload_reg
-		  && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reload_reg)))
-		{
-		  rtx prev;
-
-		  for (prev = get_last_insn (); prev;
-		       prev = PREV_INSN (prev))
-		    if (GET_RTX_CLASS (GET_CODE (prev) == 'i')
-			&& reg_overlap_mentioned_for_reload_p (second_reload_reg,
-							       PATTERN (prev)))
-		      {
-			REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_DEAD,
-							      second_reload_reg,
-							      REG_NOTES (prev));
-			break;
-		      }
-		}
-#endif
 	    }
 
 	  this_reload_insn = get_last_insn ();
@@ -6864,119 +6858,7 @@ emit_reload_insns (insn, bb)
 	  reload_in[j]
 	    = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
 	}
-      /* Add a note saying the input reload reg
-	 dies in this insn, if anyone cares.  */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-      if (old != 0
-	  && reload_reg_rtx[j] != old
-	  && reload_reg_rtx[j] != 0
-	  && reload_out[j] == 0
-	  && ! reload_inherited[j]
-	  && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j])))
-	{
-	  register rtx reloadreg = reload_reg_rtx[j];
 
-#if 0
-	  /* We can't abort here because we need to support this for sched.c.
-	     It's not terrible to miss a REG_DEAD note, but we should try
-	     to figure out how to do this correctly.  */
-	  /* The code below is incorrect for address-only reloads.  */
-	  if (reload_when_needed[j] != RELOAD_OTHER
-	      && reload_when_needed[j] != RELOAD_FOR_INPUT)
-	    abort ();
-#endif
-
-	  /* Add a death note to this insn, for an input reload.  */
-
-	  if ((reload_when_needed[j] == RELOAD_OTHER
-	       || reload_when_needed[j] == RELOAD_FOR_INPUT)
-	      && ! dead_or_set_p (insn, reloadreg))
-	    REG_NOTES (insn)
-	      = gen_rtx_EXPR_LIST (REG_DEAD,
-				   reloadreg, REG_NOTES (insn));
-	}
-
-      /* When we inherit a reload, the last marked death of the reload reg
-	 may no longer really be a death.  */
-      if (reload_reg_rtx[j] != 0
-	  && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j]))
-	  && reload_inherited[j])
-	{
-	  /* Handle inheriting an output reload.
-	     Remove the death note from the output reload insn.  */
-	  if (reload_spill_index[j] >= 0
-	      && GET_CODE (reload_in[j]) == REG
-	      && spill_reg_store[reload_spill_index[j]] != 0
-	      && find_regno_note (spill_reg_store[reload_spill_index[j]],
-				  REG_DEAD, REGNO (reload_reg_rtx[j])))
-	    remove_death (REGNO (reload_reg_rtx[j]),
-			  spill_reg_store[reload_spill_index[j]]);
-	  /* Likewise for input reloads that were inherited.  */
-	  else if (reload_spill_index[j] >= 0
-		   && GET_CODE (reload_in[j]) == REG
-		   && spill_reg_store[reload_spill_index[j]] == 0
-		   && reload_inheritance_insn[j] != 0
-		   && find_regno_note (reload_inheritance_insn[j], REG_DEAD,
-				       REGNO (reload_reg_rtx[j])))
-	    remove_death (REGNO (reload_reg_rtx[j]),
-			  reload_inheritance_insn[j]);
-	  else
-	    {
-	      rtx prev;
-
-	      /* We got this register from find_equiv_reg.
-		 Search back for its last death note and get rid of it.
-		 But don't search back too far.
-		 Don't go past a place where this reg is set,
-		 since a death note before that remains valid.  */
-	      for (prev = PREV_INSN (insn);
-		   prev && GET_CODE (prev) != CODE_LABEL;
-		   prev = PREV_INSN (prev))
-		if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
-		    && dead_or_set_p (prev, reload_reg_rtx[j]))
-		  {
-		    if (find_regno_note (prev, REG_DEAD,
-					 REGNO (reload_reg_rtx[j])))
-		      remove_death (REGNO (reload_reg_rtx[j]), prev);
-		    break;
-		  }
-	    }
-	}
-
-      /* We might have used find_equiv_reg above to choose an alternate
-	 place from which to reload.  If so, and it died, we need to remove
-	 that death and move it to one of the insns we just made.  */
-
-      if (oldequiv_reg != 0
-	  && PRESERVE_DEATH_INFO_REGNO_P (true_regnum (oldequiv_reg)))
-	{
-	  rtx prev, prev1;
-
-	  for (prev = PREV_INSN (insn); prev && GET_CODE (prev) != CODE_LABEL;
-	       prev = PREV_INSN (prev))
-	    if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
-		&& dead_or_set_p (prev, oldequiv_reg))
-	      {
-		if (find_regno_note (prev, REG_DEAD, REGNO (oldequiv_reg)))
-		  {
-		    for (prev1 = this_reload_insn;
-			 prev1; prev1 = PREV_INSN (prev1))
-		      if (GET_RTX_CLASS (GET_CODE (prev1) == 'i')
-			&& reg_overlap_mentioned_for_reload_p (oldequiv_reg,
-							       PATTERN (prev1)))
-		      {
-			REG_NOTES (prev1) = gen_rtx_EXPR_LIST (REG_DEAD,
-							       oldequiv_reg,
-							       REG_NOTES (prev1));
-			break;
-		      }
-		    remove_death (REGNO (oldequiv_reg), prev);
-		  }
-		break;
-	      }
-	}
-#endif
-
       /* If we are reloading a register that was recently stored in with an
 	 output-reload, see if we can prove there was
 	 actually no need to store the old value in it.  */
@@ -7181,30 +7063,6 @@ emit_reload_insns (insn, bb)
 			    reload_when_needed[j]);
 	    }
 
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-	  /* If final will look at death notes for this reg,
-	     put one on the last output-reload insn to use it.  Similarly
-	     for any secondary register.  */
-	  if (PRESERVE_DEATH_INFO_REGNO_P (REGNO (reloadreg)))
-	    for (p = get_last_insn (); p; p = PREV_INSN (p))
-	      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-		  && reg_overlap_mentioned_for_reload_p (reloadreg,
-							 PATTERN (p)))
-		REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
-						   reloadreg, REG_NOTES (p));
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
-	  if (! special && second_reloadreg
-	      && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reloadreg)))
-	    for (p = get_last_insn (); p; p = PREV_INSN (p))
-	      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-		  && reg_overlap_mentioned_for_reload_p (second_reloadreg,
-							 PATTERN (p)))
-		REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
-						   second_reloadreg,
-						   REG_NOTES (p));
-#endif
-#endif
 	  /* Look at all insns we emitted, just to be safe.  */
 	  for (p = get_insns (); p; p = NEXT_INSN (p))
 	    if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
@@ -7329,50 +7187,6 @@ emit_reload_insns (insn, bb)
         basic_block_end[bb] = PREV_INSN (following_insn);
     }
 
-  /* Move death notes from INSN
-     to output-operand-address and output reload insns.  */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-  {
-    rtx insn1;
-    /* Loop over those insns, last ones first.  */
-    for (insn1 = PREV_INSN (following_insn); insn1 != insn;
-	 insn1 = PREV_INSN (insn1))
-      if (GET_CODE (insn1) == INSN && GET_CODE (PATTERN (insn1)) == SET)
-	{
-	  rtx source = SET_SRC (PATTERN (insn1));
-	  rtx dest = SET_DEST (PATTERN (insn1));
-
-	  /* The note we will examine next.  */
-	  rtx reg_notes = REG_NOTES (insn);
-	  /* The place that pointed to this note.  */
-	  rtx *prev_reg_note = &REG_NOTES (insn);
-
-	  /* If the note is for something used in the source of this
-	     reload insn, or in the output address, move the note.  */
-	  while (reg_notes)
-	    {
-	      rtx next_reg_notes = XEXP (reg_notes, 1);
-	      if (REG_NOTE_KIND (reg_notes) == REG_DEAD
-		  && GET_CODE (XEXP (reg_notes, 0)) == REG
-		  && ((GET_CODE (dest) != REG
-		       && reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
-							      dest))
-		      || reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
-							     source)))
-		{
-		  *prev_reg_note = next_reg_notes;
-		  XEXP (reg_notes, 1) = REG_NOTES (insn1);
-		  REG_NOTES (insn1) = reg_notes;
-		}
-	      else
-		prev_reg_note = &XEXP (reg_notes, 1);
-
-	      reg_notes = next_reg_notes;
-	    }
-	}
-  }
-#endif
-
   /* For all the spill regs newly reloaded in this instruction,
      record what they were reloaded from, so subsequent instructions
      can inherit the reloads.
@@ -8080,6 +7894,313 @@ count_occurrences (x, find)
   return count;
 }
 
+static HARD_REG_SET set_regs;
+static HARD_REG_SET set_regs_nonote;
+static HARD_REG_SET used_regs;
+static HARD_REG_SET live_regs;
+
+/* Walk the rtx X recursively, calling WORKER for every sub-expression with
+   the type of access as parameter.  */
+static void
+find_set_and_used_regs (x, read, written)
+     rtx x;
+     int read, written;
+{
+  enum rtx_code code;
+  const char *fmt;
+  int i, regno, nregs;
+
+  if (0 && x == 0)
+    return;
+
+  code = GET_CODE (x);
+  if (code == SUBREG)
+    {
+      x = SUBREG_REG (x);
+      code = GET_CODE (x);
+    }
+
+  switch (code)
+    {
+    case PC:
+    case CC0:
+    case SCRATCH:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      return;
+
+    case REG:
+      regno = REGNO (x);
+      if (regno >= FIRST_PSEUDO_REGISTER)
+	return;
+      nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
+      while (nregs-- > 0)
+	{
+	  if (written)
+	    SET_HARD_REG_BIT (set_regs, regno + nregs);
+	  if (read)
+	    SET_HARD_REG_BIT (used_regs, regno + nregs);
+	}
+      return;
+
+    case ZERO_EXTRACT:
+    case SIGN_EXTRACT:
+      find_set_and_used_regs (XEXP (x, 0), read, written);
+      find_set_and_used_regs (XEXP (x, 1), 1, 0);
+      find_set_and_used_regs (XEXP (x, 2), 1, 0);
+      return;
+      
+    case PRE_DEC:
+    case POST_DEC:
+    case PRE_INC:
+    case POST_INC:
+      find_set_and_used_regs (XEXP (x, 0), 1, 1);
+      return;
+      
+    case SET:
+      find_set_and_used_regs (SET_SRC (x), 1, 0);
+
+      /* fall through */
+    case CLOBBER:
+      find_set_and_used_regs (SET_DEST (x), 0, 1);
+      return;
+
+    default:
+      break;
+    }
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+	find_set_and_used_regs (XEXP (x, i), 1, 0);
+      else if (fmt[i] == 'E')
+	{
+	  int j;
+
+	  for (j = 0; j < XVECLEN (x, i); j++)
+	    find_set_and_used_regs (XVECEXP (x, i, j), 1, 0);
+	}
+    }
+}
+
+/* Fill the reg sets set_regs and used_regs with information about the usage
+   of registers within this insn.  If MAKE_NOTES is nonzero, create
+   appropriate REG_DEAD/REG_UNUSED notes.  */
+static void
+calc_reg_usage (insn, make_notes)
+     rtx insn;
+     int make_notes;
+{
+  int i;
+
+  CLEAR_HARD_REG_SET (set_regs);
+  CLEAR_HARD_REG_SET (set_regs_nonote);
+  CLEAR_HARD_REG_SET (used_regs);
+  find_set_and_used_regs (PATTERN (insn), 0, 0);
+
+  if (GET_CODE (insn) == CALL_INSN)
+    {
+      rtx x;
+      for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0; x = XEXP (x, 1))
+	find_set_and_used_regs (XEXP (x, 0), 0, 0);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	if (call_used_regs[i] && ! fixed_regs[i] && ! global_regs[i])
+	  SET_HARD_REG_BIT (set_regs_nonote, i);
+    }
+
+  IOR_HARD_REG_SET (set_regs, set_regs_nonote);
+
+  if (! make_notes)
+    return;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      /* Fixed and global regs are live throughout the function.  The
+	 same applies to regs we didn't eliminate.  */
+      if (fixed_regs[i] || global_regs [i]
+	  || TEST_HARD_REG_BIT (not_eliminated_regs, i)
+	  || TEST_HARD_REG_BIT (live_regs, i))
+	continue;
+
+      if (TEST_HARD_REG_BIT (set_regs, i)
+	  && ! TEST_HARD_REG_BIT (set_regs_nonote, i))
+	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED,
+					      gen_rtx_REG (reg_raw_mode[i], i),
+					      REG_NOTES (insn));
+      else if (TEST_HARD_REG_BIT (used_regs, i))
+	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD,
+					      gen_rtx_REG (reg_raw_mode[i], i),
+					      REG_NOTES (insn));
+    }
+  AND_COMPL_HARD_REG_SET (live_regs, set_regs);
+  IOR_HARD_REG_SET (live_regs, used_regs);
+}
+
+/* Fill *PREGSET with those registers which must be live at the end of the
+   function.  */
+static void
+find_regs_live_at_end (pregset)
+     HARD_REG_SET *pregset;
+{
+  int i;
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (global_regs[i]
+#ifdef EPILOGUE_USES
+	  || EPILOGUE_USES (i)
+#endif
+	  )
+	SET_HARD_REG_BIT (*pregset, i);
+    }
+
+  IOR_HARD_REG_SET (*pregset, fixed_reg_set);
+  IOR_HARD_REG_SET (*pregset, not_eliminated_regs);
+}
+
+/* Now that all pseudo registers have been eliminated, calculate hard register
+   life information.  */
+void
+reload_life_analysis (first)
+     rtx first;
+{
+  rtx insn, last;
+  int b;
+  int_list_ptr *s_preds, *s_succs;
+  int *num_preds, *num_succs;
+  HARD_REG_SET *block_sets;
+  HARD_REG_SET *block_uses;
+  HARD_REG_SET *live_at_start;
+  HARD_REG_SET *live_at_end;
+  int outside_block = 1;
+
+  if (n_basic_blocks == 0)
+    return;
+
+  s_preds = (int_list_ptr *) xmalloc (n_basic_blocks * sizeof (int_list_ptr));
+  s_succs = (int_list_ptr *) xmalloc (n_basic_blocks * sizeof (int_list_ptr));
+  num_preds = (int *) xmalloc (n_basic_blocks * sizeof (int));
+  num_succs = (int *) xmalloc (n_basic_blocks * sizeof (int));
+  block_sets = (HARD_REG_SET *) xmalloc (n_basic_blocks * sizeof (HARD_REG_SET));
+  block_uses = (HARD_REG_SET *) xmalloc (n_basic_blocks * sizeof (HARD_REG_SET));
+  live_at_start = (HARD_REG_SET *) xmalloc (n_basic_blocks * sizeof (HARD_REG_SET));
+  live_at_end = (HARD_REG_SET *) xmalloc (n_basic_blocks * sizeof (HARD_REG_SET));
+
+  bzero (block_sets, n_basic_blocks * sizeof (HARD_REG_SET));
+  bzero (block_uses, n_basic_blocks * sizeof (HARD_REG_SET));
+  bzero (live_at_start, n_basic_blocks * sizeof (HARD_REG_SET));
+  bzero (live_at_end, n_basic_blocks * sizeof (HARD_REG_SET));
+
+  find_regs_live_at_end (live_at_end + n_basic_blocks - 1);
+
+  compute_preds_succs (s_preds, s_succs, num_preds, num_succs);
+
+  b = n_basic_blocks;
+  for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+    ;
+  for (insn = last; insn; insn = PREV_INSN (insn))
+    {
+      enum rtx_code code = GET_CODE (insn);
+
+      /* Start with fresh live info at the end of every basic block.  */
+      if (b > 0 && basic_block_end[b - 1] == insn)
+	{
+	  outside_block = 0;
+	  b--;
+	}
+      /* Clobbers are inserted during rtl expansion to show flow.c that some
+	 values die when that is non-obvious.  Once all pseudos are converted
+	 to hard regs, that information is no longer needed, and can in fact
+	 be incorrect.
+         Some of them are also inserted during reload, and may be outside a
+	 basic block, so NOTEify them before aborting on an outside block
+	 insn.  */
+      if (GET_RTX_CLASS (code) == 'i' && GET_CODE (PATTERN (insn)) == CLOBBER)
+	{
+	  PUT_CODE (insn, NOTE);
+	  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+	  NOTE_SOURCE_FILE (insn) = 0;
+	  code = NOTE;
+	}
+
+      if (GET_RTX_CLASS (code) == 'i' && outside_block)
+	abort ();
+
+      if (GET_RTX_CLASS (code) == 'i')
+	{
+	  calc_reg_usage (insn, 0);
+
+	  IOR_HARD_REG_SET (block_sets[b], set_regs);
+	  AND_COMPL_HARD_REG_SET (block_sets[b], used_regs);
+
+	  AND_COMPL_HARD_REG_SET (block_uses[b], set_regs);
+	  IOR_HARD_REG_SET (block_uses[b], used_regs);
+	}
+
+      if (insn == basic_block_head[b])
+	{
+	  outside_block = 1;
+	}
+    }
+  for (;;)
+    {
+      int something_changed = 0;
+
+      for (b = n_basic_blocks - 1; b >= 0; b--)
+	{
+	  int_list_ptr psucc;
+	  HARD_REG_SET tmp;
+
+	  CLEAR_HARD_REG_SET (live_at_end[b]);
+	  for (psucc = s_succs[b]; psucc; psucc = psucc->next)
+	    IOR_HARD_REG_SET (live_at_end[b],
+			      live_at_start[INT_LIST_VAL (psucc)]);
+	  COPY_HARD_REG_SET (tmp, live_at_end[b]);
+	  AND_COMPL_HARD_REG_SET (tmp, block_sets[b]);
+	  IOR_HARD_REG_SET (tmp, block_uses[b]);
+	  GO_IF_HARD_REG_EQUAL (tmp, live_at_start[b], win);
+	  COPY_HARD_REG_SET (live_at_start[b], tmp);
+	  something_changed = 1;
+
+	win:
+	  ;
+	}
+      if (! something_changed)
+	break;
+    }
+  for (b = 0; b < n_basic_blocks; b++)
+    {
+      int i;
+      CLEAR_REG_SET (basic_block_live_at_start[b]);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	if (TEST_HARD_REG_BIT (live_at_start[b], i))
+	  SET_REGNO_REG_SET (basic_block_live_at_start[b], i);
+    }
+  for (insn = last; insn; insn = PREV_INSN (insn))
+    {
+      enum rtx_code code = GET_CODE (insn);
+
+      /* Start with fresh live info at the end of every basic block.  */
+      if (b > 0 && basic_block_end[b - 1] == insn)
+	{
+	  b--;
+	  COPY_HARD_REG_SET (live_regs, live_at_end[b]);
+	}
+
+      if (GET_RTX_CLASS (code) == 'i')
+	calc_reg_usage (insn, 1);
+    }
+
+  free (s_preds);
+  free (s_succs);
+  free (num_preds);
+  free (num_succs);
+  free (block_sets);
+  free (block_uses);
+  free (live_at_end);
+  free (live_at_start);
+}
+
 /* This array holds values which are equivalent to a hard register
    during reload_cse_regs.  Each array element is an EXPR_LIST of
    values.  Each time a hard register is set, we set the corresponding
@@ -8102,13 +8223,6 @@ static rtx *reg_values;
 
 static rtx invalidate_regno_rtx;
 
-/* This is a set of registers for which we must remove REG_DEAD notes in
-   previous insns, because our modifications made them invalid.  That can
-   happen if we introduced the register into the current insn, or we deleted
-   the current insn which used to set the register.  */
-
-static HARD_REG_SET no_longer_dead_regs;
-
 /* Invalidate any entries in reg_values which depend on REGNO,
    including those for REGNO itself.  This is called if REGNO is
    changing.  If CLOBBER is true, then always forget anything we
@@ -8311,55 +8425,6 @@ reload_cse_invalidate_rtx (dest, ignore)
     reload_cse_invalidate_mem (dest);
 }
 
-/* Possibly delete death notes on the insns before INSN if modifying INSN
-   extended the lifespan of the registers.  */
-
-static void
-reload_cse_delete_death_notes (insn)
-     rtx insn;
-{
-  int dreg;
-
-  for (dreg = 0; dreg < FIRST_PSEUDO_REGISTER; dreg++)
-    {
-      rtx trial;
-
-      if (! TEST_HARD_REG_BIT (no_longer_dead_regs, dreg))
-	continue;
-
-      for (trial = prev_nonnote_insn (insn);
-	   (trial
-	    && GET_CODE (trial) != CODE_LABEL
-	    && GET_CODE (trial) != BARRIER);
-	   trial = prev_nonnote_insn (trial))
-	{
-	  if (find_regno_note (trial, REG_DEAD, dreg))
-	    {
-	      remove_death (dreg, trial);
-	      break;
-	    }
-	}
-    }
-}
-
-/* Record that the current insn uses hard reg REGNO in mode MODE.  This
-   will be used in reload_cse_delete_death_notes to delete prior REG_DEAD
-   notes for this register.  */
-
-static void
-reload_cse_no_longer_dead (regno, mode)
-     int regno;
-     enum machine_mode mode;
-{
-  int nregs = HARD_REGNO_NREGS (regno, mode);
-  while (nregs-- > 0)
-    {
-      SET_HARD_REG_BIT (no_longer_dead_regs, regno);
-      regno++;
-    }
-}
-
-
 /* Do a very simple CSE pass over the hard registers.
 
    This function detects no-op moves where we happened to assign two
@@ -8432,8 +8497,6 @@ reload_cse_regs_1 (first)
       if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
 	continue;
 
-      CLEAR_HARD_REG_SET (no_longer_dead_regs);
-
       /* If this is a call instruction, forget anything stored in a
 	 call clobbered register, or, if this is not a const call, in
 	 memory.  */
@@ -8474,20 +8537,18 @@ reload_cse_regs_1 (first)
 		  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 		  NOTE_SOURCE_FILE (insn) = 0;
 		}
-	      reload_cse_delete_death_notes (insn);
 
 	      /* We're done with this insn.  */
 	      continue;
 	    }
 
 	  /* It's not a no-op, but we can try to simplify it.  */
-	  CLEAR_HARD_REG_SET (no_longer_dead_regs);
 	  count += reload_cse_simplify_set (body, insn);
 
-	  if (count > 0 && apply_change_group ())
-	    reload_cse_delete_death_notes (insn);
-	  else if (reload_cse_simplify_operands (insn))
-	    reload_cse_delete_death_notes (insn);
+	  if (count > 0)
+	    apply_change_group ();
+	  else
+	    reload_cse_simplify_operands (insn);
 	    
 	  reload_cse_record_set (body, body);
 	}
@@ -8531,22 +8592,20 @@ reload_cse_regs_1 (first)
 		  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 		  NOTE_SOURCE_FILE (insn) = 0;
 		}
-	      reload_cse_delete_death_notes (insn);
 
 	      /* We're done with this insn.  */
 	      continue;
 	    }
 	  
 	  /* It's not a no-op, but we can try to simplify it.  */
-	  CLEAR_HARD_REG_SET (no_longer_dead_regs);
 	  for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
 	    if (GET_CODE (XVECEXP (body, 0, i)) == SET)
 	      count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
 
-	  if (count > 0 && apply_change_group ())
-	    reload_cse_delete_death_notes (insn);
-	  else if (reload_cse_simplify_operands (insn))
-	    reload_cse_delete_death_notes (insn);
+	  if (count > 0)
+	    apply_change_group ();
+	  else
+	    reload_cse_simplify_operands (insn);
 
 	  /* Look through the PARALLEL and record the values being
              set, if possible.  Also handle any CLOBBERs.  */
@@ -8725,14 +8784,6 @@ reload_cse_noop_set_p (set, insn)
 	ret = 1;
     }
 
-  /* If we can delete this SET, then we need to look for an earlier
-     REG_DEAD note on DREG, and remove it if it exists.  */
-  if (ret && dreg >= 0)
-    {
-      if (! find_regno_note (insn, REG_UNUSED, dreg))
-	reload_cse_no_longer_dead (dreg, dest_mode);
-    }
-
   return ret;
 }
 
@@ -8792,11 +8843,8 @@ reload_cse_simplify_set (set, insn)
              storage.  */
 	  push_obstacks (&reload_obstack, &reload_obstack);
 
-	  if (validated && ! find_regno_note (insn, REG_UNUSED, i))
-	    {
-	      reload_cse_no_longer_dead (i, dest_mode);
-	      return 1;
-	    }
+	  if (validated)
+	    return 1;
 	}
     }
   return 0;
@@ -9001,7 +9049,6 @@ reload_cse_simplify_operands (insn)
   /* Substitute the operands as determined by op_alt_regno for the best
      alternative.  */
   j = alternative_order[0];
-  CLEAR_HARD_REG_SET (no_longer_dead_regs);
 
   /* Pop back to the real obstacks while changing the insn.  */
   pop_obstacks ();
@@ -9012,7 +9059,6 @@ reload_cse_simplify_operands (insn)
       if (op_alt_regno[i][j] == -1)
 	continue;
 
-      reload_cse_no_longer_dead (op_alt_regno[i][j], mode);
       validate_change (insn, recog_operand_loc[i],
 		       gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
     }
@@ -9025,7 +9071,6 @@ reload_cse_simplify_operands (insn)
       if (op_alt_regno[op][j] == -1)
 	continue;
 
-      reload_cse_no_longer_dead (op_alt_regno[op][j], mode);
       validate_change (insn, recog_dup_loc[i],
 		       gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
     }
@@ -9612,8 +9657,7 @@ static int reg_base_reg[FIRST_PSEUDO_REG
 static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
 /* move2add_luid is linearily increased while scanning the instructions
    from first to last.  It is used to set reg_set_luid in
-   reload_cse_move2add and move2add_note_store, and to set reg_death_luid
-   (local variable of reload_cse_move2add) .  */
+   reload_cse_move2add and move2add_note_store.  */
 static int move2add_luid;
 
 static void
@@ -9623,16 +9667,10 @@ reload_cse_move2add (first)
   int i;
   rtx insn;
   int last_label_luid;
-  /* reg_death and reg_death_luid are solely used to remove stale REG_DEAD
-     notes.  */
-  int reg_death_luid[FIRST_PSEUDO_REGISTER];
-  rtx reg_death[FIRST_PSEUDO_REGISTER];
 
   for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
-    {
-      reg_set_luid[i] = 0;
-      reg_death_luid[i] = 0;
-    }
+    reg_set_luid[i] = 0;
+
   last_label_luid = 0;
   move2add_luid = 1;
   for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
@@ -9687,8 +9725,6 @@ reload_cse_move2add (first)
 			   && have_add2_insn (GET_MODE (reg)))
 		    success = validate_change (insn, &PATTERN (insn),
 					       gen_add2_insn (reg, new_src), 0);
-		  if (success && reg_death_luid[regno] > reg_set_luid[regno])
-		    remove_death (regno, reg_death[regno]);
 		  reg_set_luid[regno] = move2add_luid;
 		  reg_mode[regno] = GET_MODE (reg);
 		  reg_offset[regno] = src;
@@ -9738,8 +9774,6 @@ reload_cse_move2add (first)
 					     gen_add2_insn (reg, new_src), 0);
 		      if (success)
 			{
-			  if (reg_death_luid[regno] > reg_set_luid[regno])
-			    remove_death (regno, reg_death[regno]);
 			  /* INSN might be the first insn in a basic block
 			     if the preceding insn is a conditional jump
 			     or a possible-throwing call.  */
@@ -9769,18 +9803,6 @@ reload_cse_move2add (first)
 		{
 		  reg_set_luid[regno] = move2add_luid;
 		  reg_offset[regno] = note;
-		}
-	    }
-	  /* Remember any REG_DEAD notes so that we can remove them
-	     later if necessary.  */
-	  else if (REG_NOTE_KIND (note) == REG_DEAD
-	      && GET_CODE (XEXP (note, 0)) == REG)
-	    {
-	      int regno = REGNO (XEXP (note, 0));
-	      if (regno < FIRST_PSEUDO_REGISTER)
-		{
-		  reg_death[regno] = insn;
-		  reg_death_luid[regno] = move2add_luid;
 		}
 	    }
 	}
Index: reorg.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/reorg.c,v
retrieving revision 1.1.1.22
diff -u -p -r1.1.1.22 reorg.c
--- reorg.c	1998/10/01 14:39:40	1.1.1.22
+++ reorg.c	1998/10/08 07:37:34
@@ -131,13 +131,7 @@ Boston, MA 02111-1307, USA.  */
 #include "obstack.h"
 #include "insn-attr.h"
 
-/* Import list of registers used as spill regs from reload.  */
-extern HARD_REG_SET used_spill_regs;
 
-/* Import highest label used in function at end of reload.  */
-extern int max_label_num_after_reload;
-
-
 #ifdef DELAY_SLOTS
 
 #define obstack_chunk_alloc xmalloc
@@ -2584,14 +2578,6 @@ find_dead_or_set_registers (target, res,
 	  AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
 	  CLEAR_HARD_REG_SET (pending_dead_regs);
 
-	  if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
-	    {
-	      /* All spill registers are dead at a label, so kill all of the
-		 ones that aren't needed also.  */
-	      COPY_HARD_REG_SET (scratch, used_spill_regs);
-	      AND_COMPL_HARD_REG_SET (scratch, needed.regs);
-	      AND_COMPL_HARD_REG_SET (res->regs, scratch);
-	    }
 	  continue;
 
 	case BARRIER:
Index: rtl.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/rtl.h,v
retrieving revision 1.1.1.36
diff -u -p -r1.1.1.36 rtl.h
--- rtl.h	1998/10/05 10:52:19	1.1.1.36
+++ rtl.h	1998/10/08 07:37:34
@@ -1488,6 +1488,7 @@ extern void local_alloc			PROTO ((void))
 
 /* In reload1.c */
 extern void reload_cse_regs		PROTO ((rtx));
+extern void reload_life_analysis	PROTO ((rtx));
 extern void init_reload			PROTO ((void));
 extern void mark_home_live		PROTO ((int));
 #ifdef BUFSIZ
Index: rtlanal.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/rtlanal.c,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 rtlanal.c
--- rtlanal.c	1998/09/16 12:57:21	1.1.1.15
+++ rtlanal.c	1998/10/08 07:37:34
@@ -1194,30 +1194,21 @@ dead_or_set_regno_p (insn, test_regno)
   int regno, endregno;
   rtx link;
 
-  /* REG_READ notes are not normally maintained after reload, so we
-     ignore them if the are invalid.  */
-  if (! reload_completed
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-      || PRESERVE_DEATH_INFO_REGNO_P (test_regno)
-#endif
-      )
+  /* See if there is a death note for something that includes
+     TEST_REGNO.  */
+  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     {
-      /* See if there is a death note for something that includes
-         TEST_REGNO.  */
-      for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-	{
-	  if (REG_NOTE_KIND (link) != REG_DEAD
-	      || GET_CODE (XEXP (link, 0)) != REG)
-	    continue;
+      if (REG_NOTE_KIND (link) != REG_DEAD
+	  || GET_CODE (XEXP (link, 0)) != REG)
+	continue;
 
-	  regno = REGNO (XEXP (link, 0));
-	  endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
-		      : regno + HARD_REGNO_NREGS (regno,
-						  GET_MODE (XEXP (link, 0))));
+      regno = REGNO (XEXP (link, 0));
+      endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
+		  : regno + HARD_REGNO_NREGS (regno,
+					      GET_MODE (XEXP (link, 0))));
 
-	  if (test_regno >= regno && test_regno < endregno)
-	    return 1;
-	}
+      if (test_regno >= regno && test_regno < endregno)
+	return 1;
     }
 
   if (GET_CODE (insn) == CALL_INSN
@@ -1231,7 +1222,7 @@ dead_or_set_regno_p (insn, test_regno)
       /* A value is totally replaced if it is the destination or the
 	 destination is a SUBREG of REGNO that does not change the number of
 	 words in it.  */
-     if (GET_CODE (dest) == SUBREG
+      if (GET_CODE (dest) == SUBREG
 	  && (((GET_MODE_SIZE (GET_MODE (dest))
 		+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 	      == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
Index: sched.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/sched.c,v
retrieving revision 1.1.1.27
diff -u -p -r1.1.1.27 sched.c
--- sched.c	1998/09/07 20:54:44	1.1.1.27
+++ sched.c	1998/10/08 07:37:34
@@ -1553,27 +1553,6 @@ sched_analyze_insn (x, insn, loop_notes)
       REG_NOTES (insn) = loop_notes;
     }
 
-  /* After reload, it is possible for an instruction to have a REG_DEAD note
-     for a register that actually dies a few instructions earlier.  For
-     example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
-     In this case, we must consider the insn to use the register mentioned
-     in the REG_DEAD note.  Otherwise, we may accidentally move this insn
-     after another insn that sets the register, thus getting obviously invalid
-     rtl.  This confuses reorg which believes that REG_DEAD notes are still
-     meaningful.
-
-     ??? We would get better code if we fixed reload to put the REG_DEAD
-     notes in the right places, but that may not be worth the effort.  */
-
-  if (reload_completed)
-    {
-      rtx note;
-
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-	if (REG_NOTE_KIND (note) == REG_DEAD)
-	  sched_analyze_2 (XEXP (note, 0), insn);
-    }
-
   EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
 			     {
 			       reg_last_sets[i] = insn;
@@ -3849,16 +3828,7 @@ update_flow_info (notes, first, last, or
 		 register that was not needed by this instantiation of the
 		 pattern, so we can safely ignore it.  */
 	      if (insn == first)
-		{
-		  /* After reload, REG_DEAD notes come sometimes an
-		     instruction after the register actually dies.  */
-		  if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
-		    {
-		      XEXP (note, 1) = REG_NOTES (insn);
-		      REG_NOTES (insn) = note;
-		      break;
-		    }
-			
+		{			
 		  if (REG_NOTE_KIND (note) != REG_UNUSED)
 		    abort ();
 
Index: tm.texi
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/tm.texi,v
retrieving revision 1.1.1.32
diff -u -p -r1.1.1.32 tm.texi
--- tm.texi	1998/10/05 10:52:24	1.1.1.32
+++ tm.texi	1998/10/08 07:37:35
@@ -1684,24 +1684,6 @@ If this macro is not defined, it means t
 mysteriously.  This is the usual situation; all else being equal,
 it is best for the RTL expression to show all the activity.
 
-@cindex death notes
-@findex PRESERVE_DEATH_INFO_REGNO_P
-@item PRESERVE_DEATH_INFO_REGNO_P (@var{regno})
-If defined, this is a C expression whose value is nonzero if correct
-@code{REG_DEAD} notes are needed for hard register number @var{regno}
-after reload.
-
-You would arrange to preserve death info for a register when some of the
-code in the machine description which is executed to write the assembler
-code looks at the death notes.  This is necessary only when the actual
-hardware feature which GNU CC thinks of as a register is not actually a
-register of the usual sort.  (It might, for example, be a hardware
-stack.)
-
-It is also useful for peepholes and linker relaxation.
-
-If this macro is not defined, it means that no death notes need to be
-preserved, and some may even be incorrect.  This is the usual situation.
 @end table
 
 @node Register Classes
Index: toplev.c
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/toplev.c,v
retrieving revision 1.1.1.47
diff -u -p -r1.1.1.47 toplev.c
--- toplev.c	1998/10/01 14:39:48	1.1.1.47
+++ toplev.c	1998/10/08 07:37:35
@@ -355,10 +355,6 @@ lang_expand_expr_t lang_expand_expr = 0;
 
 void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
 
-/* Highest label number used at the end of reload.  */
-
-int max_label_num_after_reload;
-
 /* Nonzero if generating code to do profiling.  */
 
 int profile_flag = 0;
@@ -3735,10 +3731,6 @@ rest_of_compilation (decl)
   if (global_reg_dump)
     open_dump_file (".greg", decl_printable_name (decl, 2));
 
-  /* Save the last label number used so far, so reorg can tell
-     when it's safe to kill spill regs.  */
-  max_label_num_after_reload = max_label_num ();
-
   /* Unless we did stupid register allocation,
      allocate remaining pseudo-regs, then do the reload pass
      fixing up any insns that are invalid.  */
@@ -3760,6 +3752,10 @@ rest_of_compilation (decl)
   /* Do a very simple CSE pass over just the hard registers.  */
   if (optimize > 0)
     reload_cse_regs (insns);
+
+  /* Re-create the death notes which were deleted during reload.  */
+  if (optimize)
+    reload_life_analysis (insns);
 
   /* On some machines, the prologue and epilogue code, or parts thereof,
      can be represented as RTL.  Doing so lets us schedule insns between
Index: config/gmicro/gmicro.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/gmicro/gmicro.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 gmicro.h
--- config/gmicro/gmicro.h	1998/04/04 15:44:43	1.1.1.4
+++ config/gmicro/gmicro.h	1998/10/08 07:37:40
@@ -241,7 +241,6 @@ extern int target_flags;
 /* #define OVERLAPPING_REGNO_P(REGNO) */
 
 /* #define INSN_CLOBBERS_REGNO_P(INSN,REGNO)  */
-/* #define PRESERVE_DEATH_INFO_REGNO_P(REGNO)  */
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
Index: config/i386/i386.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/i386/i386.h,v
retrieving revision 1.1.1.32
diff -u -p -r1.1.1.32 i386.h
--- config/i386/i386.h	1998/10/05 10:53:03	1.1.1.32
+++ config/i386/i386.h	1998/10/08 07:37:43
@@ -834,11 +834,6 @@ enum reg_class
 
 #define STACK_TOP_P(xop) (REG_P (xop) && REGNO (xop) == FIRST_STACK_REG)
 
-/* Try to maintain the accuracy of the death notes for regs satisfying the
-   following.  Important for stack like regs, to know when to pop. */
-
-/* #define PRESERVE_DEATH_INFO_REGNO_P(x) FP_REGNO_P(x) */
-
 /* 1 if register REGNO can magically overlap other regs.
    Note that nonzero values work only in very special circumstances. */
 
Index: config/m32r/m32r.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/m32r/m32r.h,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 m32r.h
--- config/m32r/m32r.h	1998/09/29 19:17:56	1.1.1.15
+++ config/m32r/m32r.h	1998/10/08 07:37:46
@@ -2077,9 +2077,6 @@ extern int  conditional_move_operand		PR
 extern int  carry_compare_operand		PROTO((Rtx, int));
 extern char *emit_cond_move			PROTO((Rtx *, Rtx));
 
-/* Needed by a peephole optimisation.  */
-#define PRESERVE_DEATH_INFO_REGNO_P(regno) (regno < FIRST_PSEUDO_REGISTER)
-
 extern char * m32r_output_block_move PROTO((Rtx, Rtx *));
 extern int    m32r_block_immediate_operand PROTO((Rtx, int));
 extern void   m32r_expand_block_move PROTO((Rtx *));
Index: config/m88k/m88k.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/m88k/m88k.h,v
retrieving revision 1.1.1.11
diff -u -p -r1.1.1.11 m88k.h
--- config/m88k/m88k.h	1998/09/07 20:55:31	1.1.1.11
+++ config/m88k/m88k.h	1998/10/08 07:37:48
@@ -648,7 +648,6 @@ extern char * reg_names[];
 /* These interfaces that don't apply to the m88000.  */
 /* OVERLAPPING_REGNO_P(REGNO) 0 */
 /* INSN_CLOBBERS_REGNO_P(INSN, REGNO) 0 */
-/* PRESERVE_DEATH_INFO_REGNO_P(REGNO) 0 */
 
 /* True if register is an extended register.  */
 #define XRF_REGNO_P(N) ((N) < FIRST_PSEUDO_REGISTER && (N) >= FIRST_EXTENDED_REGISTER)
Index: config/sh/sh.h
===================================================================
RCS file: /usr/local/cvs/gcs/gcc/config/sh/sh.h,v
retrieving revision 1.1.1.19
diff -u -p -r1.1.1.19 sh.h
--- config/sh/sh.h	1998/09/18 14:19:12	1.1.1.19
+++ config/sh/sh.h	1998/10/08 07:37:50
@@ -158,8 +158,6 @@ extern int target_flags;
 
 #define TARGET_DEFAULT  (0)
 
-#define PRESERVE_DEATH_INFO_REGNO_P(regno) (TARGET_RELAX || optimize)
-
 #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)				\
 do {									\
   if (SIZE)								\




More information about the Gcc-patches mailing list