From 308f9b7994783bcf7867e5c06fe3a88bd01d847f Mon Sep 17 00:00:00 2001 From: hubicka Date: Thu, 28 Feb 2002 10:11:01 +0000 Subject: [PATCH] * basic-block.h (BB_REACHABLE): Renumber. (BB_DIRTY, BB_NEW): New flags. (clear_bb_flags): Declare. (update_life_info_in_dirty_blocks): Declare. * cfg.c (clear_bb_flags): New function. * cfgrtl.c (create_basic_block_structure): Set flags to BB_NEW. * emit-rtl.c (add_insn_after, add_insn_before, remove_insn, reorder_insns, emit_insn_after): Mark block as dirty. * flow.c (update_life_info): Fix clearing of PROP_LOG_LINKS. (update_life_info_in_dirty_blocks): New function. * recog.c (apply_change_group): Dirtify block. * cse.c (cse_insn): Reorder emitting of jump insn to keep cfg consistent. * gcse.c (delete_null_pointer_checks): Likewise. * toplev.c (dump_file_index): Move cse2 after bp, add DFI_null (dump_file_info): Similary. (rest_of_compilation): Avoid most of CFG rebuilds; do first if converision after null pointer checks, do cse2 after branch prediction; avoid full liveness rebuild after initializing subregs. * invoke.texi (-d options): Document -du, renumber. * cfgcleanup.c (bb_flags): Remove BB_UPDATE_LIFE. (notice_new_block): Do not set BB_UPDATE_LIFE. (try_forward_edges, merge_blocks_move_predecessor_nojumps, merge_blocks_move_successor_nojumps, merge_blocks, try_crossjump_to_edge): Likewise. (try_optimize_cfg): Likewise; use update_life_info_in_dirty_blocks. * cfgrtl.c (merge_blocks_nomove): Copy b's flags to a. * ifcvt.c (SET_UPDATE_LIFE, UPDATE_LIFE): Kill. (merge_of_block): Do not use life_data_ok. (find_if_case_1): Do not use SET_UPDATE_LIFE. (if_convert): Use BB_DIRTY mechanizm to update life. * lcm.c (optimize_mode_switching): Update update_life_info_in_dirty_blocks git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50127 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 41 ++++++++++ gcc/basic-block.h | 7 +- gcc/cfg.c | 11 +++ gcc/cfgcleanup.c | 48 +++--------- gcc/cfgrtl.c | 2 + gcc/cse.c | 3 +- gcc/doc/invoke.texi | 51 ++++++------ gcc/emit-rtl.c | 9 +++ gcc/flow.c | 33 +++++++- gcc/gcse.c | 4 +- gcc/ifcvt.c | 41 +++------- gcc/lcm.c | 16 ++-- gcc/recog.c | 11 +++ gcc/toplev.c | 221 +++++++++++++++++++++++++--------------------------- 14 files changed, 272 insertions(+), 226 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3074e4b47af..d757905eb2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,44 @@ +Don Feb 28 11:07:36 CET 2002 Jan Hubicka + + * basic-block.h (BB_REACHABLE): Renumber. + (BB_DIRTY, BB_NEW): New flags. + (clear_bb_flags): Declare. + (update_life_info_in_dirty_blocks): Declare. + * cfg.c (clear_bb_flags): New function. + * cfgrtl.c (create_basic_block_structure): Set flags to BB_NEW. + * emit-rtl.c (add_insn_after, add_insn_before, remove_insn, + reorder_insns, emit_insn_after): Mark block as dirty. + * flow.c (update_life_info): Fix clearing of PROP_LOG_LINKS. + (update_life_info_in_dirty_blocks): New function. + * recog.c (apply_change_group): Dirtify block. + + * cse.c (cse_insn): Reorder emitting of jump insn to keep + cfg consistent. + * gcse.c (delete_null_pointer_checks): Likewise. + + * toplev.c (dump_file_index): Move cse2 after bp, + add DFI_null + (dump_file_info): Similary. + (rest_of_compilation): Avoid most of CFG rebuilds; + do first if converision after null pointer checks, do cse2 + after branch prediction; avoid full liveness rebuild after + initializing subregs. + * invoke.texi (-d options): Document -du, renumber. + + * cfgcleanup.c (bb_flags): Remove BB_UPDATE_LIFE. + (notice_new_block): Do not set BB_UPDATE_LIFE. + (try_forward_edges, merge_blocks_move_predecessor_nojumps, + merge_blocks_move_successor_nojumps, merge_blocks, + try_crossjump_to_edge): Likewise. + (try_optimize_cfg): Likewise; use update_life_info_in_dirty_blocks. + * cfgrtl.c (merge_blocks_nomove): Copy b's flags to a. + * ifcvt.c (SET_UPDATE_LIFE, UPDATE_LIFE): Kill. + (merge_of_block): Do not use life_data_ok. + (find_if_case_1): Do not use SET_UPDATE_LIFE. + (if_convert): Use BB_DIRTY mechanizm to update life. + * lcm.c (optimize_mode_switching): Update + update_life_info_in_dirty_blocks + 2002-02-28 Neil Booth * Makefile.in (integrate.o): Update. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 1bc1d780f19..39e24c82760 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -221,7 +221,9 @@ typedef struct basic_block_def { #define BB_FREQ_MAX 10000 /* Masks for basic_block.flags. */ -#define BB_REACHABLE 1 +#define BB_DIRTY 1 +#define BB_NEW 2 +#define BB_REACHABLE 4 /* Number of basic blocks in the current function. */ @@ -311,6 +313,7 @@ extern void redirect_edge_pred PARAMS ((edge, basic_block)); extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx)); extern basic_block create_basic_block PARAMS ((int, rtx, rtx)); extern int flow_delete_block PARAMS ((basic_block)); +extern void clear_bb_flags PARAMS ((void)); extern void merge_blocks_nomove PARAMS ((basic_block, basic_block)); extern void tidy_fallthru_edge PARAMS ((edge, basic_block, basic_block)); @@ -587,6 +590,8 @@ enum update_life_extent extern void life_analysis PARAMS ((rtx, FILE *, int)); extern void update_life_info PARAMS ((sbitmap, enum update_life_extent, int)); +extern void update_life_info_in_dirty_blocks PARAMS ((enum update_life_extent, + int)); extern int count_or_remove_death_notes PARAMS ((sbitmap, int)); extern int propagate_block PARAMS ((basic_block, regset, regset, regset, int)); diff --git a/gcc/cfg.c b/gcc/cfg.c index 8adcef637b3..a33beffd0b2 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA dump_flow_info, debug_flow_info, dump_edge_info - Allocation of AUX fields for basic blocks alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block + - clear_bb_flags */ #include "config.h" @@ -440,6 +441,16 @@ redirect_edge_pred (e, new_pred) new_pred->succ = e; e->src = new_pred; } + +void +clear_bb_flags () +{ + int i; + ENTRY_BLOCK_PTR->flags = 0; + EXIT_BLOCK_PTR->flags = 0; + for (i = 0; i < n_basic_blocks; i++) + BASIC_BLOCK (i)->flags = 0; +} void dump_flow_info (file) diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index d9f9cf261e5..017a4aa5390 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -52,11 +52,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA enum bb_flags { - /* Set if life info needs to be recomputed for given BB. */ - BB_UPDATE_LIFE = 1, /* Set if BB is the forwarder block to avoid too many forwarder_block_p calls. */ - BB_FORWARDER_BLOCK = 2 + BB_FORWARDER_BLOCK = 1 }; #define BB_FLAGS(BB) (enum bb_flags) (BB)->aux @@ -101,7 +99,6 @@ notice_new_block (bb) if (!bb) return; - BB_SET_FLAG (bb, BB_UPDATE_LIFE); if (forwarder_block_p (bb)) BB_SET_FLAG (bb, BB_FORWARDER_BLOCK); } @@ -519,7 +516,6 @@ try_forward_edges (mode, b) if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b)) BB_SET_FLAG (b, BB_FORWARDER_BLOCK); - BB_SET_FLAG (b, BB_UPDATE_LIFE); do { @@ -663,7 +659,7 @@ merge_blocks_move_predecessor_nojumps (a, b) /* Scramble the insn chain. */ if (a->end != PREV_INSN (b->head)) reorder_insns_nobb (a->head, a->end, PREV_INSN (b->head)); - BB_SET_FLAG (a, BB_UPDATE_LIFE); + a->flags |= BB_DIRTY; if (rtl_dump_file) fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n", @@ -731,7 +727,6 @@ merge_blocks_move_successor_nojumps (a, b) /* Now blocks A and B are contiguous. Merge them. */ merge_blocks_nomove (a, b); - BB_SET_FLAG (a, BB_UPDATE_LIFE); if (rtl_dump_file) fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n", @@ -760,12 +755,6 @@ merge_blocks (e, b, c, mode) if (e->flags & EDGE_FALLTHRU) { int b_index = b->index, c_index = c->index; - /* We need to update liveness in case C already has broken liveness - or B ends by conditional jump to next instructions that will be - removed. */ - if ((BB_FLAGS (c) & BB_UPDATE_LIFE) - || GET_CODE (b->end) == JUMP_INSN) - BB_SET_FLAG (b, BB_UPDATE_LIFE); merge_blocks_nomove (b, c); update_forwarder_flag (b); @@ -831,8 +820,6 @@ merge_blocks (e, b, c, mode) bb = force_nonfallthru (b_fallthru_edge); if (bb) notice_new_block (bb); - else - BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE); } merge_blocks_move_predecessor_nojumps (b, c); @@ -1418,7 +1405,6 @@ try_crossjump_to_edge (mode, e1, e2) remove_edge (src1->succ); make_single_succ_edge (src1, redirect_to, 0); - BB_SET_FLAG (src1, BB_UPDATE_LIFE); update_forwarder_flag (src1); return true; @@ -1532,6 +1518,9 @@ try_optimize_cfg (mode) for (i = 0; i < n_basic_blocks; i++) update_forwarder_flag (BASIC_BLOCK (i)); + if (mode & CLEANUP_UPDATE_LIFE) + clear_bb_flags (); + if (! (* targetm.cannot_modify_jumps_p) ()) { /* Attempt to merge blocks as made possible by edge removal. If @@ -1633,10 +1622,7 @@ try_optimize_cfg (mode) /* Simplify branch over branch. */ if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b)) - { - BB_SET_FLAG (b, BB_UPDATE_LIFE); - changed_here = true; - } + changed_here = true; /* If B has a single outgoing edge, but uses a non-trivial jump instruction without side-effects, we @@ -1649,7 +1635,6 @@ try_optimize_cfg (mode) && onlyjump_p (b->end) && redirect_edge_and_branch (b->succ, b->succ->dest)) { - BB_SET_FLAG (b, BB_UPDATE_LIFE); update_forwarder_flag (b); changed_here = true; } @@ -1689,24 +1674,9 @@ try_optimize_cfg (mode) remove_fake_edges (); if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall) - { - bool found = 0; - - blocks = sbitmap_alloc (n_basic_blocks); - sbitmap_zero (blocks); - for (i = 0; i < n_basic_blocks; i++) - if (BB_FLAGS (BASIC_BLOCK (i)) & BB_UPDATE_LIFE) - { - found = 1; - SET_BIT (blocks, i); - } - - if (found) - update_life_info (blocks, UPDATE_LIFE_GLOBAL, - PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE - | PROP_KILL_DEAD_CODE); - sbitmap_free (blocks); - } + update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL, + PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE + | PROP_KILL_DEAD_CODE | PROP_LOG_LINKS); for (i = 0; i < n_basic_blocks; i++) BASIC_BLOCK (i)->aux = NULL; diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 5b99ab237e2..1b00a61285c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -271,6 +271,7 @@ create_basic_block_structure (index, head, end, bb_note) bb->head = head; bb->end = end; bb->index = index; + bb->flags = BB_NEW; BASIC_BLOCK (index) = bb; if (basic_block_for_insn) update_bb_for_insn (bb); @@ -592,6 +593,7 @@ merge_blocks_nomove (a, b) for (e = b->succ; e; e = e->succ_next) e->src = a; a->succ = b->succ; + a->flags |= b->flags; /* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */ b->pred = b->succ = NULL; diff --git a/gcc/cse.c b/gcc/cse.c index a607b0c46f3..557e8086d7f 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -5800,10 +5800,11 @@ cse_insn (insn, libcall_insn) and hope for the best. */ if (n_sets == 1) { - rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn); + rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn); JUMP_LABEL (new) = XEXP (src, 0); LABEL_NUSES (XEXP (src, 0))++; + delete_insn (insn); insn = new; /* Now emit a BARRIER after the unconditional jump. */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 90df7de7361..8dab7a0f3a8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2853,19 +2853,19 @@ Here are the possible letters for use in @var{letters}, and their meanings: Annotate the assembler output with miscellaneous debugging information. @item b @opindex db -Dump after computing branch probabilities, to @file{@var{file}.14.bp}. +Dump after computing branch probabilities, to @file{@var{file}.15.bp}. @item B @opindex dB -Dump after block reordering, to @file{@var{file}.29.bbro}. +Dump after block reordering, to @file{@var{file}.30.bbro}. @item c @opindex dc -Dump after instruction combination, to the file @file{@var{file}.16.combine}. +Dump after instruction combination, to the file @file{@var{file}.17.combine}. @item C @opindex dC -Dump after the first if conversion, to the file @file{@var{file}.17.ce}. +Dump after the first if conversion, to the file @file{@var{file}.18.ce}. @item d @opindex dd -Dump after delayed branch scheduling, to @file{@var{file}.31.dbr}. +Dump after delayed branch scheduling, to @file{@var{file}.32.dbr}. @item D @opindex dD Dump all macro definitions, at the end of preprocessing, in addition to @@ -2876,28 +2876,28 @@ Dump after SSA optimizations, to @file{@var{file}.04.ssa} and @file{@var{file}.07.ussa}. @item E @opindex dE -Dump after the second if conversion, to @file{@var{file}.26.ce2}. +Dump after the second if conversion, to @file{@var{file}.27.ce2}. @item f @opindex df -Dump after life analysis, to @file{@var{file}.15.life}. +Dump after life analysis, to @file{@var{file}.16.life}. @item F @opindex dF -Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.09.addressof}. +Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.10.addressof}. @item g @opindex dg -Dump after global register allocation, to @file{@var{file}.21.greg}. +Dump after global register allocation, to @file{@var{file}.22.greg}. @item h @opindex dh Dump after finalization of EH handling code, to @file{@var{file}.02.eh}. @item k @opindex dk -Dump after reg-to-stack conversion, to @file{@var{file}.28.stack}. +Dump after reg-to-stack conversion, to @file{@var{file}.29.stack}. @item o @opindex do -Dump after post-reload optimizations, to @file{@var{file}.22.postreload}. +Dump after post-reload optimizations, to @file{@var{file}.23.postreload}. @item G @opindex dG -Dump after GCSE, to @file{@var{file}.10.gcse}. +Dump after GCSE, to @file{@var{file}.11.gcse}. @item i @opindex di Dump after sibling call optimizations, to @file{@var{file}.01.sibling}. @@ -2906,49 +2906,52 @@ Dump after sibling call optimizations, to @file{@var{file}.01.sibling}. Dump after the first jump optimization, to @file{@var{file}.03.jump}. @item k @opindex dk -Dump after conversion from registers to stack, to @file{@var{file}.32.stack}. +Dump after conversion from registers to stack, to @file{@var{file}.33.stack}. @item l @opindex dl -Dump after local register allocation, to @file{@var{file}.20.lreg}. +Dump after local register allocation, to @file{@var{file}.21.lreg}. @item L @opindex dL -Dump after loop optimization, to @file{@var{file}.11.loop}. +Dump after loop optimization, to @file{@var{file}.12.loop}. @item M @opindex dM Dump after performing the machine dependent reorganisation pass, to -@file{@var{file}.30.mach}. +@file{@var{file}.31.mach}. @item n @opindex dn -Dump after register renumbering, to @file{@var{file}.25.rnreg}. +Dump after register renumbering, to @file{@var{file}.26.rnreg}. @item N @opindex dN -Dump after the register move pass, to @file{@var{file}.18.regmove}. +Dump after the register move pass, to @file{@var{file}.19.regmove}. @item r @opindex dr Dump after RTL generation, to @file{@var{file}.00.rtl}. @item R @opindex dR -Dump after the second scheduling pass, to @file{@var{file}.27.sched2}. +Dump after the second scheduling pass, to @file{@var{file}.28.sched2}. @item s @opindex ds Dump after CSE (including the jump optimization that sometimes follows -CSE), to @file{@var{file}.08.cse}. +CSE), to @file{@var{file}.09.cse}. @item S @opindex dS -Dump after the first scheduling pass, to @file{@var{file}.19.sched}. +Dump after the first scheduling pass, to @file{@var{file}.20.sched}. @item t @opindex dt Dump after the second CSE pass (including the jump optimization that -sometimes follows CSE), to @file{@var{file}.12.cse2}. +sometimes follows CSE), to @file{@var{file}.13.cse2}. +@item u +@opindex du +Dump after null pointer ellimination pass ti @file{@var{file}.08.null}. @item w @opindex dw -Dump after the second flow pass, to @file{@var{file}.23.flow2}. +Dump after the second flow pass, to @file{@var{file}.24.flow2}. @item X @opindex dX Dump after SSA dead code elimination, to @file{@var{file}.06.ssadce}. @item z @opindex dz -Dump after the peephole pass, to @file{@var{file}.24.peephole2}. +Dump after the peephole pass, to @file{@var{file}.25.peephole2}. @item a @opindex da Produce all the dumps listed above. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 492888f9037..e248af19021 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3276,6 +3276,8 @@ add_insn_after (insn, after) && (bb = BLOCK_FOR_INSN (after))) { set_block_for_insn (insn, bb); + if (INSN_P (insn)) + bb->flags |= BB_DIRTY; /* Should not happen as first in the BB is always either NOTE or LABEL. */ if (bb->end == after @@ -3343,6 +3345,8 @@ add_insn_before (insn, before) && (bb = BLOCK_FOR_INSN (before))) { set_block_for_insn (insn, bb); + if (INSN_P (insn)) + bb->flags |= BB_DIRTY; /* Should not happen as first in the BB is always either NOTE or LABEl. */ if (bb->head == insn @@ -3420,6 +3424,8 @@ remove_insn (insn) && (unsigned int)INSN_UID (insn) < basic_block_for_insn->num_elements && (bb = BLOCK_FOR_INSN (insn))) { + if (INSN_P (insn)) + bb->flags |= BB_DIRTY; if (bb->head == insn) { /* Never ever delete the basic block note without deleting whole basic @@ -3497,6 +3503,7 @@ reorder_insns (from, to, after) && (bb = BLOCK_FOR_INSN (after))) { rtx x; + bb->flags |= BB_DIRTY; if (basic_block_for_insn && (unsigned int)INSN_UID (from) < basic_block_for_insn->num_elements @@ -3504,6 +3511,7 @@ reorder_insns (from, to, after) { if (bb2->end == to) bb2->end = prev; + bb2->flags |= BB_DIRTY; } if (bb->end == after) @@ -4028,6 +4036,7 @@ emit_insns_after (first, after) && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements && (bb = BLOCK_FOR_INSN (after))) { + bb->flags |= BB_DIRTY; for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) set_block_for_insn (last, bb); set_block_for_insn (last, bb); diff --git a/gcc/flow.c b/gcc/flow.c index 6c3cd564d7d..54985d921f5 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -645,10 +645,6 @@ update_life_info (blocks, extent, prop_flags) && (extent == UPDATE_LIFE_LOCAL || blocks)) abort (); - /* Clear log links in case we are asked to (re)compute them. */ - if (prop_flags & PROP_LOG_LINKS) - clear_log_links (blocks); - /* For a global update, we go through the relaxation process again. */ if (extent != UPDATE_LIFE_LOCAL) { @@ -685,6 +681,10 @@ update_life_info (blocks, extent, prop_flags) count_or_remove_death_notes (blocks, 1); } + /* Clear log links in case we are asked to (re)compute them. */ + if (prop_flags & PROP_LOG_LINKS) + clear_log_links (blocks); + if (blocks) { EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, @@ -746,6 +746,31 @@ update_life_info (blocks, extent, prop_flags) ? TV_LIFE_UPDATE : TV_LIFE); } +/* Update life information in all blocks where BB_DIRTY is set. */ + +void +update_life_info_in_dirty_blocks (extent, prop_flags) + enum update_life_extent extent; + int prop_flags; +{ + sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks); + int block_num; + int n = 0; + + sbitmap_zero (update_life_blocks); + for (block_num = 0; block_num < n_basic_blocks; block_num++) + if (BASIC_BLOCK (block_num)->flags & BB_DIRTY) + { + SET_BIT (update_life_blocks, block_num); + n++; + } + + if (n) + update_life_info (update_life_blocks, extent, prop_flags); + + sbitmap_free (update_life_blocks); +} + /* Free the variables allocated by find_basic_blocks. KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed. */ diff --git a/gcc/gcse.c b/gcc/gcse.c index b7b08f2840a..52013c1ddd1 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -5330,8 +5330,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin, { rtx new_jump; - new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)), - last_insn); + new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)), + last_insn); JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn); LABEL_NUSES (JUMP_LABEL (new_jump))++; emit_barrier_after (new_jump); diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index a7860e3ea4e..038b8c5d5ff 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -113,10 +113,8 @@ static void noce_emit_move_insn PARAMS ((rtx, rtx)); as well as a flag indicating that the block should be rescaned for life analysis. */ -#define SET_ORIG_INDEX(BB,I) ((BB)->aux = (void *)((size_t)(I) << 1)) -#define ORIG_INDEX(BB) ((size_t)(BB)->aux >> 1) -#define SET_UPDATE_LIFE(BB) ((BB)->aux = (void *)((size_t)(BB)->aux | 1)) -#define UPDATE_LIFE(BB) ((size_t)(BB)->aux & 1) +#define SET_ORIG_INDEX(BB,I) ((BB)->aux = (void *)((size_t)(I))) +#define ORIG_INDEX(BB) ((size_t)(BB)->aux) /* Count the number of non-jump active insns in BB. */ @@ -1845,7 +1843,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb) /* First merge TEST block into THEN block. This is a no-brainer since the THEN block did not have a code label to begin with. */ - if (life_data_ok) + if (combo_bb->global_live_at_end) COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end); merge_blocks_nomove (combo_bb, then_bb); num_removed_blocks++; @@ -1886,7 +1884,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb) && join_bb != EXIT_BLOCK_PTR) { /* We can merge the JOIN. */ - if (life_data_ok) + if (combo_bb->global_live_at_end) COPY_REG_SET (combo_bb->global_live_at_end, join_bb->global_live_at_end); merge_blocks_nomove (combo_bb, join_bb); @@ -1907,9 +1905,6 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb) tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb); } - /* Make sure we update life info properly. */ - SET_UPDATE_LIFE (combo_bb); - num_updated_if_blocks++; } @@ -2324,7 +2319,6 @@ find_if_case_1 (test_bb, then_edge, else_edge) /* Conversion went ok, including moving the insns and fixing up the jump. Adjust the CFG to match. */ - SET_UPDATE_LIFE (test_bb); bitmap_operation (test_bb->global_live_at_end, else_bb->global_live_at_start, then_bb->global_live_at_end, BITMAP_IOR); @@ -2333,10 +2327,7 @@ find_if_case_1 (test_bb, then_edge, else_edge) /* Make rest of code believe that the newly created block is the THEN_BB block we are going to remove. */ if (new_bb) - { - new_bb->aux = then_bb->aux; - SET_UPDATE_LIFE (then_bb); - } + new_bb->aux = then_bb->aux; flow_delete_block (then_bb); /* We've possibly created jump to next insn, cleanup_cfg will solve that later. */ @@ -2403,7 +2394,6 @@ find_if_case_2 (test_bb, then_edge, else_edge) /* Conversion went ok, including moving the insns and fixing up the jump. Adjust the CFG to match. */ - SET_UPDATE_LIFE (test_bb); bitmap_operation (test_bb->global_live_at_end, then_bb->global_live_at_start, else_bb->global_live_at_end, BITMAP_IOR); @@ -2718,6 +2708,8 @@ if_convert (x_life_data_ok) post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks); calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS); } + if (life_data_ok) + clear_bb_flags (); /* Record initial block numbers. */ for (block_num = 0; block_num < n_basic_blocks; block_num++) @@ -2742,28 +2734,15 @@ if_convert (x_life_data_ok) /* Rebuild life info for basic blocks that require it. */ if (num_removed_blocks && life_data_ok) { - sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks); - sbitmap_zero (update_life_blocks); - /* If we allocated new pseudos, we must resize the array for sched1. */ if (max_regno < max_reg_num ()) { max_regno = max_reg_num (); allocate_reg_info (max_regno, FALSE, FALSE); } - - for (block_num = 0; block_num < n_basic_blocks; block_num++) - if (UPDATE_LIFE (BASIC_BLOCK (block_num))) - SET_BIT (update_life_blocks, block_num); - - count_or_remove_death_notes (update_life_blocks, 1); - /* ??? See about adding a mode that verifies that the initial - set of blocks don't let registers come live. */ - update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL, - PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE - | PROP_KILL_DEAD_CODE); - - sbitmap_free (update_life_blocks); + update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE + | PROP_KILL_DEAD_CODE); } clear_aux_for_blocks (); diff --git a/gcc/lcm.c b/gcc/lcm.c index 0a8a7cef9a1..f64c7ada7d4 100644 --- a/gcc/lcm.c +++ b/gcc/lcm.c @@ -1031,6 +1031,7 @@ optimize_mode_switching (file) int max_num_modes = 0; bool emited = false; + clear_bb_flags (); #ifdef NORMAL_MODE /* Increment n_basic_blocks before allocating bb_info. */ n_basic_blocks++; @@ -1398,16 +1399,11 @@ optimize_mode_switching (file) if (!need_commit && !emited) return 0; - /* Ideally we'd figure out what blocks were affected and start from - there, but this is enormously complicated by commit_edge_insertions, - which would screw up any indices we'd collected, and also need to - be involved in the update. Bail and recompute global life info for - everything. */ - - allocate_reg_life_data (); - update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, - (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE - | PROP_SCAN_DEAD_CODE | PROP_REG_INFO)); + max_regno = max_reg_num (); + allocate_reg_info (max_regno, FALSE, FALSE); + update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, + (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE + | PROP_SCAN_DEAD_CODE)); return 1; } diff --git a/gcc/recog.c b/gcc/recog.c index 6039c4d607a..69f75b79bf6 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -392,6 +392,17 @@ apply_change_group () if (i == num_changes) { + basic_block bb; + + for (i = 0; i < num_changes; i++) + if (changes[i].object + && INSN_P (changes[i].object) + && basic_block_for_insn + && ((unsigned int)INSN_UID (changes[i].object) + < basic_block_for_insn->num_elements) + && (bb = BLOCK_FOR_INSN (changes[i].object))) + bb->flags |= BB_DIRTY; + num_changes = 0; return 1; } diff --git a/gcc/toplev.c b/gcc/toplev.c index 9676dcde5a0..7cf0c96db9a 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -240,13 +240,14 @@ enum dump_file_index DFI_ssa_ccp, DFI_ssa_dce, DFI_ussa, + DFI_null, DFI_cse, DFI_addressof, DFI_gcse, DFI_loop, - DFI_cse2, DFI_cfg, DFI_bp, + DFI_cse2, DFI_life, DFI_combine, DFI_ce, @@ -272,7 +273,7 @@ enum dump_file_index Remaining -d letters: - " o q u " + " o q " " H JK OPQ TUV YZ" */ @@ -286,13 +287,14 @@ static struct dump_file_info dump_file[DFI_MAX] = { "ssaccp", 'W', 1, 0, 0 }, { "ssadce", 'X', 1, 0, 0 }, { "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */ + { "null", 'u', 0, 0, 0 }, { "cse", 's', 0, 0, 0 }, { "addressof", 'F', 0, 0, 0 }, { "gcse", 'G', 1, 0, 0 }, { "loop", 'L', 1, 0, 0 }, - { "cse2", 't', 1, 0, 0 }, { "cfg", 'f', 1, 0, 0 }, { "bp", 'b', 1, 0, 0 }, + { "cse2", 't', 1, 0, 0 }, { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */ { "combine", 'c', 1, 0, 0 }, { "ce", 'C', 1, 0, 0 }, @@ -2608,6 +2610,8 @@ rest_of_compilation (decl) reg_scan (insns, max_reg_num (), 0); rebuild_jump_labels (insns); find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP); /* CFG is no longer maintained up-to-date. */ @@ -2616,11 +2620,11 @@ rest_of_compilation (decl) purge_line_number_notes (insns); timevar_pop (TV_JUMP); + close_dump_file (DFI_jump, print_rtl, insns); /* Now is when we stop if -fsyntax-only and -Wreturn-type. */ if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl)) { - close_dump_file (DFI_jump, print_rtl, insns); goto exit_rest_of_compilation; } @@ -2697,23 +2701,22 @@ rest_of_compilation (decl) if (optimize > 0) { + open_dump_file (DFI_null, decl); find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP | (flag_thread_jumps ? CLEANUP_THREADING : 0)); - /* ??? Run if-conversion before delete_null_pointer_checks, - since the later does not preserve the CFG. This should - be changed -- no since converting if's that are going to - be deleted. */ - timevar_push (TV_IFCVT); - if_convert (0); - timevar_pop (TV_IFCVT); - - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); /* Try to identify useless null pointer tests and delete them. */ if (flag_delete_null_pointer_checks) delete_null_pointer_checks (insns); + + timevar_push (TV_IFCVT); + if_convert (0); + timevar_pop (TV_IFCVT); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); + close_dump_file (DFI_null, print_rtl_with_bb, insns); } /* Jump optimization, and the removal of NULL pointer checks, may @@ -2722,9 +2725,11 @@ rest_of_compilation (decl) maximum instruction UID, so if we can reduce the maximum UID we'll save big on memory. */ renumber_insns (rtl_dump_file); + if (optimize) + compute_bb_for_insn (get_max_uid ()); timevar_pop (TV_JUMP); - close_dump_file (DFI_jump, print_rtl, insns); + close_dump_file (DFI_jump, print_rtl_with_bb, insns); ggc_collect (); @@ -2736,36 +2741,32 @@ rest_of_compilation (decl) if (optimize > 0) { open_dump_file (DFI_cse, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + if (tem) + rebuild_jump_labels (insns); + purge_all_dead_edges (0); /* If we are not running more CSE passes, then we are no longer expecting CSE to be run. But always rerun it in a cheap mode. */ cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse; if (tem || optimize > 1) - { - timevar_push (TV_JUMP); - rebuild_jump_labels (insns); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - timevar_pop (TV_JUMP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - } + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); /* 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); + delete_trivially_dead_insns (insns, max_reg_num (), 1); /* Try to identify useless null pointer tests and delete them. */ if (flag_delete_null_pointer_checks || flag_thread_jumps) { timevar_push (TV_JUMP); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP | (flag_thread_jumps ? CLEANUP_THREADING : 0)); @@ -2773,21 +2774,23 @@ rest_of_compilation (decl) if (flag_delete_null_pointer_checks) delete_null_pointer_checks (insns); /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); timevar_pop (TV_JUMP); } /* The second pass of jump optimization is likely to have removed a bunch more instructions. */ renumber_insns (rtl_dump_file); + compute_bb_for_insn (get_max_uid ()); timevar_pop (TV_CSE); - close_dump_file (DFI_cse, print_rtl, insns); + close_dump_file (DFI_cse, print_rtl_with_bb, insns); } open_dump_file (DFI_addressof, decl); purge_addressof (insns); + if (optimize) + purge_all_dead_edges (0); reg_scan (insns, max_reg_num (), 1); close_dump_file (DFI_addressof, print_rtl, insns); @@ -2804,7 +2807,6 @@ rest_of_compilation (decl) timevar_push (TV_GCSE); open_dump_file (DFI_gcse, decl); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); tem = gcse_main (insns, rtl_dump_file); rebuild_jump_labels (insns); @@ -2813,8 +2815,6 @@ rest_of_compilation (decl) save_cfj = flag_cse_follow_jumps; flag_cse_skip_blocks = flag_cse_follow_jumps = 0; - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); /* If -fexpensive-optimizations, re-run CSE to clean up things done by gcse. */ if (flag_expensive_optimizations) @@ -2822,6 +2822,7 @@ rest_of_compilation (decl) timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + purge_all_dead_edges (0); timevar_pop (TV_CSE); cse_not_expected = !flag_rerun_cse_after_loop; } @@ -2833,11 +2834,8 @@ rest_of_compilation (decl) tem = tem2 = 0; timevar_push (TV_JUMP); rebuild_jump_labels (insns); - delete_trivially_dead_insns (insns, max_reg_num (), 0); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + delete_trivially_dead_insns (insns, max_reg_num (), 1); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); timevar_pop (TV_JUMP); if (flag_expensive_optimizations) @@ -2845,16 +2843,20 @@ rest_of_compilation (decl) timevar_push (TV_CSE); reg_scan (insns, max_reg_num (), 1); tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file); + purge_all_dead_edges (0); timevar_pop (TV_CSE); } } - close_dump_file (DFI_gcse, print_rtl, insns); + close_dump_file (DFI_gcse, print_rtl_with_bb, insns); timevar_pop (TV_GCSE); ggc_collect (); flag_cse_skip_blocks = save_csb; flag_cse_follow_jumps = save_cfj; +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif } /* Move constant computations out of loops. */ @@ -2863,6 +2865,7 @@ rest_of_compilation (decl) { timevar_push (TV_LOOP); open_dump_file (DFI_loop, decl); + /* CFG is no longer maintained up-to-date. */ free_bb_for_insn (); if (flag_rerun_loop_opt) @@ -2888,62 +2891,98 @@ rest_of_compilation (decl) (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0)); + /* Loop can create trivially dead instructions. */ + delete_trivially_dead_insns (insns, max_reg_num (), 0); close_dump_file (DFI_loop, print_rtl, insns); timevar_pop (TV_LOOP); ggc_collect (); } + /* Do control and data flow analysis; wrote some of the results to + the dump file. */ + + timevar_push (TV_FLOW); + open_dump_file (DFI_cfg, decl); + + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); + cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + + /* It may make more sense to mark constant functions after dead code is + eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs + may insert code making function non-constant, but we still must consider + it as constant, otherwise -fbranch-probabilities will not read data back. + + life_analyzis rarely eliminates modification of external memory. + */ + mark_constant_function (); + + close_dump_file (DFI_cfg, print_rtl_with_bb, insns); + + /* Do branch profiling and static profile estimation passes. */ + if (optimize > 0 || profile_arc_flag || flag_test_coverage + || flag_branch_probabilities) + { + struct loops loops; + + timevar_push (TV_BRANCH_PROB); + open_dump_file (DFI_bp, decl); + if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) + branch_prob (); + + /* Discover and record the loop depth at the head of each basic + block. The loop infrastructure does the real job for us. */ + flow_loops_find (&loops, LOOP_TREE); + + /* Estimate using heuristics if no profiling info is available. */ + if (flag_guess_branch_prob) + estimate_probability (&loops); + + if (rtl_dump_file) + flow_loops_dump (&loops, rtl_dump_file, NULL, 0); + + flow_loops_free (&loops); + close_dump_file (DFI_bp, print_rtl_with_bb, insns); + timevar_pop (TV_BRANCH_PROB); + } + if (optimize > 0) { timevar_push (TV_CSE2); open_dump_file (DFI_cse2, decl); + if (rtl_dump_file) + dump_flow_info (rtl_dump_file); if (flag_rerun_cse_after_loop) { - /* Running another jump optimization pass before the second - cse pass sometimes simplifies the RTL enough to allow - the second CSE pass to do a better job. Jump_optimize can change - max_reg_num so we must rerun reg_scan afterwards. - ??? Rework to not call reg_scan so often. */ timevar_push (TV_JUMP); - /* The previous call to loop_optimize makes some instructions - 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); timevar_push (TV_IFCVT); - - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE); if_convert (0); - timevar_pop(TV_IFCVT); timevar_pop (TV_JUMP); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); reg_scan (insns, max_reg_num (), 0); tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file); + purge_all_dead_edges (0); if (tem) { timevar_push (TV_JUMP); rebuild_jump_labels (insns); - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE); - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); timevar_pop (TV_JUMP); } } - close_dump_file (DFI_cse2, print_rtl, insns); + close_dump_file (DFI_cse2, print_rtl_with_bb, insns); timevar_pop (TV_CSE2); ggc_collect (); @@ -2951,60 +2990,17 @@ rest_of_compilation (decl) cse_not_expected = 1; + close_dump_file (DFI_life, print_rtl_with_bb, insns); regclass_init (); - /* Do control and data flow analysis; wrote some of the results to - the dump file. */ - - timevar_push (TV_FLOW); - open_dump_file (DFI_cfg, decl); - - find_basic_blocks (insns, max_reg_num (), rtl_dump_file); - cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); check_function_return_warnings (); - /* It may make more sense to mark constant functions after dead code is - eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs - may insert code making function non-constant, but we still must consider - it as constant, otherwise -fbranch-probabilities will not read data back. - - life_analyzis rarely eliminates modification of external memory. - */ - mark_constant_function (); - - close_dump_file (DFI_cfg, print_rtl_with_bb, insns); - - if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) - { - timevar_push (TV_BRANCH_PROB); - open_dump_file (DFI_bp, decl); - - branch_prob (); - - close_dump_file (DFI_bp, print_rtl_with_bb, insns); - timevar_pop (TV_BRANCH_PROB); - } - - open_dump_file (DFI_life, decl); - if (optimize) - { - struct loops loops; - - /* Discover and record the loop depth at the head of each basic - block. The loop infrastructure does the real job for us. */ - flow_loops_find (&loops, LOOP_TREE); - - /* Estimate using heuristics if no profiling info is available. */ - if (flag_guess_branch_prob) - estimate_probability (&loops); - - if (rtl_dump_file) - flow_loops_dump (&loops, rtl_dump_file, NULL, 0); - - flow_loops_free (&loops); - } +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif life_analysis (insns, rtl_dump_file, PROP_FINAL); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); timevar_pop (TV_FLOW); no_new_pseudos = 1; @@ -3018,12 +3014,14 @@ rest_of_compilation (decl) if (optimize) { + clear_bb_flags (); if (initialize_uninitialized_subregs ()) { /* Insns were inserted, so things might look a bit different. */ insns = get_insns (); - life_analysis (insns, rtl_dump_file, - (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES)); + update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_LOG_LINKS | PROP_REG_INFO + | PROP_DEATH_NOTES); } } @@ -3089,6 +3087,7 @@ rest_of_compilation (decl) regmove_optimize (insns, max_reg_num (), rtl_dump_file); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); close_dump_file (DFI_regmove, print_rtl_with_bb, insns); timevar_pop (TV_REGMOVE); @@ -3107,13 +3106,7 @@ rest_of_compilation (decl) timevar_push (TV_MODE_SWITCH); no_new_pseudos = 0; - if (optimize_mode_switching (NULL)) - { - /* We did work, and so had to regenerate global life information. - Take advantage of this and don't re-recompute register life - information below. */ - register_life_up_to_date = 1; - } + optimize_mode_switching (NULL); no_new_pseudos = 1; timevar_pop (TV_MODE_SWITCH); -- 2.11.0