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]
Other format: [Raw text]

delete_trivially_dead_insns cleanup



Hi,
this patch cleanups and optimizes delete_trivially_dead_insns, so it now kills
more dead code by iterating until stabilizes (when counter is droped to 0 by
removing insns, some later insns may become dead.  After loop
delete_trivially_dead_insns usually needs 3 iterations to stabilize.

The compiler appears to be slighly faster and there is some reduction of number
of instructions of resulting file.  I've added timer as I plan to use it more
commonly in followup patches.

I didn't included update to rest_of_compilation as I have more involved change
in next patch.  I hope these to both get approved, but if not, I will add the
trivial update of killing last argument.


Bootstrapped/regtested i386

Honza

Sun Mar  3 17:25:35 CET 2002  Jan Hubicka  <jh@suse.cz>
	* cse.c: Include timevar.h
	(delete_trivially_dead_insns): Kill preserve_basic_blocks argument;
	iterate until stabilizes; print statistics; return number of killed
	insns.
	* Makefile.in: (cse.o): Add timevar.h dependency
	* rtl.h (delete_trivially_dead_insns): New.
	* timever.def: Add TV_DELETE_TRIVIALLY_DEAD timer.
	* toplev.c (rest_of_compilation): Update callers.

*** cse.c.old	Sun Mar  3 15:43:09 2002
--- cse.c	Sun Mar  3 19:05:34 2002
*************** Software Foundation, 59 Temple Place - S
*** 37,42 ****
--- 37,43 ----
  #include "toplev.h"
  #include "output.h"
  #include "ggc.h"
+ #include "timevar.h"
  
  /* The basic idea of common subexpression elimination is to go
     through the code, keeping a record of expressions that would
*************** dead_libcall_p (insn)
*** 7605,7685 ****
     move dead invariants out of loops or make givs for dead quantities.  The
     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;
-   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));
    for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
      count_reg_usage (insn, counts, NULL_RTX, 1);
  
!   /* Go from the last insn to the first and delete insns that only set unused
!      registers or copy a register to itself.  As we delete an insn, remove
!      usage counts for registers it uses.
! 
!      The first jump optimization pass may leave a real insn as the last
!      insn in the function.   We must not skip that insn or we may end
!      up deleting code that is not really dead.  */
!   insn = get_last_insn ();
!   if (! INSN_P (insn))
!     insn = prev_real_insn (insn);
! 
!   if (!preserve_basic_blocks)
!     for (; insn; insn = prev)
!       {
! 	int live_insn = 0;
! 
! 	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_related_insns (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;
  
! 	  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.
--- 7606,7647 ----
     move dead invariants out of loops or make givs for dead quantities.  The
     remaining passes of the compilation are also sped up.  */
  
! int
! delete_trivially_dead_insns (insns, nreg)
       rtx insns;
       int nreg;
  {
    int *counts;
    rtx insn, prev;
    int in_libcall = 0, dead_libcall = 0;
!   int ndead = 0, nlastdead, niterations = 0;
  
+   timevar_push (TV_DELETE_TRIVIALLY_DEAD);
    /* First count the number of times each register is used.  */
    counts = (int *) xcalloc (nreg, sizeof (int));
    for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
      count_reg_usage (insn, counts, NULL_RTX, 1);
  
!   do
!     {
!       nlastdead = ndead;
!       niterations++;
!       /* Go from the last insn to the first and delete insns that only set unused
! 	 registers or copy a register to itself.  As we delete an insn, remove
! 	 usage counts for registers it uses.
! 
! 	 The first jump optimization pass may leave a real insn as the last
! 	 insn in the function.   We must not skip that insn or we may end
! 	 up deleting code that is not really dead.  */
!       insn = get_last_insn ();
!       if (! INSN_P (insn))
! 	insn = prev_real_insn (insn);
  
!       for (; insn; insn = prev)
  	{
  	  int live_insn = 0;
  
! 	  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.
*************** delete_trivially_dead_insns (insns, nreg
*** 7703,7709 ****
  	  if (! live_insn)
  	    {
  	      count_reg_usage (insn, counts, NULL_RTX, -1);
! 	      delete_insn (insn);
  	    }
  
  	  if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
--- 7665,7672 ----
  	  if (! live_insn)
  	    {
  	      count_reg_usage (insn, counts, NULL_RTX, -1);
! 	      delete_insn_and_edges (insn);
! 	      ndead++;
  	    }
  
  	  if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
*************** delete_trivially_dead_insns (insns, nreg
*** 7712,7718 ****
--- 7675,7687 ----
  	      dead_libcall = 0;
  	    }
  	}
+     } while (ndead != nlastdead);
  
+   if (rtl_dump_file && ndead)
+     fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+ 	     ndead, niterations);
    /* Clean up.  */
    free (counts);
+   timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
+   return ndead;
  }
*** rtl.h.old	Sun Mar  3 16:51:22 2002
--- rtl.h	Sun Mar  3 19:04:16 2002
*************** struct cse_basic_block_data;
*** 1792,1798 ****
  
  extern int rtx_cost			PARAMS ((rtx, enum rtx_code));
  extern int address_cost			PARAMS ((rtx, enum machine_mode));
! extern int delete_trivially_dead_insns	PARAMS ((rtx, int, int));
  #ifdef BUFSIZ
  extern int cse_main			PARAMS ((rtx, int, int, FILE *));
  #endif
--- 1792,1798 ----
  
  extern int rtx_cost			PARAMS ((rtx, enum rtx_code));
  extern int address_cost			PARAMS ((rtx, enum machine_mode));
! extern int delete_trivially_dead_insns	PARAMS ((rtx, int));
  #ifdef BUFSIZ
  extern int cse_main			PARAMS ((rtx, int, int, FILE *));
  #endif
*** Makefile.in.old	Sun Mar  3 17:24:13 2002
--- Makefile.in	Sun Mar  3 17:23:50 2002
*************** cselib.o : cselib.c $(CONFIG_H) $(SYSTEM
*** 1444,1450 ****
     output.h function.h cselib.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
  cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
     real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \
!    $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H)
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h \
     flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
     function.h output.h toplev.h $(TM_P_H) $(PARAMS_H)
--- 1444,1450 ----
     output.h function.h cselib.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
  cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
     real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \
!    $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H)
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h \
     flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
     function.h output.h toplev.h $(TM_P_H) $(PARAMS_H)
*** timervar.def.old	Sun Mar  3 17:24:51 2002
--- timevar.def	Sun Mar  3 17:02:51 2002
*************** DEFTIMEVAR (TV_DUMP                  , "
*** 43,48 ****
--- 43,49 ----
  DEFTIMEVAR (TV_CFG                   , "cfg construction")
  /* Time spent by cleaning up CFG.  */
  DEFTIMEVAR (TV_CLEANUP_CFG           , "cfg cleanup")
+ DEFTIMEVAR (TV_DELETE_TRIVIALLY_DEAD , "trivially dead code")
  /* Time spent by life analysis.  */
  DEFTIMEVAR (TV_LIFE		     , "life analysis")
  DEFTIMEVAR (TV_LIFE_UPDATE	     , "life info update")


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