diff options
author | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-24 19:15:36 +0000 |
---|---|---|
committer | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-24 19:15:36 +0000 |
commit | 0b3f0f444150a9e3b64cc963ad1ef6bd44d7a70e (patch) | |
tree | f5db0208687505d3114934ff0a9f353f86b4947f /gcc | |
parent | 44b28efc77e651970b3e9fe5a0fae2f69de7b542 (diff) | |
download | gcc-0b3f0f444150a9e3b64cc963ad1ef6bd44d7a70e.tar.gz |
* jump.c (reset_insn_reg_label_operand_notes): New function,
split out from ...
(init_label_info): ... here. Reset LABEL_NUSES in cfglayout mode.
* cfgcleanup.c (delete_dead_jump_tables_between): New function,
split out from ...
(delete_dead_jumptables): ... here. Handle cfglayout mode.
(cleanup_cfg): Delete dead jump tables in cfglayout mode if an
expensive CFG cleanup is called for.
* cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths.
(cfg_layout_finalize): Delete dead jump tables before re-building
the insns chain.
* ira.c (ira): Rebuild jump labels *after* deleting unreachable
basic blocks, not before.
* loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup.
* modulo-sched.c (sms_schedule): Do not look for BARRIERs in the
insns chain of a scheduling extended basic block, they cannot appear
there in cfglayout mode.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205337 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 89 | ||||
-rw-r--r-- | gcc/cfgrtl.c | 31 | ||||
-rw-r--r-- | gcc/ira.c | 2 | ||||
-rw-r--r-- | gcc/jump.c | 80 | ||||
-rw-r--r-- | gcc/loop-init.c | 2 | ||||
-rw-r--r-- | gcc/modulo-sched.c | 5 |
7 files changed, 159 insertions, 71 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 903725782d0..29ac53cb0fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2013-11-24 Steven Bosscher <steven@gcc.gnu.org> + + * jump.c (reset_insn_reg_label_operand_notes): New function, + split out from ... + (init_label_info): ... here. Reset LABEL_NUSES in cfglayout mode. + * cfgcleanup.c (delete_dead_jump_tables_between): New function, + split out from ... + (delete_dead_jumptables): ... here. Handle cfglayout mode. + (cleanup_cfg): Delete dead jump tables in cfglayout mode if an + expensive CFG cleanup is called for. + * cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths. + (cfg_layout_finalize): Delete dead jump tables before re-building + the insns chain. + * ira.c (ira): Rebuild jump labels *after* deleting unreachable + basic blocks, not before. + * loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup. + + * modulo-sched.c (sms_schedule): Do not look for BARRIERs in the + insns chain of a scheduling extended basic block, they cannot appear + there in cfglayout mode. + 2013-11-24 Tobias Burnus <burnus@net-b.de> * doc/invoke.texi (-fsanitize=leak): Add link to the wiki page. diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 234e5b64fe7..e909b03253d 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -2944,40 +2944,65 @@ delete_unreachable_blocks (void) return changed; } + +/* Look for, and delete, any dead jumptables between START and END. */ + +static void +delete_dead_jump_tables_between (rtx start, rtx end) +{ + rtx insn, next; + + for (insn = start; insn != end; insn = next) + { + next = NEXT_INSN (insn); + if (next != NULL_RTX + && LABEL_P (insn) + && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn) + && JUMP_TABLE_DATA_P (next)) + { + rtx label = insn, jump = next; + + if (dump_file) + fprintf (dump_file, "Dead jumptable %i removed\n", + INSN_UID (insn)); + + next = NEXT_INSN (next); + delete_insn (jump); + delete_insn (label); + } + } +} + + /* Delete any jump tables never referenced. We can't delete them at the - time of removing tablejump insn as they are referenced by the preceding - insns computing the destination, so we delay deleting and garbagecollect - them once life information is computed. */ + time of removing tablejump insn as the label preceding the jump table + data may be referenced by the preceding insns computing the destination. + So we delay deleting and garbage-collect them from time to time, after + a CFG cleanup. */ + void delete_dead_jumptables (void) { basic_block bb; - /* A dead jump table does not belong to any basic block. Scan insns - between two adjacent basic blocks. */ + /* Label reference count must up-to-date to detect dead jump tables. */ + rebuild_jump_labels (get_insns ()); + FOR_EACH_BB (bb) { - rtx insn, next; - - for (insn = NEXT_INSN (BB_END (bb)); - insn && !NOTE_INSN_BASIC_BLOCK_P (insn); - insn = next) + if (current_ir_type () == IR_RTL_CFGLAYOUT) { - next = NEXT_INSN (insn); - if (LABEL_P (insn) - && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn) - && JUMP_TABLE_DATA_P (next)) - { - rtx label = insn, jump = next; - - if (dump_file) - fprintf (dump_file, "Dead jumptable %i removed\n", - INSN_UID (insn)); - - next = NEXT_INSN (next); - delete_insn (jump); - delete_insn (label); - } + /* Jump tables only appear in the header or footer of BB. */ + delete_dead_jump_tables_between (BB_HEADER (bb), NULL_RTX); + delete_dead_jump_tables_between (BB_FOOTER (bb), NULL_RTX); + } + else + { + /* Jump tables are in the insns chain between basic blocks. */ + rtx start = NEXT_INSN (BB_END (bb)); + rtx end = (bb->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) + ? NULL_RTX : BB_HEAD (bb->next_bb); + delete_dead_jump_tables_between (start, end); } } } @@ -3049,13 +3074,13 @@ cleanup_cfg (int mode) if (mode & CLEANUP_CROSSJUMP) remove_fake_exit_edges (); - /* Don't call delete_dead_jumptables in cfglayout mode, because - that function assumes that jump tables are in the insns stream. - But we also don't _have_ to delete dead jumptables in cfglayout - mode because we shouldn't even be looking at things that are - not in a basic block. Dead jumptables are cleaned up when - going out of cfglayout mode. */ - if (!(mode & CLEANUP_CFGLAYOUT)) + /* Don't always call delete_dead_jumptables in cfglayout mode, because + jump tables can only appear in the headers and footers of basic blocks + and we usually are not interested in anything hiding there. + But if an expensive cleanup is called for, garbage-collect the dead + jump tables to get label reference counts right. This sometimes + allows some labels to be removed and more basic blocks to be merged. */ + if (!(mode & CLEANUP_CFGLAYOUT) || (mode & CLEANUP_EXPENSIVE)) delete_dead_jumptables (); /* ??? We probably do this way too often. */ diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 63f44afbbae..4ce7273834c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -3696,10 +3696,10 @@ fixup_reorder_chain (void) #endif /* Now add jumps and labels as needed to match the blocks new - outgoing edges. */ + outgoing edges. Fixup missing or redundant BARRIERs. */ - for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block) - bb->aux) + for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; + bb = (basic_block) bb->aux) { edge e_fall, e_taken, e; rtx bb_end_insn; @@ -3853,13 +3853,26 @@ fixup_reorder_chain (void) relink_block_chain (/*stay_in_cfglayout_mode=*/false); - /* Annoying special case - jump around dead jumptables left in the code. */ + /* Annoying special case - stray barriers left in the code. This happens + if a tablejump is transformed to a simpe or confitional jump, or if a + basic block ending in a tablejump is removed but the jump table itself + is not. */ FOR_EACH_BB (bb) { edge e = find_fallthru_edge (bb->succs); - if (e && !can_fallthru (e->src, e->dest)) - force_nonfallthru (e); + if (e && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)) + { + rtx insn, next; + for (insn = NEXT_INSN (BB_END (e->src)); + insn != BB_HEAD (e->dest); + insn = next) + { + next = NEXT_INSN (insn); + if (BARRIER_P (insn)) + remove_insn (insn); + } + } } /* Ensure goto_locus from edges has some instructions with that locus @@ -4273,7 +4286,7 @@ break_superblocks (void) } /* Finalize the changes: reorder insn list according to the sequence specified - by aux pointers, enter compensation code, rebuild scope forest. */ + by aux pointers, enter compensation code. */ void cfg_layout_finalize (void) @@ -4281,6 +4294,7 @@ cfg_layout_finalize (void) #ifdef ENABLE_CHECKING verify_flow_info (); #endif + delete_dead_jumptables (); force_one_exit_fallthru (); rtl_register_cfg_hooks (); if (reload_completed @@ -4291,9 +4305,6 @@ cfg_layout_finalize (void) fixup_fallthru_exit_predecessor (); fixup_reorder_chain (); - rebuild_jump_labels (get_insns ()); - delete_dead_jumptables (); - #ifdef ENABLE_CHECKING verify_insn_chain (); verify_flow_info (); diff --git a/gcc/ira.c b/gcc/ira.c index 2902ebe0a8b..43f98d4d69a 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -5273,9 +5273,9 @@ ira (FILE *f) if (optimize && rebuild_p) { timevar_push (TV_JUMP); - rebuild_jump_labels (get_insns ()); if (purge_all_dead_edges ()) delete_unreachable_blocks (); + rebuild_jump_labels (get_insns ()); timevar_pop (TV_JUMP); } diff --git a/gcc/jump.c b/gcc/jump.c index a27aaa94b8d..87f9619d751 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -177,6 +177,34 @@ make_pass_cleanup_barriers (gcc::context *ctxt) } +/* Remove all REG_LABEL_OPERAND notes from INSN. + + REG_LABEL_TARGET notes (including the JUMP_LABEL field) are sticky and + not reset here; that way we won't lose association with a label when + e.g. the source for a target register disappears out of reach for targets + that may use jump-target registers. Jump transformations are supposed to + transform any REG_LABEL_TARGET notes. The target label reference in a + branch may disappear from the branch (and from the instruction before it) + for other reasons, like register allocation. */ + +static void +reset_insn_reg_label_operand_notes (rtx insn) +{ + if (INSN_P (insn)) + { + rtx note, next; + + for (note = REG_NOTES (insn); note; note = next) + { + next = XEXP (note, 1); + if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND + && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn))) + remove_note (insn, note); + } + } +} + + /* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET for remaining targets for JUMP_P. Delete any REG_LABEL_OPERAND notes whose labels don't occur in the insn any more. */ @@ -186,32 +214,38 @@ init_label_info (rtx f) { rtx insn; - for (insn = f; insn; insn = NEXT_INSN (insn)) + if (current_ir_type () == IR_RTL_CFGLAYOUT) { - if (LABEL_P (insn)) - LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); - - /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are - sticky and not reset here; that way we won't lose association - with a label when e.g. the source for a target register - disappears out of reach for targets that may use jump-target - registers. Jump transformations are supposed to transform - any REG_LABEL_TARGET notes. The target label reference in a - branch may disappear from the branch (and from the - instruction before it) for other reasons, like register - allocation. */ - - if (INSN_P (insn)) + basic_block bb; + + FOR_EACH_BB (bb) { - rtx note, next; + /* Labels only appear between BB_HEAD and the basic block note, + and in the basic block header and footer. */ + for (insn = BB_HEAD (bb); + insn && LABEL_P (insn); + insn = NEXT_INSN (insn)) + LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); + for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn)) + if (LABEL_P (insn)) + LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); + for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn)) + if (LABEL_P (insn)) + LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); - for (note = REG_NOTES (insn); note; note = next) - { - next = XEXP (note, 1); - if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND - && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn))) - remove_note (insn, note); - } + FOR_BB_INSNS (bb, insn) + if (INSN_P (insn)) + reset_insn_reg_label_operand_notes (insn); + } + } + else + { + for (insn = f; insn; insn = NEXT_INSN (insn)) + { + if (LABEL_P (insn)) + LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); + if (INSN_P (insn)) + reset_insn_reg_label_operand_notes (insn); } } } diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 664b1ace427..0d8e4383744 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -415,7 +415,7 @@ rtl_loop_done (void) loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); - cleanup_cfg (0); + cleanup_cfg (CLEANUP_EXPENSIVE); if (dump_file) { dump_reg_info (dump_file); diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index f3130449909..444ffda34e9 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -1471,7 +1471,7 @@ sms_schedule (void) continue; } - /* Don't handle BBs with calls or barriers + /* Don't handle BBs with calls or !single_set with the exception of instructions that include count_reg---these instructions are part of the control part that do-loop recognizes. @@ -1481,7 +1481,6 @@ sms_schedule (void) rtx set; if (CALL_P (insn) - || BARRIER_P (insn) || (NONDEBUG_INSN_P (insn) && !JUMP_P (insn) && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE && !reg_mentioned_p (count_reg, insn)) @@ -1496,8 +1495,6 @@ sms_schedule (void) { if (CALL_P (insn)) fprintf (dump_file, "SMS loop-with-call\n"); - else if (BARRIER_P (insn)) - fprintf (dump_file, "SMS loop-with-barrier\n"); else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn) && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE)) fprintf (dump_file, "SMS loop-with-not-single-set\n"); |