This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
delete_trivially_dead_insns cleanup
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com
- Date: Sun, 3 Mar 2002 19:22:16 +0100
- Subject: 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")