http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45354
Alexander Monakov <amonakov at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED AssignedTo|unassigned at gcc dot |amonakov at gcc dot gnu.org |gnu.org | --- Comment #9 from Alexander Monakov <amonakov at gcc dot gnu.org> 2010-11-29 13:58:45 UTC --- Thanks. We go over-eager when cleaning up degenerate jumps and don't pay attention to EDGE_CROSSING. diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index 7956cd8..0adc836 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -156,6 +156,7 @@ static void move_bb_info (basic_block, basic_block); static void remove_empty_bb (basic_block, bool); static void sel_merge_blocks (basic_block, basic_block); static void sel_remove_loop_preheader (void); +static bool have_removable_jump_p (basic_block, basic_block); static bool insn_is_the_only_one_in_bb_p (insn_t); static void create_initial_data_sets (basic_block); @@ -3675,7 +3676,7 @@ tidy_control_flow (basic_block xbb, bool full_tidying) return changed; /* Check if there is a unnecessary jump after insn left. */ - if (jump_leads_only_to_bb_p (BB_END (xbb), xbb->next_bb) + if (have_removable_jump_p (xbb, xbb->next_bb) && INSN_SCHED_TIMES (BB_END (xbb)) == 0 && !IN_CURRENT_FENCE_P (BB_END (xbb))) { @@ -3716,7 +3717,7 @@ tidy_control_flow (basic_block xbb, bool full_tidying) /* And unconditional jump in previous basic block leads to next basic block of XBB and this jump can be safely removed. */ && in_current_region_p (xbb->prev_bb) - && jump_leads_only_to_bb_p (BB_END (xbb->prev_bb), xbb->next_bb) + && have_removable_jump_p (xbb->prev_bb, xbb->next_bb) && INSN_SCHED_TIMES (BB_END (xbb->prev_bb)) == 0 /* Also this jump is not at the scheduling boundary. */ && !IN_CURRENT_FENCE_P (BB_END (xbb->prev_bb))) @@ -6104,11 +6105,13 @@ sel_is_loop_preheader_p (basic_block bb) return false; } -/* Checks whether JUMP leads to basic block DEST_BB and no other blocks. */ -bool -jump_leads_only_to_bb_p (insn_t jump, basic_block dest_bb) +/* Check whether JUMP_BB ends with a jump insn that leads only to DEST_BB and + can be removed, making the corresponding edge fallthrough (assuming that + all basic blocks between JUMP_BB and DEST_BB are empty). */ +static bool +have_removable_jump_p (basic_block jump_bb, basic_block dest_bb) { - basic_block jump_bb = BLOCK_FOR_INSN (jump); + insn_t jump = BB_END (jump_bb); /* It is not jump, jump with side-effects or jump can lead to several basic blocks. */ @@ -6119,7 +6122,7 @@ jump_leads_only_to_bb_p (insn_t jump, basic_block dest_bb) /* Several outgoing edges, abnormal edge or destination of jump is not DEST_BB. */ if (EDGE_COUNT (jump_bb->succs) != 1 - || EDGE_SUCC (jump_bb, 0)->flags & EDGE_ABNORMAL + || EDGE_SUCC (jump_bb, 0)->flags & (EDGE_ABNORMAL | EDGE_CROSSING) || EDGE_SUCC (jump_bb, 0)->dest != dest_bb) return false; @@ -6199,7 +6202,7 @@ sel_remove_loop_preheader (void) basic block if it becomes empty. */ if (next_bb->prev_bb == prev_bb && prev_bb != ENTRY_BLOCK_PTR - && jump_leads_only_to_bb_p (BB_END (prev_bb), next_bb)) + && have_removable_jump_p (prev_bb, next_bb)) { redirect_edge_and_branch (EDGE_SUCC (prev_bb, 0), next_bb); if (BB_END (prev_bb) == bb_note (prev_bb)) diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h index 9ab0466..1f3dec4 100644 --- a/gcc/sel-sched-ir.h +++ b/gcc/sel-sched-ir.h @@ -1590,7 +1590,6 @@ extern bool sel_remove_insn (insn_t, bool, bool); extern bool bb_header_p (insn_t); extern void sel_init_invalid_data_sets (insn_t); extern bool insn_at_boundary_p (insn_t); -extern bool jump_leads_only_to_bb_p (insn_t, basic_block); /* Basic block and CFG functions. */