diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-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, 76 insertions, 138 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 29ac53cb0fd..1fd4f3f342c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2013-11-24 Steven Bosscher <steven@gcc.gnu.org> + PR bootstrap/59279 + Revert previous commit. + +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. diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index e909b03253d..234e5b64fe7 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -2944,65 +2944,40 @@ 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 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. */ - + 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. */ void delete_dead_jumptables (void) { basic_block bb; - /* Label reference count must up-to-date to detect dead jump tables. */ - rebuild_jump_labels (get_insns ()); - + /* A dead jump table does not belong to any basic block. Scan insns + between two adjacent basic blocks. */ FOR_EACH_BB (bb) { - if (current_ir_type () == IR_RTL_CFGLAYOUT) - { - /* 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 + rtx insn, next; + + for (insn = NEXT_INSN (BB_END (bb)); + insn && !NOTE_INSN_BASIC_BLOCK_P (insn); + insn = next) { - /* 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); + 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); + } } } } @@ -3074,13 +3049,13 @@ cleanup_cfg (int mode) if (mode & CLEANUP_CROSSJUMP) remove_fake_exit_edges (); - /* 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)) + /* 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)) delete_dead_jumptables (); /* ??? We probably do this way too often. */ diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 4ce7273834c..63f44afbbae 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. Fixup missing or redundant BARRIERs. */ + outgoing edges. */ - 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,26 +3853,13 @@ fixup_reorder_chain (void) relink_block_chain (/*stay_in_cfglayout_mode=*/false); - /* 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. */ + /* Annoying special case - jump around dead jumptables left in the code. */ FOR_EACH_BB (bb) { edge e = find_fallthru_edge (bb->succs); - 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); - } - } + if (e && !can_fallthru (e->src, e->dest)) + force_nonfallthru (e); } /* Ensure goto_locus from edges has some instructions with that locus @@ -4286,7 +4273,7 @@ break_superblocks (void) } /* Finalize the changes: reorder insn list according to the sequence specified - by aux pointers, enter compensation code. */ + by aux pointers, enter compensation code, rebuild scope forest. */ void cfg_layout_finalize (void) @@ -4294,7 +4281,6 @@ 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 @@ -4305,6 +4291,9 @@ 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 43f98d4d69a..2902ebe0a8b 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 87f9619d751..a27aaa94b8d 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -177,34 +177,6 @@ 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. */ @@ -214,38 +186,32 @@ init_label_info (rtx f) { rtx insn; - if (current_ir_type () == IR_RTL_CFGLAYOUT) + for (insn = f; insn; insn = NEXT_INSN (insn)) { - basic_block bb; - - FOR_EACH_BB (bb) + 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)) { - /* 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); + rtx note, next; - 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); + 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); + } } } } diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 0d8e4383744..664b1ace427 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 (CLEANUP_EXPENSIVE); + cleanup_cfg (0); if (dump_file) { dump_reg_info (dump_file); diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 444ffda34e9..f3130449909 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 + /* Don't handle BBs with calls or barriers 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,6 +1481,7 @@ 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)) @@ -1495,6 +1496,8 @@ 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"); |