Commit 4793dca1 by Jan Hubicka Committed by Jan Hubicka

basic-block.h (CLEANUP_PRE_SIBCALL): New constant.

	* basic-block.h (CLEANUP_PRE_SIBCALL): New constant.
	* except.c (finish_eh_generation): Update call of cleanup_cfg;
	do rebuild_jump_labels instead of jump_optimize
	* sibcall.c (optimize_sibling_and_tail_recursive_call): Likewise.
	* toplev.c (rest_of_compulation): Likewise for -Wreturn_type.
	* flow.c (try_optimize_cfg): Remove unneeded code_labels.

	* flow.c: Include timevar.h
	(find_basic_block): Push/pop timevar;
	(cleanup_cfg): Likewise.
	* timevar.def (TV_CFG, TV_CLEANUP_CFG): New.
	* Makefile: Add dependencies on timevar.h

	* integrate.c (save_for_inline): Kill all BASIC_BLOCK notes.
	(copy_insn_list): Avoid killing of BASIC_BLOCK notes.

	* rtl.h (delete_trivially_dead_insns): Add new parameter.
	* toplev.c (rest_of_compilation): Update calls.
	* cse.c (set_live_p, 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.

	* reg-stack.c (stack_regs_mentioned): Return 0 if
	stack_regs_mentioned_data is not initialized.
	(reg_to_stack): Make stack_regs_mentioned survive after the
	reg-stack is completted; do not call cleanup_cfg.
	* toplev.c (rest_of_compilation): Do cleanup_cfg before bb-reorder;
	make cleanup_cfg after bb-reorder to output to debug file.

From-SVN: r44056
parent ccef9ef5
Mon Jul 16 22:48:00 CEST 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (CLEANUP_PRE_SIBCALL): New constant.
* except.c (finish_eh_generation): Update call of cleanup_cfg;
do rebuild_jump_labels instead of jump_optimize
* sibcall.c (optimize_sibling_and_tail_recursive_call): Likewise.
* toplev.c (rest_of_compulation): Likewise for -Wreturn_type.
* flow.c (try_optimize_cfg): Remove unneeded code_labels.
* flow.c: Include timevar.h
(find_basic_block): Push/pop timevar;
(cleanup_cfg): Likewise.
* timevar.def (TV_CFG, TV_CLEANUP_CFG): New.
* Makefile: Add dependencies on timevar.h
* integrate.c (save_for_inline): Kill all BASIC_BLOCK notes.
(copy_insn_list): Avoid killing of BASIC_BLOCK notes.
* rtl.h (delete_trivially_dead_insns): Add new parameter.
* toplev.c (rest_of_compilation): Update calls.
* cse.c (set_live_p, 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.
* reg-stack.c (stack_regs_mentioned): Return 0 if
stack_regs_mentioned_data is not initialized.
(reg_to_stack): Make stack_regs_mentioned survive after the
reg-stack is completted; do not call cleanup_cfg.
* toplev.c (rest_of_compilation): Do cleanup_cfg before bb-reorder;
make cleanup_cfg after bb-reorder to output to debug file.
2001-07-16 Richard Henderson <rth@redhat.com> 2001-07-16 Richard Henderson <rth@redhat.com>
* regclass.c (init_reg_sets): Use only 32 bits per initializer * regclass.c (init_reg_sets): Use only 32 bits per initializer
......
...@@ -540,6 +540,8 @@ enum update_life_extent ...@@ -540,6 +540,8 @@ enum update_life_extent
#define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */ #define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */
#define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need #define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need
to care REG_DEAD notes. */ to care REG_DEAD notes. */
#define CLEANUP_PRE_SIBCALL 8 /* Do not get confused by code hidden
inside call_placeholders.. */
/* Flags for loop discovery. */ /* Flags for loop discovery. */
#define LOOP_TREE 1 /* Build loop hierarchy tree. */ #define LOOP_TREE 1 /* Build loop hierarchy tree. */
......
/* config.in. Generated automatically from configure.in by autoheader 2.13. */ /* config.in. Generated automatically from configure.in by autoheader. */
/* Define to empty if the keyword does not work. */ /* Define to empty if the keyword does not work. */
#undef const #undef const
......
...@@ -689,6 +689,9 @@ static struct cse_reg_info * get_cse_reg_info PARAMS ((unsigned int)); ...@@ -689,6 +689,9 @@ static struct cse_reg_info * get_cse_reg_info PARAMS ((unsigned int));
static int check_dependence PARAMS ((rtx *, void *)); static int check_dependence PARAMS ((rtx *, void *));
static void flush_hash_table PARAMS ((void)); static void flush_hash_table PARAMS ((void));
static bool insn_live_p PARAMS ((rtx, int *));
static bool set_live_p PARAMS ((rtx, int *));
static bool dead_libcall_p PARAMS ((rtx, int *));
/* Dump the expressions in the equivalence class indicated by CLASSP. /* Dump the expressions in the equivalence class indicated by CLASSP.
This function is used only for debugging. */ This function is used only for debugging. */
...@@ -7481,6 +7484,98 @@ count_reg_usage (x, counts, dest, incr) ...@@ -7481,6 +7484,98 @@ count_reg_usage (x, counts, dest, incr)
} }
} }
/* Return true if set is live. */
static bool
set_live_p (set, counts)
rtx set;
int *counts;
{
#ifdef HAVE_cc0
rtx tem;
#endif
if (set_noop_p (set))
;
#ifdef HAVE_cc0
else if (GET_CODE (SET_DEST (set)) == CC0
&& !side_effects_p (SET_SRC (set))
&& ((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 (set)) != REG
|| REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
|| counts[REGNO (SET_DEST (set))] != 0
|| side_effects_p (SET_SRC (set))
/* 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 (set) == current_function_internal_arg_pointer))
return true;
return false;
}
/* 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)
return set_live_p (PATTERN (insn), counts);
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_live_p (elt, counts))
return true;
}
else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
return true;
}
else
return true;
}
/* 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 /* 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. that is never used or they copy a register to itself.
...@@ -7490,17 +7585,16 @@ count_reg_usage (x, counts, dest, incr) ...@@ -7490,17 +7585,16 @@ count_reg_usage (x, counts, dest, incr)
remaining passes of the compilation are also sped up. */ remaining passes of the compilation are also sped up. */
void void
delete_trivially_dead_insns (insns, nreg) delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
rtx insns; rtx insns;
int nreg; int nreg;
int preserve_basic_blocks;
{ {
int *counts; int *counts;
rtx insn, prev; rtx insn, prev;
#ifdef HAVE_cc0
rtx tem;
#endif
int i; int i;
int in_libcall = 0, dead_libcall = 0; int in_libcall = 0, dead_libcall = 0;
basic_block bb;
/* First count the number of times each register is used. */ /* First count the number of times each register is used. */
counts = (int *) xcalloc (nreg, sizeof (int)); counts = (int *) xcalloc (nreg, sizeof (int));
...@@ -7518,124 +7612,89 @@ delete_trivially_dead_insns (insns, nreg) ...@@ -7518,124 +7612,89 @@ delete_trivially_dead_insns (insns, nreg)
if (! INSN_P (insn)) if (! INSN_P (insn))
insn = prev_real_insn (insn); insn = prev_real_insn (insn);
for (; insn; insn = prev) if (!preserve_basic_blocks)
{ for (; insn; insn = prev)
int live_insn = 0; {
rtx note; int live_insn = 0;
rtx note;
prev = prev_real_insn (insn);
/* Don't delete any insns that are part of a libcall block unless prev = prev_real_insn (insn);
we can delete the whole libcall block.
Flow or loop might get confused if we did that. Remember /* Don't delete any insns that are part of a libcall block unless
that we are scanning backwards. */ we can delete the whole libcall block.
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 Flow or loop might get confused if we did that. Remember
replace the source with the REG_EQUAL expression. 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, counts);
}
else if (in_libcall)
live_insn = ! dead_libcall;
else
live_insn = insn_live_p (insn, counts);
We assume that insns with REG_RETVALs can only be reg->reg /* If this is a dead insn, delete it and show registers in it aren't
copies at this point. */ being used. */
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) if (! live_insn)
new = XEXP (note, 0); {
count_reg_usage (insn, counts, NULL_RTX, -1);
delete_insn (insn);
}
if (set && validate_change (insn, &SET_SRC (set), new, 0)) if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
{ {
remove_note (insn, in_libcall = 0;
find_reg_note (insn, REG_RETVAL, NULL_RTX)); dead_libcall = 0;
dead_libcall = 1; }
} }
} else
} for (i = 0; i < n_basic_blocks; i++)
else if (in_libcall) for (bb = BASIC_BLOCK (i), insn = bb->end; insn != bb->head; insn = prev)
live_insn = ! dead_libcall;
else if (GET_CODE (PATTERN (insn)) == SET)
{ {
if (set_noop_p (PATTERN (insn))) int live_insn = 0;
; rtx note;
#ifdef HAVE_cc0 prev = PREV_INSN (insn);
else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0 if (!INSN_P (insn))
&& ! side_effects_p (SET_SRC (PATTERN (insn))) continue;
&& ((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) /* Don't delete any insns that are part of a libcall block unless
{ we can delete the whole libcall block.
if (set_noop_p (elt))
;
#ifdef HAVE_cc0 Flow or loop might get confused if we did that. Remember
else if (GET_CODE (SET_DEST (elt)) == CC0 that we are scanning backwards. */
&& ! side_effects_p (SET_SRC (elt)) if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
&& ((tem = next_nonnote_insn (insn)) == 0 {
|| ! INSN_P (tem) in_libcall = 1;
|| ! 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; live_insn = 1;
} dead_libcall = dead_libcall_p (insn, counts);
else }
live_insn = 1; 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 /* If this is a dead insn, delete it and show registers in it aren't
being used. */ being used. */
if (! live_insn) if (! live_insn)
{ {
count_reg_usage (insn, counts, NULL_RTX, -1); count_reg_usage (insn, counts, NULL_RTX, -1);
delete_insn (insn); if (insn == bb->end)
} bb->end = PREV_INSN (insn);
flow_delete_insn (insn);
}
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
{ {
in_libcall = 0; in_libcall = 0;
dead_libcall = 0; dead_libcall = 0;
}
} }
}
/* Clean up. */ /* Clean up. */
free (counts); free (counts);
......
...@@ -2347,7 +2347,7 @@ finish_eh_generation () ...@@ -2347,7 +2347,7 @@ finish_eh_generation ()
connect many of the handlers, and then type information will not connect many of the handlers, and then type information will not
be effective. Still, this is a win over previous implementations. */ be effective. Still, this is a win over previous implementations. */
jump_optimize_minimal (get_insns ()); rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0); find_basic_blocks (get_insns (), max_reg_num (), 0);
cleanup_cfg (0); cleanup_cfg (0);
...@@ -2370,7 +2370,7 @@ finish_eh_generation () ...@@ -2370,7 +2370,7 @@ finish_eh_generation ()
/* We've totally changed the CFG. Start over. */ /* We've totally changed the CFG. Start over. */
find_exception_handler_labels (); find_exception_handler_labels ();
jump_optimize_minimal (get_insns ()); rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0); find_basic_blocks (get_insns (), max_reg_num (), 0);
cleanup_cfg (0); cleanup_cfg (0);
} }
......
...@@ -135,6 +135,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -135,6 +135,7 @@ Boston, MA 02111-1307, USA. */
#include "recog.h" #include "recog.h"
#include "expr.h" #include "expr.h"
#include "ssa.h" #include "ssa.h"
#include "timevar.h"
#include "obstack.h" #include "obstack.h"
#include "splay-tree.h" #include "splay-tree.h"
...@@ -499,6 +500,7 @@ find_basic_blocks (f, nregs, file) ...@@ -499,6 +500,7 @@ find_basic_blocks (f, nregs, file)
FILE *file ATTRIBUTE_UNUSED; FILE *file ATTRIBUTE_UNUSED;
{ {
int max_uid; int max_uid;
timevar_push (TV_CFG);
/* Flush out existing data. */ /* Flush out existing data. */
if (basic_block_info != NULL) if (basic_block_info != NULL)
...@@ -556,6 +558,7 @@ find_basic_blocks (f, nregs, file) ...@@ -556,6 +558,7 @@ find_basic_blocks (f, nregs, file)
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_flow_info (); verify_flow_info ();
#endif #endif
timevar_pop (TV_CFG);
} }
void void
...@@ -1002,6 +1005,7 @@ void ...@@ -1002,6 +1005,7 @@ void
cleanup_cfg (mode) cleanup_cfg (mode)
int mode; int mode;
{ {
timevar_push (TV_CLEANUP_CFG);
delete_unreachable_blocks (); delete_unreachable_blocks ();
if (try_optimize_cfg (mode)) if (try_optimize_cfg (mode))
delete_unreachable_blocks (); delete_unreachable_blocks ();
...@@ -1010,6 +1014,7 @@ cleanup_cfg (mode) ...@@ -1010,6 +1014,7 @@ cleanup_cfg (mode)
/* Kill the data we won't maintain. */ /* Kill the data we won't maintain. */
free_EXPR_LIST_list (&label_value_list); free_EXPR_LIST_list (&label_value_list);
free_EXPR_LIST_list (&tail_recursion_label_list); free_EXPR_LIST_list (&tail_recursion_label_list);
timevar_pop (TV_CLEANUP_CFG);
} }
/* Create a new basic block consisting of the instructions between /* Create a new basic block consisting of the instructions between
...@@ -2960,6 +2965,14 @@ merge_blocks (e, b, c, mode) ...@@ -2960,6 +2965,14 @@ merge_blocks (e, b, c, mode)
int c_has_outgoing_fallthru; int c_has_outgoing_fallthru;
int b_has_incoming_fallthru; int b_has_incoming_fallthru;
/* Avoid overactive code motion, as the forwarder blocks should eb
eliminated by the edge redirection instead. Only exception is the
case b is an forwarder block and c has no fallthru edge, but no
optimizers should be confused by this extra jump and we are about
to kill the jump in bb_reorder pass instead. */
if (forwarder_block_p (b) || forwarder_block_p (c))
return 0;
/* We must make sure to not munge nesting of exception regions, /* We must make sure to not munge nesting of exception regions,
lexical blocks, and loop notes. lexical blocks, and loop notes.
...@@ -3688,6 +3701,26 @@ try_optimize_cfg (mode) ...@@ -3688,6 +3701,26 @@ try_optimize_cfg (mode)
b = c; b = c;
} }
/* Remove code labels no longer used.
Don't do the optimization before sibling calls are discovered,
as some branches may be hidden inside CALL_PLACEHOLDERs. */
if (!(mode & CLEANUP_PRE_SIBCALL)
&& b->pred->pred_next == NULL
&& (b->pred->flags & EDGE_FALLTHRU)
&& GET_CODE (b->head) == CODE_LABEL
/* If previous block does end with condjump jumping to next BB,
we can't delete the label. */
&& (b->pred->src == ENTRY_BLOCK_PTR
|| !reg_mentioned_p (b->head, b->pred->src->end)))
{
rtx label = b->head;
b->head = NEXT_INSN (b->head);
flow_delete_insn_chain (label, label);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleted label in block %i.\n",
b->index);
}
/* A loop because chains of blocks might be combineable. */ /* A loop because chains of blocks might be combineable. */
while ((s = b->succ) != NULL while ((s = b->succ) != NULL
&& s->succ_next == NULL && s->succ_next == NULL
......
...@@ -427,6 +427,13 @@ save_for_inline (fndecl) ...@@ -427,6 +427,13 @@ save_for_inline (fndecl)
argvec = initialize_for_inline (fndecl); argvec = initialize_for_inline (fndecl);
/* Delete basic block notes created by early run of find_basic_block.
The notes would be later used by find_basic_blocks to reuse the memory
for basic_block structures on already freed obstack. */
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
delete_insn (insn);
/* If there are insns that copy parms from the stack into pseudo registers, /* If there are insns that copy parms from the stack into pseudo registers,
those insns are not copied. `expand_inline_function' must those insns are not copied. `expand_inline_function' must
emit the correct code to handle such things. */ emit the correct code to handle such things. */
...@@ -1552,17 +1559,11 @@ copy_insn_list (insns, map, static_chain_value) ...@@ -1552,17 +1559,11 @@ copy_insn_list (insns, map, static_chain_value)
discarded because it is important to have only one of discarded because it is important to have only one of
each in the current function. each in the current function.
NOTE_INSN_DELETED notes aren't useful. NOTE_INSN_DELETED notes aren't useful. */
NOTE_INSN_BASIC_BLOCK is discarded because the saved bb
pointer (which will soon be dangling) confuses flow's
attempts to preserve bb structures during the compilation
of a function. */
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
{ {
copy = emit_note (NOTE_SOURCE_FILE (insn), copy = emit_note (NOTE_SOURCE_FILE (insn),
NOTE_LINE_NUMBER (insn)); NOTE_LINE_NUMBER (insn));
......
...@@ -303,7 +303,7 @@ stack_regs_mentioned (insn) ...@@ -303,7 +303,7 @@ stack_regs_mentioned (insn)
unsigned int uid, max; unsigned int uid, max;
int test; int test;
if (! INSN_P (insn)) if (! INSN_P (insn) || !stack_regs_mentioned_data)
return 0; return 0;
uid = INSN_UID (insn); uid = INSN_UID (insn);
...@@ -419,6 +419,13 @@ reg_to_stack (first, file) ...@@ -419,6 +419,13 @@ reg_to_stack (first, file)
int max_uid; int max_uid;
block_info bi; block_info bi;
/* Clean up previous run. */
if (stack_regs_mentioned_data)
{
VARRAY_FREE (stack_regs_mentioned_data);
stack_regs_mentioned_data = 0;
}
if (!optimize) if (!optimize)
split_all_insns (0); split_all_insns (0);
...@@ -479,11 +486,8 @@ reg_to_stack (first, file) ...@@ -479,11 +486,8 @@ reg_to_stack (first, file)
VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1, VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
"stack_regs_mentioned cache"); "stack_regs_mentioned cache");
if (convert_regs (file) && optimize) convert_regs (file);
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_CROSSJUMP | CLEANUP_POST_REGSTACK);
/* Clean up. */
VARRAY_FREE (stack_regs_mentioned_data);
free (bi); free (bi);
} }
......
...@@ -1689,7 +1689,7 @@ struct cse_basic_block_data; ...@@ -1689,7 +1689,7 @@ struct cse_basic_block_data;
extern int rtx_cost PARAMS ((rtx, enum rtx_code)); extern int rtx_cost PARAMS ((rtx, enum rtx_code));
extern int address_cost PARAMS ((rtx, enum machine_mode)); extern int address_cost PARAMS ((rtx, enum machine_mode));
extern void delete_trivially_dead_insns PARAMS ((rtx, int)); extern void delete_trivially_dead_insns PARAMS ((rtx, int, int));
#ifdef BUFSIZ #ifdef BUFSIZ
extern int cse_main PARAMS ((rtx, int, int, FILE *)); extern int cse_main PARAMS ((rtx, int, int, FILE *));
#endif #endif
......
...@@ -565,11 +565,11 @@ optimize_sibling_and_tail_recursive_calls () ...@@ -565,11 +565,11 @@ optimize_sibling_and_tail_recursive_calls ()
ahead and find all the EH labels. */ ahead and find all the EH labels. */
find_exception_handler_labels (); find_exception_handler_labels ();
jump_optimize_minimal (insns); rebuild_jump_labels (insns);
/* We need cfg information to determine which blocks are succeeded /* We need cfg information to determine which blocks are succeeded
only by the epilogue. */ only by the epilogue. */
find_basic_blocks (insns, max_reg_num (), 0); find_basic_blocks (insns, max_reg_num (), 0);
cleanup_cfg (0); cleanup_cfg (CLEANUP_PRE_SIBCALL);
/* If there are no basic blocks, then there is nothing to do. */ /* If there are no basic blocks, then there is nothing to do. */
if (n_basic_blocks == 0) if (n_basic_blocks == 0)
......
...@@ -39,6 +39,10 @@ DEFTIMEVAR (TV_GC , "garbage collection") ...@@ -39,6 +39,10 @@ DEFTIMEVAR (TV_GC , "garbage collection")
/* Time spent generating dump files. */ /* Time spent generating dump files. */
DEFTIMEVAR (TV_DUMP , "dump files") DEFTIMEVAR (TV_DUMP , "dump files")
/* Time spent by constructing CFG. */
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */
DEFTIMEVAR (TV_CLEANUP_CFG , "cfg cleanup")
/* Timing in various stages of the compiler. */ /* Timing in various stages of the compiler. */
DEFTIMEVAR (TV_CPP , "preprocessing") DEFTIMEVAR (TV_CPP , "preprocessing")
DEFTIMEVAR (TV_LEX , "lexical analysis") DEFTIMEVAR (TV_LEX , "lexical analysis")
......
...@@ -2827,17 +2827,18 @@ rest_of_compilation (decl) ...@@ -2827,17 +2827,18 @@ rest_of_compilation (decl)
if (DECL_DEFER_OUTPUT (decl)) if (DECL_DEFER_OUTPUT (decl))
{ {
/* If -Wreturn-type, we have to do a bit of compilation. We just /* If -Wreturn-type, we have to do a bit of compilation. We just
want to call jump_optimize to figure out whether or not we can want to call cleanup the cfg to figure out whether or not we can
fall off the end of the function; we do the minimum amount of fall off the end of the function; we do the minimum amount of
work necessary to make that safe. And, we set optimize to zero work necessary to make that safe. */
to keep jump_optimize from working too hard. */
if (warn_return_type) if (warn_return_type)
{ {
int saved_optimize = optimize; int saved_optimize = optimize;
optimize = 0; optimize = 0;
rebuild_jump_labels (insns);
find_exception_handler_labels (); find_exception_handler_labels ();
jump_optimize (insns, !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN); find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
cleanup_cfg (CLEANUP_PRE_SIBCALL);
optimize = saved_optimize; optimize = saved_optimize;
} }
...@@ -3092,7 +3093,7 @@ rest_of_compilation (decl) ...@@ -3092,7 +3093,7 @@ rest_of_compilation (decl)
/* Run this after jump optmizations remove all the unreachable code /* Run this after jump optmizations remove all the unreachable code
so that unreachable code will not keep values live. */ so that unreachable code will not keep values live. */
delete_trivially_dead_insns (insns, max_reg_num ()); delete_trivially_dead_insns (insns, max_reg_num (), 0);
/* Try to identify useless null pointer tests and delete them. */ /* Try to identify useless null pointer tests and delete them. */
if (flag_delete_null_pointer_checks) if (flag_delete_null_pointer_checks)
...@@ -3195,7 +3196,7 @@ rest_of_compilation (decl) ...@@ -3195,7 +3196,7 @@ rest_of_compilation (decl)
trivially dead. We delete those instructions now in the trivially dead. We delete those instructions now in the
hope that doing so will make the heuristics in loop work hope that doing so will make the heuristics in loop work
better and possibly speed up compilation. */ better and possibly speed up compilation. */
delete_trivially_dead_insns (insns, max_reg_num ()); delete_trivially_dead_insns (insns, max_reg_num (), 0);
/* The regscan pass is currently necessary as the alias /* The regscan pass is currently necessary as the alias
analysis code depends on this information. */ analysis code depends on this information. */
...@@ -3228,7 +3229,7 @@ rest_of_compilation (decl) ...@@ -3228,7 +3229,7 @@ rest_of_compilation (decl)
trivially dead. We delete those instructions now in the trivially dead. We delete those instructions now in the
hope that doing so will make the heuristics in jump work hope that doing so will make the heuristics in jump work
better and possibly speed up compilation. */ better and possibly speed up compilation. */
delete_trivially_dead_insns (insns, max_reg_num ()); delete_trivially_dead_insns (insns, max_reg_num (), 0);
reg_scan (insns, max_reg_num (), 0); reg_scan (insns, max_reg_num (), 0);
jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN); jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
...@@ -3672,15 +3673,22 @@ rest_of_compilation (decl) ...@@ -3672,15 +3673,22 @@ rest_of_compilation (decl)
ggc_collect (); ggc_collect ();
#endif #endif
if (optimize > 0 && flag_reorder_blocks) if (optimize > 0)
{ {
timevar_push (TV_REORDER_BLOCKS); timevar_push (TV_REORDER_BLOCKS);
open_dump_file (DFI_bbro, decl); open_dump_file (DFI_bbro, decl);
reorder_basic_blocks (); /* Last attempt to optimize CFG, as life analyzis possibly removed
some instructions. */
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
| CLEANUP_CROSSJUMP);
if (flag_reorder_blocks)
{
reorder_basic_blocks ();
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
}
close_dump_file (DFI_bbro, print_rtl_with_bb, insns); close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
timevar_pop (TV_REORDER_BLOCKS); timevar_pop (TV_REORDER_BLOCKS);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment