This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
make delete_trivially_dead CFG friendly
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com, patches at x86-64 dot org
- Subject: make delete_trivially_dead CFG friendly
- From: Jan Hubicka <jh at suse dot cz>
- Date: Fri, 29 Jun 2001 15:02:14 +0200
Hi,
this patch makes delete_trivially_dead_insns to work with flowgraph,
so it can be used for quick cleanup after new jump pass as well as for
some other tricks.
In future we will likely remove the non-preserving loop.
Bootstrapped/regtested i586
Honza
Fri Jun 29 14:33:46 CEST 2001 Jan Hubicka <jh@suse.cz>
* rtl.h (delete_trivially_dead_insns): Add new parameter.
* toplev.c (rest_of_compilation): Update calls.
* 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.
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.265
diff -c -3 -p -r1.265 rtl.h
*** rtl.h 2001/06/20 07:18:12 1.265
--- rtl.h 2001/06/29 12:32:56
*************** 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
Index: cse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cse.c,v
retrieving revision 1.186
diff -c -3 -p -r1.186 cse.c
*** cse.c 2001/05/17 18:46:57 1.186
--- cse.c 2001/06/29 12:32:59
*************** 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
*** 7542,7666 ****
insn = get_last_insn ();
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);
--- 7642,7731 ----
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;
! 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;
! }
! 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 = 0;
! }
! 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);
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.475
diff -c -3 -p -r1.475 toplev.c
*** toplev.c 2001/06/26 19:24:08 1.475
--- toplev.c 2001/06/29 12:33:01
*************** 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,