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]

Re: make delete_trivially_dead CFG friendly


> On Fri, Jun 29, 2001 at 03:02:14PM +0200, Jan Hubicka wrote:
> > 	* cse.c (insn_live_p, dead_libcall_p): Break out from ...
> > 	(delete_trivially_dead_insns): ... here; accept new argument
> > 	preserve_basic_blocks; preserve basic blocks if set.
> 
> You're not using dead_libcall_p.
Duh.

*** /windows/C/honza/gcc/gcc/cse.c	Fri May 18 02:05:14 2001
--- cse.c	Mon Jul  2 12:02:36 2001
*************** count_reg_usage (x, counts, dest, incr)
*** 7506,7511 ****
--- 7506,7609 ----
      }
  }
  
+ /* Return true if insn is live.  */
+ static bool
+ insn_live_p (insn, counts)
+ 	rtx insn;
+ 	int *counts;
+ {
+   int i;
+   if (GET_CODE (PATTERN (insn)) == SET)
+     {
+       if (set_noop_p (PATTERN (insn)))
+ 	;
+ 
+ #ifdef HAVE_cc0
+       else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0
+ 	       && !side_effects_p (SET_SRC (PATTERN (insn)))
+ 	       && ((tem = next_nonnote_insn (insn)) == 0
+ 		   || !INSN_P (tem)
+ 		   || !reg_referenced_p (cc0_rtx, PATTERN (tem))))
+ 	return false;
+ #endif
+       else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG
+ 	       || REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
+ 	       || counts[REGNO (SET_DEST (PATTERN (insn)))] != 0
+ 	       || side_effects_p (SET_SRC (PATTERN (insn)))
+ 	       /* An ADDRESSOF expression can turn into a use of the
+ 	          internal arg pointer, so always consider the
+ 	          internal arg pointer live.  If it is truly dead,
+ 	          flow will delete the initializing insn.  */
+ 	       || (SET_DEST (PATTERN (insn))
+ 		   == current_function_internal_arg_pointer))
+ 	return true;
+     }
+   else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+     for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+       {
+ 	rtx elt = XVECEXP (PATTERN (insn), 0, i);
+ 
+ 	if (GET_CODE (elt) == SET)
+ 	  {
+ 	    if (set_noop_p (elt))
+ 	      ;
+ 
+ #ifdef HAVE_cc0
+ 	    else if (GET_CODE (SET_DEST (elt)) == CC0
+ 		     && !side_effects_p (SET_SRC (elt))
+ 		     && ((tem = next_nonnote_insn (insn)) == 0
+ 			 || !INSN_P (tem)
+ 			 || !reg_referenced_p (cc0_rtx, PATTERN (tem))))
+ 	      ;
+ #endif
+ 	    else if (GET_CODE (SET_DEST (elt)) != REG
+ 		     || REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER
+ 		     || counts[REGNO (SET_DEST (elt))] != 0
+ 		     || side_effects_p (SET_SRC (elt))
+ 		     /* An ADDRESSOF expression can turn into a use of the
+ 		        internal arg pointer, so always consider the
+ 		        internal arg pointer live.  If it is truly dead,
+ 		        flow will delete the initializing insn.  */
+ 		     || (SET_DEST (elt)
+ 			 == current_function_internal_arg_pointer))
+ 	      return true;
+ 	  }
+ 	else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
+ 	  return true;
+       }
+   else
+     return true;
+   return false;
+ }
+ /* Return true if libcall is dead as a whole.  */
+ static bool
+ dead_libcall_p (insn, counts)
+      rtx insn;
+      int *counts;
+ {
+   rtx note;
+   /* See if there's a REG_EQUAL note on this insn and try to
+      replace the source with the REG_EQUAL expression.
+ 
+      We assume that insns with REG_RETVALs can only be reg->reg
+      copies at this point.  */
+   note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+   if (note)
+     {
+       rtx set = single_set (insn);
+       rtx new = simplify_rtx (XEXP (note, 0));
+ 
+       if (!new)
+ 	new = XEXP (note, 0);
+ 
+       if (set && validate_change (insn, &SET_SRC (set), new, 0))
+ 	{
+ 	  remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
+ 	  return true;
+ 	}
+     }
+   return false;
+ }
  /* Scan all the insns and delete any that are dead; i.e., they store a register
     that is never used or they copy a register to itself.
  
*************** count_reg_usage (x, counts, dest, incr)
*** 7515,7523 ****
     remaining passes of the compilation are also sped up.  */
  
  void
! delete_trivially_dead_insns (insns, nreg)
       rtx insns;
       int nreg;
  {
    int *counts;
    rtx insn, prev;
--- 7613,7622 ----
     remaining passes of the compilation are also sped up.  */
  
  void
! delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
       rtx insns;
       int nreg;
+      int preserve_basic_blocks;
  {
    int *counts;
    rtx insn, prev;
*************** delete_trivially_dead_insns (insns, nreg
*** 7526,7531 ****
--- 7625,7631 ----
  #endif
    int i;
    int in_libcall = 0, dead_libcall = 0;
+   basic_block bb;
  
    /* First count the number of times each register is used.  */
    counts = (int *) xcalloc (nreg, sizeof (int));
*************** delete_trivially_dead_insns (insns, nreg
*** 7543,7666 ****
    if (! INSN_P (insn))
      insn = prev_real_insn (insn);
  
!   for (; insn; insn = prev)
!     {
!       int live_insn = 0;
!       rtx note;
! 
!       prev = prev_real_insn (insn);
! 
!       /* Don't delete any insns that are part of a libcall block unless
! 	 we can delete the whole libcall block.
! 
! 	 Flow or loop might get confused if we did that.  Remember
! 	 that we are scanning backwards.  */
!       if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
! 	{
! 	  in_libcall = 1;
! 	  live_insn = 1;
! 	  dead_libcall = 0;
! 
! 	  /* See if there's a REG_EQUAL note on this insn and try to
! 	     replace the source with the REG_EQUAL expression.
! 
! 	     We assume that insns with REG_RETVALs can only be reg->reg
! 	     copies at this point.  */
! 	  note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
! 	  if (note)
! 	    {
! 	      rtx set = single_set (insn);
! 	      rtx new = simplify_rtx (XEXP (note, 0));
! 
! 	      if (!new)
! 		new = XEXP (note, 0);
  
! 	      if (set && validate_change (insn, &SET_SRC (set), new, 0))
! 		{
! 		  remove_note (insn,
! 			       find_reg_note (insn, REG_RETVAL, NULL_RTX));
! 		  dead_libcall = 1;
! 		}
! 	    }
! 	}
!       else if (in_libcall)
! 	live_insn = ! dead_libcall;
!       else if (GET_CODE (PATTERN (insn)) == SET)
! 	{
! 	  if (set_noop_p (PATTERN (insn)))
! 	    ;
  
! #ifdef HAVE_cc0
! 	  else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0
! 		   && ! side_effects_p (SET_SRC (PATTERN (insn)))
! 		   && ((tem = next_nonnote_insn (insn)) == 0
! 		       || ! INSN_P (tem)
! 		       || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
! 	    ;
! #endif
! 	  else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG
! 		   || REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
! 		   || counts[REGNO (SET_DEST (PATTERN (insn)))] != 0
! 		   || side_effects_p (SET_SRC (PATTERN (insn)))
! 		   /* An ADDRESSOF expression can turn into a use of the
! 		      internal arg pointer, so always consider the
! 		      internal arg pointer live.  If it is truly dead,
! 		      flow will delete the initializing insn.  */
! 		   || (SET_DEST (PATTERN (insn))
! 		       == current_function_internal_arg_pointer))
! 	    live_insn = 1;
! 	}
!       else if (GET_CODE (PATTERN (insn)) == PARALLEL)
! 	for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
  	  {
! 	    rtx elt = XVECEXP (PATTERN (insn), 0, i);
  
! 	    if (GET_CODE (elt) == SET)
! 	      {
! 		if (set_noop_p (elt))
! 		  ;
  
! #ifdef HAVE_cc0
! 		else if (GET_CODE (SET_DEST (elt)) == CC0
! 			 && ! side_effects_p (SET_SRC (elt))
! 			 && ((tem = next_nonnote_insn (insn)) == 0
! 			     || ! INSN_P (tem)
! 			     || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
! 		  ;
! #endif
! 		else if (GET_CODE (SET_DEST (elt)) != REG
! 			 || REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER
! 			 || counts[REGNO (SET_DEST (elt))] != 0
! 			 || side_effects_p (SET_SRC (elt))
! 			 /* An ADDRESSOF expression can turn into a use of the
! 			    internal arg pointer, so always consider the
! 			    internal arg pointer live.  If it is truly dead,
! 			    flow will delete the initializing insn.  */
! 			 || (SET_DEST (elt)
! 			     == current_function_internal_arg_pointer))
! 		  live_insn = 1;
! 	      }
! 	    else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
  	      live_insn = 1;
! 	  }
!       else
! 	live_insn = 1;
  
!       /* If this is a dead insn, delete it and show registers in it aren't
! 	 being used.  */
  
!       if (! live_insn)
! 	{
! 	  count_reg_usage (insn, counts, NULL_RTX, -1);
! 	  delete_insn (insn);
! 	}
  
!       if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
! 	{
! 	  in_libcall = 0;
! 	  dead_libcall = 0;
  	}
-     }
  
    /* Clean up.  */
    free (counts);
--- 7643,7731 ----
    if (! INSN_P (insn))
      insn = prev_real_insn (insn);
  
!   if (!preserve_basic_blocks)
!     for (; insn; insn = prev)
!       {
! 	int live_insn = 0;
! 	rtx note;
! 
! 	prev = prev_real_insn (insn);
! 
! 	/* Don't delete any insns that are part of a libcall block unless
! 	   we can delete the whole libcall block.
! 
! 	   Flow or loop might get confused if we did that.  Remember
! 	   that we are scanning backwards.  */
! 	if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
! 	  {
! 	    in_libcall = 1;
! 	    live_insn = 1;
! 	    dead_libcall = dead_libcall_p (insn);
! 	  }
! 	else if (in_libcall)
! 	  live_insn = ! dead_libcall;
! 	else
! 	  live_insn = insn_live_p (insn, counts);
  
! 	/* If this is a dead insn, delete it and show registers in it aren't
! 	   being used.  */
  
! 	if (! live_insn)
  	  {
! 	    count_reg_usage (insn, counts, NULL_RTX, -1);
! 	    delete_insn (insn);
! 	  }
  
! 	if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
! 	  {
! 	    in_libcall = 0;
! 	    dead_libcall = 0;
! 	  }
!       }
!   else
!     for (i = 0; i < n_basic_blocks; i++)
!       for (bb = BASIC_BLOCK (i), insn = bb->end; insn != bb->head; insn = prev)
! 	{
! 	  int live_insn = 0;
! 	  rtx note;
  
! 	  prev = PREV_INSN (insn);
! 	  if (!INSN_P (insn))
! 	    continue;
! 
! 	  /* Don't delete any insns that are part of a libcall block unless
! 	     we can delete the whole libcall block.
! 
! 	     Flow or loop might get confused if we did that.  Remember
! 	     that we are scanning backwards.  */
! 	  if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
! 	    {
! 	      in_libcall = 1;
  	      live_insn = 1;
! 	      dead_libcall = dead_libcall_p (insn);
! 	    }
! 	  else if (in_libcall)
! 	    live_insn = ! dead_libcall;
! 	  else
! 	    live_insn = insn_live_p (insn, counts);
  
! 	  /* If this is a dead insn, delete it and show registers in it aren't
! 	     being used.  */
  
! 	  if (! live_insn)
! 	    {
! 	      count_reg_usage (insn, counts, NULL_RTX, -1);
! 	      if (insn == bb->end)
! 		bb->end = PREV_INSN (insn);
! 	      flow_delete_insn (insn);
! 	    }
  
! 	  if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
! 	    {
! 	      in_libcall = 0;
! 	      dead_libcall = 0;
! 	    }
  	}
  
    /* Clean up.  */
    free (counts);
*** /windows/C/honza/gcc/gcc/rtl.h	Wed Jun 20 15:18:18 2001
--- rtl.h	Mon Jul  2 12:00:07 2001
*************** struct cse_basic_block_data;
*** 1689,1695 ****
  
  extern int rtx_cost			PARAMS ((rtx, enum rtx_code));
  extern int address_cost			PARAMS ((rtx, enum machine_mode));
! extern void delete_trivially_dead_insns	PARAMS ((rtx, int));
  #ifdef BUFSIZ
  extern int cse_main			PARAMS ((rtx, int, int, FILE *));
  #endif
--- 1689,1695 ----
  
  extern int rtx_cost			PARAMS ((rtx, enum rtx_code));
  extern int address_cost			PARAMS ((rtx, enum machine_mode));
! extern void delete_trivially_dead_insns	PARAMS ((rtx, int, int));
  #ifdef BUFSIZ
  extern int cse_main			PARAMS ((rtx, int, int, FILE *));
  #endif
*** /windows/C/honza/gcc/gcc/toplev.c	Wed Jun 27 02:06:16 2001
--- toplev.c	Thu Jul  5 00:50:09 2001
*************** rest_of_compilation (decl)
*** 3014,3020 ****
  
        /* Run this after jump optmizations remove all the unreachable code
  	 so that unreachable code will not keep values live.  */
!       delete_trivially_dead_insns (insns, max_reg_num ());
  
        /* Try to identify useless null pointer tests and delete them.  */
        if (flag_delete_null_pointer_checks)
--- 3014,3020 ----
  
        /* Run this after jump optmizations remove all the unreachable code
  	 so that unreachable code will not keep values live.  */
!       delete_trivially_dead_insns (insns, max_reg_num (), 0);
  
        /* Try to identify useless null pointer tests and delete them.  */
        if (flag_delete_null_pointer_checks)
*************** rest_of_compilation (decl)
*** 3170,3176 ****
  	     trivially dead.  We delete those instructions now in the
  	     hope that doing so will make the heuristics in loop work
  	     better and possibly speed up compilation.  */
! 	  delete_trivially_dead_insns (insns, max_reg_num ());
  
  	  /* The regscan pass is currently necessary as the alias
  		  analysis code depends on this information.  */
--- 3170,3176 ----
  	     trivially dead.  We delete those instructions now in the
  	     hope that doing so will make the heuristics in loop work
  	     better and possibly speed up compilation.  */
! 	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
  
  	  /* The regscan pass is currently necessary as the alias
  		  analysis code depends on this information.  */
*************** rest_of_compilation (decl)
*** 3203,3209 ****
  	     trivially dead.  We delete those instructions now in the
  	     hope that doing so will make the heuristics in jump work
  	     better and possibly speed up compilation.  */
! 	  delete_trivially_dead_insns (insns, max_reg_num ());
  
  	  reg_scan (insns, max_reg_num (), 0);
  	  jump_optimize (insns, !JUMP_CROSS_JUMP,
--- 3203,3209 ----
  	     trivially dead.  We delete those instructions now in the
  	     hope that doing so will make the heuristics in jump work
  	     better and possibly speed up compilation.  */
! 	  delete_trivially_dead_insns (insns, max_reg_num (), 0);
  
  	  reg_scan (insns, max_reg_num (), 0);
  	  jump_optimize (insns, !JUMP_CROSS_JUMP,


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