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]

Patch to fix sched2 REG_DEAD note handling


This patch causes gcc to recreate the REG_DEAD notes during sched2 which
allows delete_computation to be more aggressive.

Notes:

  1) The actual changes are very minor.  The patch is rather large simply
     because of identing changes.

  2) Haifa will be addressed in a separate patch.

ChangeLog:

Thu Jun 17 01:45:09 EDT 1999  John Wehle  (john@feith.com)

	* sched.c (attach_deaths_insn): Skip prologue and epilogue insns.
	(schedule_block): Also recreate REG_DEAD notes after reload.
	(schedule_insns): Allocate and free the necessary resources to do so.
	(schedule_insns): Mark prologue and epilogue insns.
	* rtl.h (rtx_def): Update "used" field comment.
	* jump.c (delete_computation): Recursively delete insns even if
	the traditional scheduler was run after reload.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/sched.c.ORIGINAL	Wed Jun 16 00:20:45 1999
--- gcc/sched.c	Thu Jun 17 01:42:32 1999
*************** Boston, MA 02111-1307, USA.  */
*** 125,130 ****
--- 125,131 ----
  #include "regs.h"
  #include "hard-reg-set.h"
  #include "flags.h"
+ #include "insn-flags.h"
  #include "insn-config.h"
  #include "insn-attr.h"
  #include "recog.h"
*************** attach_deaths_insn (insn)
*** 2425,2430 ****
--- 2426,2436 ----
    register RTX_CODE code = GET_CODE (x);
    rtx link;
  
+   /* Skip prologue and epilogue instructions since they are not processed
+      by flow.  */
+   if (insn->used)
+     return;
+ 
    if (code == SET)
      {
        attach_deaths (SET_SRC (x), insn, 0);
*************** schedule_block (b, file)
*** 2881,2972 ****
       Recreate the register life information for the end of this basic
       block.  */
  
!   if (reload_completed == 0)
!     {
!       COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
!       CLEAR_REG_SET (bb_dead_regs);
  
!       if (b == 0)
! 	{
! 	  /* This is the first block in the function.  There may be insns
! 	     before head that we can't schedule.   We still need to examine
! 	     them though for accurate register lifetime analysis.  */
  
! 	  /* We don't want to remove any REG_DEAD notes as the code below
! 	     does.  */
  
! 	  for (insn = BLOCK_HEAD (b); insn != head;
! 	       insn = NEXT_INSN (insn))
! 	    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	      {
! 		/* See if the register gets born here.  */
! 		/* We must check for registers being born before we check for
! 		   registers dying.  It is possible for a register to be born
! 		   and die in the same insn, e.g. reading from a volatile
! 		   memory location into an otherwise unused register.  Such
! 		   a register must be marked as dead after this insn.  */
! 		if (GET_CODE (PATTERN (insn)) == SET
! 		    || GET_CODE (PATTERN (insn)) == CLOBBER)
! 		  sched_note_set (PATTERN (insn), 0);
! 		else if (GET_CODE (PATTERN (insn)) == PARALLEL)
! 		  {
! 		    int j;
! 		    for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		      if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
! 			  || GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
! 			sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
! 
! 		    /* ??? This code is obsolete and should be deleted.  It
! 		       is harmless though, so we will leave it in for now.  */
! 		    for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		      if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == USE)
! 			sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
! 		  }
  
! 		/* Each call clobbers (makes live) all call-clobbered regs
! 		   that are not global or fixed.  Note that the function-value
! 		   reg is a call_clobbered reg.  */
  
! 		if (GET_CODE (insn) == CALL_INSN)
! 		  {
! 		    int j;
! 		    for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 		      if (call_used_regs[j] && ! global_regs[j]
! 			  && ! fixed_regs[j])
! 			{
! 			  SET_REGNO_REG_SET (bb_live_regs, j);
! 			  CLEAR_REGNO_REG_SET (bb_dead_regs, j);
! 			}
! 		  }
  
! 		for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
  		  {
! 		    if ((REG_NOTE_KIND (link) == REG_DEAD
! 			 || REG_NOTE_KIND (link) == REG_UNUSED)
! 			/* Verify that the REG_NOTE has a valid value.  */
! 			&& GET_CODE (XEXP (link, 0)) == REG)
! 		      {
! 			register int regno = REGNO (XEXP (link, 0));
  
! 			if (regno < FIRST_PSEUDO_REGISTER)
! 			  {
! 			    int j = HARD_REGNO_NREGS (regno,
! 						      GET_MODE (XEXP (link, 0)));
! 			    while (--j >= 0)
! 			      {
! 				CLEAR_REGNO_REG_SET (bb_live_regs, regno + j);
! 				SET_REGNO_REG_SET (bb_dead_regs, regno + j);
! 			      }
! 			  }
! 			else
  			  {
! 			    CLEAR_REGNO_REG_SET (bb_live_regs, regno);
! 			    SET_REGNO_REG_SET (bb_dead_regs, regno);
  			  }
  		      }
  		  }
  	      }
! 	}
      }
  
    /* If debugging information is being produced, keep track of the line
--- 2887,2975 ----
       Recreate the register life information for the end of this basic
       block.  */
  
!   COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
!   CLEAR_REG_SET (bb_dead_regs);
  
!   if (b == 0)
!     {
!       /* This is the first block in the function.  There may be insns
! 	 before head that we can't schedule.   We still need to examine
! 	 them though for accurate register lifetime analysis.  */
  
!       /* We don't want to remove any REG_DEAD notes as the code below
! 	 does.  */
  
!       for (insn = BLOCK_HEAD (b); insn != head;
! 	   insn = NEXT_INSN (insn))
! 	if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
! 	  {
! 	    /* See if the register gets born here.  */
! 	    /* We must check for registers being born before we check for
! 	       registers dying.  It is possible for a register to be born
! 	       and die in the same insn, e.g. reading from a volatile
! 	       memory location into an otherwise unused register.  Such
! 	       a register must be marked as dead after this insn.  */
! 	    if (GET_CODE (PATTERN (insn)) == SET
! 		|| GET_CODE (PATTERN (insn)) == CLOBBER)
! 	      sched_note_set (PATTERN (insn), 0);
! 	    else if (GET_CODE (PATTERN (insn)) == PARALLEL)
  	      {
! 		int j;
! 		for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		  if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
! 		      || GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
! 		    sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
! 
! 		/* ??? This code is obsolete and should be deleted.  It
! 		   is harmless though, so we will leave it in for now.  */
! 		for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		  if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == USE)
! 		    sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
! 	      }
  
! 	    /* Each call clobbers (makes live) all call-clobbered regs
! 	       that are not global or fixed.  Note that the function-value
! 	       reg is a call_clobbered reg.  */
  
! 	    if (GET_CODE (insn) == CALL_INSN)
! 	      {
! 		int j;
! 		for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 		  if (call_used_regs[j] && ! global_regs[j]
! 		      && ! fixed_regs[j])
! 		    {
! 		      SET_REGNO_REG_SET (bb_live_regs, j);
! 		      CLEAR_REGNO_REG_SET (bb_dead_regs, j);
! 		    }
! 	       }
  
! 	    for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
! 	      {
! 		if ((REG_NOTE_KIND (link) == REG_DEAD
! 		     || REG_NOTE_KIND (link) == REG_UNUSED)
! 		    /* Verify that the REG_NOTE has a valid value.  */
! 		    && GET_CODE (XEXP (link, 0)) == REG)
  		  {
! 		    register int regno = REGNO (XEXP (link, 0));
  
! 		    if (regno < FIRST_PSEUDO_REGISTER)
! 		      {
! 			int j = HARD_REGNO_NREGS (regno,
! 						  GET_MODE (XEXP (link, 0)));
! 			while (--j >= 0)
  			  {
! 			    CLEAR_REGNO_REG_SET (bb_live_regs, regno + j);
! 			    SET_REGNO_REG_SET (bb_dead_regs, regno + j);
  			  }
  		      }
+ 		    else
+ 		      {
+ 			CLEAR_REGNO_REG_SET (bb_live_regs, regno);
+ 			SET_REGNO_REG_SET (bb_dead_regs, regno);
+ 		      }
  		  }
  	      }
! 	  }
      }
  
    /* If debugging information is being produced, keep track of the line
*************** schedule_block (b, file)
*** 3006,3013 ****
  	    abort ();
  	}
  
!       if (reload_completed == 0
! 	  && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	{
  	  /* See if the register gets born here.  */
  	  /* We must check for registers being born before we check for
--- 3009,3015 ----
  	    abort ();
  	}
  
!       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
  	{
  	  /* See if the register gets born here.  */
  	  /* We must check for registers being born before we check for
*************** schedule_block (b, file)
*** 3096,3118 ****
  	}
      }
  
!   if (reload_completed == 0)
!     {
!       /* Keep track of register lives.  */
!       old_live_regs = ALLOCA_REG_SET ();
!       regs_sometimes_live
! 	= (struct sometimes *) alloca (max_regno * sizeof (struct sometimes));
!       sometimes_max = 0;
! 
!       /* Start with registers live at end.  */
!       COPY_REG_SET (old_live_regs, bb_live_regs);
!       EXECUTE_IF_SET_IN_REG_SET (bb_live_regs, 0, j,
! 				 {
! 				   sometimes_max
! 				     = new_sometimes_live (regs_sometimes_live,
! 							   j, sometimes_max);
! 				 });
!     }
  
    SCHED_SORT (ready, n_ready, 1);
  
--- 3098,3117 ----
  	}
      }
  
!   /* Keep track of register lives.  */
!   old_live_regs = ALLOCA_REG_SET ();
!   regs_sometimes_live
!     = (struct sometimes *) alloca (max_regno * sizeof (struct sometimes));
!   sometimes_max = 0;
! 
!   /* Start with registers live at end.  */
!   COPY_REG_SET (old_live_regs, bb_live_regs);
!   EXECUTE_IF_SET_IN_REG_SET (bb_live_regs, 0, j,
! 			     {
! 			       sometimes_max
! 				 = new_sometimes_live (regs_sometimes_live,
! 						       j, sometimes_max);
! 			     });
  
    SCHED_SORT (ready, n_ready, 1);
  
*************** schedule_block (b, file)
*** 3241,3352 ****
        if (DONE_PRIORITY_P (insn))
  	abort ();
  
!       if (reload_completed == 0)
  	{
! 	  /* Process this insn, and each insn linked to this one which must
! 	     be immediately output after this insn.  */
! 	  do
! 	    {
! 	      /* First we kill registers set by this insn, and then we
! 		 make registers used by this insn live.  This is the opposite
! 		 order used above because we are traversing the instructions
! 		 backwards.  */
! 
! 	      /* Strictly speaking, we should scan REG_UNUSED notes and make
! 		 every register mentioned there live, however, we will just
! 		 kill them again immediately below, so there doesn't seem to
! 		 be any reason why we bother to do this.  */
! 
! 	      /* See if this is the last notice we must take of a register.  */
! 	      if (GET_CODE (PATTERN (insn)) == SET
! 		  || GET_CODE (PATTERN (insn)) == CLOBBER)
! 		sched_note_set (PATTERN (insn), 1);
! 	      else if (GET_CODE (PATTERN (insn)) == PARALLEL)
! 		{
! 		  int j;
! 		  for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		    if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
! 			|| GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
! 		      sched_note_set (XVECEXP (PATTERN (insn), 0, j), 1);
! 		}
! 	      
! 	      /* This code keeps life analysis information up to date.  */
! 	      if (GET_CODE (insn) == CALL_INSN)
! 		{
! 		  register struct sometimes *p;
  
! 		  /* A call kills all call used registers that are not
! 		     global or fixed, except for those mentioned in the call
! 		     pattern which will be made live again later.  */
! 		  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 		    if (call_used_regs[i] && ! global_regs[i]
! 			&& ! fixed_regs[i])
! 		      {
! 			CLEAR_REGNO_REG_SET (bb_live_regs, i);
! 			SET_REGNO_REG_SET (bb_dead_regs, i);
! 		      }
  
! 		  /* Regs live at the time of a call instruction must not
! 		     go in a register clobbered by calls.  Record this for
! 		     all regs now live.  Note that insns which are born or
! 		     die in a call do not cross a call, so this must be done
! 		     after the killings (above) and before the births
! 		     (below).  */
! 		  p = regs_sometimes_live;
! 		  for (i = 0; i < sometimes_max; i++, p++)
! 		    if (REGNO_REG_SET_P (bb_live_regs, p->regno))
! 		      p->calls_crossed += 1;
! 		}
  
! 	      /* Make every register used live, and add REG_DEAD notes for
! 		 registers which were not live before we started.  */
! 	      attach_deaths_insn (insn);
! 
! 	      /* Find registers now made live by that instruction.  */
! 	      EXECUTE_IF_AND_COMPL_IN_REG_SET (bb_live_regs, old_live_regs, 0, i,
! 					       {
! 						 sometimes_max
! 						   = new_sometimes_live (regs_sometimes_live,
! 									 i, sometimes_max);
! 					       });
! 	      IOR_REG_SET (old_live_regs, bb_live_regs);
  
! 	      /* Count lengths of all regs we are worrying about now,
! 		 and handle registers no longer live.  */
  
! 	      for (i = 0; i < sometimes_max; i++)
! 		{
! 		  register struct sometimes *p = &regs_sometimes_live[i];
! 		  int regno = p->regno;
  
! 		  p->live_length += 1;
  
! 		  if (!REGNO_REG_SET_P (bb_live_regs, p->regno))
! 		    {
! 		      /* This is the end of one of this register's lifetime
! 			 segments.  Save the lifetime info collected so far,
! 			 and clear its bit in the old_live_regs entry.  */
! 		      sched_reg_live_length[regno] += p->live_length;
! 		      sched_reg_n_calls_crossed[regno] += p->calls_crossed;
! 		      CLEAR_REGNO_REG_SET (old_live_regs, p->regno);
! 
! 		      /* Delete the reg_sometimes_live entry for this reg by
! 			 copying the last entry over top of it.  */
! 		      *p = regs_sometimes_live[--sometimes_max];
! 		      /* ...and decrement i so that this newly copied entry
! 			 will be processed.  */
! 		      i--;
! 		    }
  		}
- 
- 	      link = insn;
- 	      insn = PREV_INSN (insn);
  	    }
- 	  while (SCHED_GROUP_P (link));
  
! 	  /* Set INSN back to the insn we are scheduling now.  */
! 	  insn = ready[0];
  	}
  
        /* Schedule INSN.  Remove it from the ready list.  */
        ready += 1;
--- 3240,3348 ----
        if (DONE_PRIORITY_P (insn))
  	abort ();
  
!       /* Process this insn, and each insn linked to this one which must
! 	 be immediately output after this insn.  */
!       do
  	{
! 	  /* First we kill registers set by this insn, and then we
! 	     make registers used by this insn live.  This is the opposite
! 	     order used above because we are traversing the instructions
! 	     backwards.  */
! 
! 	  /* Strictly speaking, we should scan REG_UNUSED notes and make
! 	     every register mentioned there live, however, we will just
! 	     kill them again immediately below, so there doesn't seem to
! 	     be any reason why we bother to do this.  */
  
! 	  /* See if this is the last notice we must take of a register.  */
! 	  if (GET_CODE (PATTERN (insn)) == SET
! 	      || GET_CODE (PATTERN (insn)) == CLOBBER)
! 	    sched_note_set (PATTERN (insn), 1);
! 	  else if (GET_CODE (PATTERN (insn)) == PARALLEL)
! 	    {
! 	      int j;
! 	      for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
! 		if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
! 		    || GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
! 		  sched_note_set (XVECEXP (PATTERN (insn), 0, j), 1);
! 	    }
! 	      
! 	  /* This code keeps life analysis information up to date.  */
! 	  if (GET_CODE (insn) == CALL_INSN)
! 	    {
! 	      register struct sometimes *p;
  
! 	      /* A call kills all call used registers that are not
! 		 global or fixed, except for those mentioned in the call
! 		 pattern which will be made live again later.  */
! 	      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 		if (call_used_regs[i] && ! global_regs[i]
! 		    && ! fixed_regs[i])
! 		  {
! 		    CLEAR_REGNO_REG_SET (bb_live_regs, i);
! 		    SET_REGNO_REG_SET (bb_dead_regs, i);
! 		  }
  
! 	      /* Regs live at the time of a call instruction must not
! 		 go in a register clobbered by calls.  Record this for
! 		 all regs now live.  Note that insns which are born or
! 		 die in a call do not cross a call, so this must be done
! 		 after the killings (above) and before the births
! 		 (below).  */
! 	      p = regs_sometimes_live;
! 	      for (i = 0; i < sometimes_max; i++, p++)
! 		if (REGNO_REG_SET_P (bb_live_regs, p->regno))
! 		  p->calls_crossed += 1;
! 	    }
! 
! 	  /* Make every register used live, and add REG_DEAD notes for
! 	     registers which were not live before we started.  */
! 	  attach_deaths_insn (insn);
! 
! 	  /* Find registers now made live by that instruction.  */
! 	  EXECUTE_IF_AND_COMPL_IN_REG_SET (bb_live_regs, old_live_regs, 0, i,
! 					   {
! 					     sometimes_max
! 					       = new_sometimes_live (regs_sometimes_live,
! 								     i, sometimes_max);
! 					   });
! 	  IOR_REG_SET (old_live_regs, bb_live_regs);
  
! 	  /* Count lengths of all regs we are worrying about now,
! 	     and handle registers no longer live.  */
  
! 	  for (i = 0; i < sometimes_max; i++)
! 	    {
! 	      register struct sometimes *p = &regs_sometimes_live[i];
! 	      int regno = p->regno;
  
! 	      p->live_length += 1;
  
! 	      if (!REGNO_REG_SET_P (bb_live_regs, p->regno))
! 		{
! 		  /* This is the end of one of this register's lifetime
! 		     segments.  Save the lifetime info collected so far,
! 		     and clear its bit in the old_live_regs entry.  */
! 		  sched_reg_live_length[regno] += p->live_length;
! 		  sched_reg_n_calls_crossed[regno] += p->calls_crossed;
! 		  CLEAR_REGNO_REG_SET (old_live_regs, p->regno);
! 
! 		  /* Delete the reg_sometimes_live entry for this reg by
! 		     copying the last entry over top of it.  */
! 		  *p = regs_sometimes_live[--sometimes_max];
! 		  /* ...and decrement i so that this newly copied entry
! 		     will be processed.  */
! 		  i--;
  		}
  	    }
  
! 	  link = insn;
! 	  insn = PREV_INSN (insn);
  	}
+       while (SCHED_GROUP_P (link));
+ 
+       /* Set INSN back to the insn we are scheduling now.  */
+       insn = ready[0];
  
        /* Schedule INSN.  Remove it from the ready list.  */
        ready += 1;
*************** schedule_block (b, file)
*** 3421,3428 ****
    if (q_size != 0)
      abort ();
  
!   if (reload_completed == 0)
!     finish_sometimes_live (regs_sometimes_live, sometimes_max);
  
    /* HEAD is now the first insn in the chain of insns that
       been scheduled by the loop above.
--- 3417,3423 ----
    if (q_size != 0)
      abort ();
  
!   finish_sometimes_live (regs_sometimes_live, sometimes_max);
  
    /* HEAD is now the first insn in the chain of insns that
       been scheduled by the loop above.
*************** schedule_insns (dump_file)
*** 4222,4227 ****
--- 4217,4224 ----
  {
    int max_uid = MAX_INSNS_PER_SPLIT * (get_max_uid () + 1);
    int b;
+   int prologue_insns;
+   int epilogue_insns;
    rtx insn;
  
    /* Taking care of this degenerate case makes the rest of
*************** schedule_insns (dump_file)
*** 4263,4284 ****
    insn_blockage = (unsigned int *) xmalloc (max_uid * sizeof (unsigned int));
    insn_ref_count = (int *) xmalloc (max_uid * sizeof (int));
  
!   if (reload_completed == 0)
!     {
!       sched_reg_n_calls_crossed = (int *) alloca (max_regno * sizeof (int));
!       sched_reg_live_length = (int *) alloca (max_regno * sizeof (int));
!       bb_dead_regs = ALLOCA_REG_SET ();
!       bb_live_regs = ALLOCA_REG_SET ();
!       bzero ((char *) sched_reg_n_calls_crossed, max_regno * sizeof (int));
!       bzero ((char *) sched_reg_live_length, max_regno * sizeof (int));
!     }
!   else
!     {
!       sched_reg_n_calls_crossed = 0;
!       sched_reg_live_length = 0;
!       bb_dead_regs = 0;
!       bb_live_regs = 0;
!     }
    init_alias_analysis ();
  
    if (write_symbols != NO_DEBUG)
--- 4260,4272 ----
    insn_blockage = (unsigned int *) xmalloc (max_uid * sizeof (unsigned int));
    insn_ref_count = (int *) xmalloc (max_uid * sizeof (int));
  
!   sched_reg_n_calls_crossed = (int *) alloca (max_regno * sizeof (int));
!   sched_reg_live_length = (int *) alloca (max_regno * sizeof (int));
!   bb_dead_regs = ALLOCA_REG_SET ();
!   bb_live_regs = ALLOCA_REG_SET ();
!   bzero ((char *) sched_reg_n_calls_crossed, max_regno * sizeof (int));
!   bzero ((char *) sched_reg_live_length, max_regno * sizeof (int));
! 
    init_alias_analysis ();
  
    if (write_symbols != NO_DEBUG)
*************** schedule_insns (dump_file)
*** 4329,4340 ****
--- 4317,4358 ----
  		&& GET_CODE (NEXT_INSN (insn)) == BARRIER)))
      emit_note_after (NOTE_INSN_DELETED, BLOCK_END (n_basic_blocks-1));
  
+ #ifdef HAVE_prologue
+   prologue_insns = 1;
+ #else
+   prologue_insns = 0;
+ #endif
+ 
    for (b = 0; b < n_basic_blocks; b++)
      {
        note_list = 0;
  
        split_block_insns (b, reload_completed == 0 || ! flag_schedule_insns);
  
+       /* Mark the prologue and epilogue instructions so that
+ 	 attach_deaths_insn can skip them.  */
+       for (epilogue_insns = 0, insn = BLOCK_HEAD (b);
+ 	   insn && insn != NEXT_INSN (BLOCK_END (b));
+ 	   insn = NEXT_INSN (insn))
+ 	{
+ 	  if (GET_CODE (insn) == NOTE)
+ 	    if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
+ 	      prologue_insns = 0;
+ 	    else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
+ 	      epilogue_insns = 1;
+ 
+ 	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ 	    insn->used = prologue_insns || epilogue_insns;
+ 
+ 	  /* USE instructions are not (for attach_deaths_insn purposes)
+ 	     part of the epilogue.  This may lose if gen_epilogue ever
+ 	     outputs a USE instruction.  */
+ 	  if (epilogue_insns
+ 	      && GET_CODE (insn) == INSN
+ 	      && GET_CODE (PATTERN (insn)) == USE)
+ 	    insn->used = 0;
+ 	}
+ 
        schedule_block (b, dump_file);
  
  #ifdef USE_C_ALLOCA
*************** schedule_insns (dump_file)
*** 4460,4470 ****
    if (write_symbols != NO_DEBUG)
      free (line_note);
  
!   if (reload_completed == 0)
!     {
!       FREE_REG_SET (bb_dead_regs);
!       FREE_REG_SET (bb_live_regs);
!     }
! 
  }
  #endif /* INSN_SCHEDULING */
--- 4478,4484 ----
    if (write_symbols != NO_DEBUG)
      free (line_note);
  
!   FREE_REG_SET (bb_dead_regs);
!   FREE_REG_SET (bb_live_regs);
  }
  #endif /* INSN_SCHEDULING */
*** gcc/rtl.h.ORIGINAL	Mon May 31 11:22:57 1999
--- gcc/rtl.h	Wed Jun 16 23:38:51 1999
*************** typedef struct rtx_def
*** 157,163 ****
       In a REG, this is not needed for that purpose, and used instead 
       in `leaf_renumber_regs_insn'.
       In a SYMBOL_REF, means that emit_library_call
!      has used it as the function.  */
    unsigned int used : 1;
    /* Nonzero if this rtx came from procedure integration.
       In a REG, nonzero means this reg refers to the return value
--- 157,165 ----
       In a REG, this is not needed for that purpose, and used instead 
       in `leaf_renumber_regs_insn'.
       In a SYMBOL_REF, means that emit_library_call
!      has used it as the function.
!      1 in an INSN, JUMP_INSN, or CALL_INSN if this insn is part of the
!      prologue or epilogue.  Valid only within sched.  */
    unsigned int used : 1;
    /* Nonzero if this rtx came from procedure integration.
       In a REG, nonzero means this reg refers to the return value
*** gcc/jump.c.ORIGINAL	Wed Jun 16 00:18:28 1999
--- gcc/jump.c	Wed Jun 16 01:33:26 1999
*************** delete_computation (insn)
*** 3835,3844 ****
      }
  #endif
  
! #ifdef INSN_SCHEDULING
!   /* ?!? The schedulers do not keep REG_DEAD notes accurate after
!      reload has completed.  The schedulers need to be fixed.  Until
!      they are, we must not rely on the death notes here.  */
    if (reload_completed && flag_schedule_insns_after_reload)
      {
        delete_insn (insn);
--- 3835,3844 ----
      }
  #endif
  
! #ifdef HAIFA
!   /* ?!? The haifa scheduler does not keep REG_DEAD notes accurate after
!      reload has completed.  The scheduler need to be fixed.  Until
!      it is, we must not rely on the death notes here.  */
    if (reload_completed && flag_schedule_insns_after_reload)
      {
        delete_insn (insn);
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------


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