This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: make delete_trivially_dead CFG friendly
- To: Richard Henderson <rth at redhat dot com>, Jan Hubicka <jh at suse dot cz>, gcc-patches at gcc dot gnu dot org, patches at x86-64 dot org
- Subject: Re: make delete_trivially_dead CFG friendly
- From: Jan Hubicka <jh at suse dot cz>
- Date: Wed, 11 Jul 2001 21:44:38 +0200
- References: <20010629150214.G13501@atrey.karlin.mff.cuni.cz> <20010629084414.C17456@redhat.com>
> 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,