From: Jan Hubicka Date: Mon, 16 Jul 2001 20:54:44 +0000 (+0200) Subject: basic-block.h (CLEANUP_PRE_SIBCALL): New constant. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4793dca1588681eb583ccfd7cd179216c2d44d7e;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef999bf7f7d..f012bdae56c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +Mon Jul 16 22:48:00 CEST 2001 Jan Hubicka + + * 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 * regclass.c (init_reg_sets): Use only 32 bits per initializer diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 656c13b9801..5b210fb981b 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -540,6 +540,8 @@ enum update_life_extent #define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */ #define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need to care REG_DEAD notes. */ +#define CLEANUP_PRE_SIBCALL 8 /* Do not get confused by code hidden + inside call_placeholders.. */ /* Flags for loop discovery. */ #define LOOP_TREE 1 /* Build loop hierarchy tree. */ diff --git a/gcc/config.in b/gcc/config.in index e9b10ef750d..53995ba2e4b 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1,4 +1,4 @@ -/* 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. */ #undef const diff --git a/gcc/cse.c b/gcc/cse.c index 266f258d758..70360d86993 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -689,6 +689,9 @@ static struct cse_reg_info * get_cse_reg_info PARAMS ((unsigned int)); static int check_dependence PARAMS ((rtx *, 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. This function is used only for debugging. */ @@ -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 that is never used or they copy a register to itself. @@ -7490,17 +7585,16 @@ count_reg_usage (x, counts, dest, incr) remaining passes of the compilation are also sped up. */ void -delete_trivially_dead_insns (insns, nreg) +delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks) rtx insns; int nreg; + int preserve_basic_blocks; { int *counts; rtx insn, prev; -#ifdef HAVE_cc0 - rtx tem; -#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)); @@ -7518,124 +7612,89 @@ delete_trivially_dead_insns (insns, nreg) if (! INSN_P (insn)) insn = prev_real_insn (insn); - for (; insn; insn = prev) - { - int live_insn = 0; - rtx note; - - prev = prev_real_insn (insn); + if (!preserve_basic_blocks) + for (; insn; insn = prev) + { + int live_insn = 0; + rtx note; - /* Don't delete any insns that are part of a libcall block unless - we can delete the whole libcall block. + prev = prev_real_insn (insn); - 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; + /* Don't delete any insns that are part of a libcall block unless + we can delete the whole libcall block. - /* See if there's a REG_EQUAL note on this insn and try to - replace the source with the REG_EQUAL expression. + 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, 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 - 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 this is a dead insn, delete it and show registers in it aren't + being used. */ - if (!new) - new = XEXP (note, 0); + if (! live_insn) + { + count_reg_usage (insn, counts, NULL_RTX, -1); + delete_insn (insn); + } - 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 (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) { - if (set_noop_p (PATTERN (insn))) - ; + int live_insn = 0; + rtx note; -#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); + prev = PREV_INSN (insn); + if (!INSN_P (insn)) + continue; - if (GET_CODE (elt) == SET) - { - if (set_noop_p (elt)) - ; + /* Don't delete any insns that are part of a libcall block unless + we can delete the whole libcall block. -#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) + 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; - } - else - 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); - /* If this is a dead insn, delete it and show registers in it aren't - being used. */ + /* 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 (! 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; + if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) + { + in_libcall = 0; + dead_libcall = 0; + } } - } /* Clean up. */ free (counts); diff --git a/gcc/except.c b/gcc/except.c index 82ef3fe0944..da501012648 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -2347,7 +2347,7 @@ finish_eh_generation () connect many of the handlers, and then type information will not 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); cleanup_cfg (0); @@ -2370,7 +2370,7 @@ finish_eh_generation () /* We've totally changed the CFG. Start over. */ find_exception_handler_labels (); - jump_optimize_minimal (get_insns ()); + rebuild_jump_labels (get_insns ()); find_basic_blocks (get_insns (), max_reg_num (), 0); cleanup_cfg (0); } diff --git a/gcc/flow.c b/gcc/flow.c index 6d25582cebc..a771ab4c3d1 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -135,6 +135,7 @@ Boston, MA 02111-1307, USA. */ #include "recog.h" #include "expr.h" #include "ssa.h" +#include "timevar.h" #include "obstack.h" #include "splay-tree.h" @@ -499,6 +500,7 @@ find_basic_blocks (f, nregs, file) FILE *file ATTRIBUTE_UNUSED; { int max_uid; + timevar_push (TV_CFG); /* Flush out existing data. */ if (basic_block_info != NULL) @@ -556,6 +558,7 @@ find_basic_blocks (f, nregs, file) #ifdef ENABLE_CHECKING verify_flow_info (); #endif + timevar_pop (TV_CFG); } void @@ -1002,6 +1005,7 @@ void cleanup_cfg (mode) int mode; { + timevar_push (TV_CLEANUP_CFG); delete_unreachable_blocks (); if (try_optimize_cfg (mode)) delete_unreachable_blocks (); @@ -1010,6 +1014,7 @@ cleanup_cfg (mode) /* Kill the data we won't maintain. */ free_EXPR_LIST_list (&label_value_list); free_EXPR_LIST_list (&tail_recursion_label_list); + timevar_pop (TV_CLEANUP_CFG); } /* Create a new basic block consisting of the instructions between @@ -2960,6 +2965,14 @@ merge_blocks (e, b, c, mode) int c_has_outgoing_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, lexical blocks, and loop notes. @@ -3688,6 +3701,26 @@ try_optimize_cfg (mode) 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. */ while ((s = b->succ) != NULL && s->succ_next == NULL diff --git a/gcc/integrate.c b/gcc/integrate.c index bcb65e826a3..a642dcc1e08 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -427,6 +427,13 @@ save_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, those insns are not copied. `expand_inline_function' must emit the correct code to handle such things. */ @@ -1552,17 +1559,11 @@ copy_insn_list (insns, map, static_chain_value) discarded because it is important to have only one of each in the current function. - 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. */ + NOTE_INSN_DELETED notes aren't useful. */ if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG - && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED - && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK) + && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED) { copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn)); diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index bdd1c98dbbf..19f666087bd 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -303,7 +303,7 @@ stack_regs_mentioned (insn) unsigned int uid, max; int test; - if (! INSN_P (insn)) + if (! INSN_P (insn) || !stack_regs_mentioned_data) return 0; uid = INSN_UID (insn); @@ -419,6 +419,13 @@ reg_to_stack (first, file) int max_uid; 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) split_all_insns (0); @@ -479,11 +486,8 @@ reg_to_stack (first, file) VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1, "stack_regs_mentioned cache"); - if (convert_regs (file) && optimize) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_CROSSJUMP | CLEANUP_POST_REGSTACK); + convert_regs (file); - /* Clean up. */ - VARRAY_FREE (stack_regs_mentioned_data); free (bi); } diff --git a/gcc/rtl.h b/gcc/rtl.h index 5dd39862097..0401f8deea8 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1689,7 +1689,7 @@ struct cse_basic_block_data; 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)); +extern void delete_trivially_dead_insns PARAMS ((rtx, int, int)); #ifdef BUFSIZ extern int cse_main PARAMS ((rtx, int, int, FILE *)); #endif diff --git a/gcc/sibcall.c b/gcc/sibcall.c index 62184e84a5b..1203e684234 100644 --- a/gcc/sibcall.c +++ b/gcc/sibcall.c @@ -565,11 +565,11 @@ optimize_sibling_and_tail_recursive_calls () ahead and find all the EH labels. */ find_exception_handler_labels (); - jump_optimize_minimal (insns); + rebuild_jump_labels (insns); /* We need cfg information to determine which blocks are succeeded only by the epilogue. */ 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 (n_basic_blocks == 0) diff --git a/gcc/timevar.def b/gcc/timevar.def index f07a7d26434..1ad57a1c504 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -39,6 +39,10 @@ DEFTIMEVAR (TV_GC , "garbage collection") /* Time spent generating 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. */ DEFTIMEVAR (TV_CPP , "preprocessing") DEFTIMEVAR (TV_LEX , "lexical analysis") diff --git a/gcc/toplev.c b/gcc/toplev.c index 746ea908afa..e357d62b6d3 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2827,17 +2827,18 @@ rest_of_compilation (decl) if (DECL_DEFER_OUTPUT (decl)) { /* 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 - work necessary to make that safe. And, we set optimize to zero - to keep jump_optimize from working too hard. */ + work necessary to make that safe. */ if (warn_return_type) { int saved_optimize = optimize; optimize = 0; + rebuild_jump_labels (insns); 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; } @@ -3092,7 +3093,7 @@ rest_of_compilation (decl) /* 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 ()); + 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) @@ -3195,7 +3196,7 @@ rest_of_compilation (decl) 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 ()); + delete_trivially_dead_insns (insns, max_reg_num (), 0); /* The regscan pass is currently necessary as the alias analysis code depends on this information. */ @@ -3228,7 +3229,7 @@ rest_of_compilation (decl) 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 ()); + delete_trivially_dead_insns (insns, max_reg_num (), 0); reg_scan (insns, max_reg_num (), 0); jump_optimize (insns, !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN); @@ -3672,15 +3673,22 @@ rest_of_compilation (decl) ggc_collect (); #endif - if (optimize > 0 && flag_reorder_blocks) + if (optimize > 0) { timevar_push (TV_REORDER_BLOCKS); 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); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); timevar_pop (TV_REORDER_BLOCKS); }