X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcfgrtl.c;h=994fb16fc47fba48577bd7bfc58e584b9d2b5e77;hp=5d736a5990bd53f30566fa4b22595c2792d091c4;hb=f69b7efb46e48bce7beb22bf8f1e26f487998aac;hpb=1f1872fdb0abb413ab6da9fd4f6adce363673c02 diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 5d736a5990b..994fb16fc47 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1,6 +1,6 @@ /* Control flow graph manipulation code for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. @@ -62,8 +62,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "df.h" -static int can_delete_note_p (rtx); -static int can_delete_label_p (rtx); +static int can_delete_note_p (const_rtx); +static int can_delete_label_p (const_rtx); static void commit_one_edge_insertion (edge); static basic_block rtl_split_edge (edge); static bool rtl_move_block_after (basic_block, basic_block); @@ -84,7 +84,7 @@ static void rtl_make_forwarder_block (edge); so that we may simply delete it. */ static int -can_delete_note_p (rtx note) +can_delete_note_p (const_rtx note) { return (NOTE_KIND (note) == NOTE_INSN_DELETED || NOTE_KIND (note) == NOTE_INSN_BASIC_BLOCK); @@ -93,7 +93,7 @@ can_delete_note_p (rtx note) /* True if a given label can be deleted. */ static int -can_delete_label_p (rtx label) +can_delete_label_p (const_rtx label) { return (!LABEL_PRESERVE_P (label) /* User declared labels must be preserved. */ @@ -138,15 +138,15 @@ delete_insn (rtx insn) /* If deleting a jump, decrement the use count of the label. Deleting the label itself should happen in the normal course of block merging. */ - if (JUMP_P (insn) - && JUMP_LABEL (insn) - && LABEL_P (JUMP_LABEL (insn))) - LABEL_NUSES (JUMP_LABEL (insn))--; - - /* Also if deleting an insn that references a label. */ - else + if (JUMP_P (insn)) { - while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX + if (JUMP_LABEL (insn) + && LABEL_P (JUMP_LABEL (insn))) + LABEL_NUSES (JUMP_LABEL (insn))--; + + /* If there are more targets, remove them too. */ + while ((note + = find_reg_note (insn, REG_LABEL_TARGET, NULL_RTX)) != NULL_RTX && LABEL_P (XEXP (note, 0))) { LABEL_NUSES (XEXP (note, 0))--; @@ -154,6 +154,14 @@ delete_insn (rtx insn) } } + /* Also if deleting any insn that references a label as an operand. */ + while ((note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX)) != NULL_RTX + && LABEL_P (XEXP (note, 0))) + { + LABEL_NUSES (XEXP (note, 0))--; + remove_note (insn, note); + } + if (JUMP_P (insn) && (GET_CODE (PATTERN (insn)) == ADDR_VEC || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)) @@ -179,6 +187,7 @@ delete_insn (rtx insn) } /* Like delete_insn but also purge dead edges from BB. */ + rtx delete_insn_and_edges (rtx insn) { @@ -223,6 +232,22 @@ delete_insn_chain (rtx start, rtx finish, bool clear_bb) start = next; } } + +/* Like delete_insn_chain but also purge dead edges from BB. */ + +void +delete_insn_chain_and_edges (rtx first, rtx last) +{ + bool purge = false; + + if (INSN_P (last) + && BLOCK_FOR_INSN (last) + && BB_END (BLOCK_FOR_INSN (last)) == last) + purge = true; + delete_insn_chain (first, last, false); + if (purge) + purge_dead_edges (BLOCK_FOR_INSN (last)); +} /* Create a new basic block consisting of the instructions between HEAD and END inclusive. This function is designed to allow fast BB construction - reuses @@ -402,8 +427,10 @@ free_bb_for_insn (void) return 0; } -struct tree_opt_pass pass_free_cfg = +struct rtl_opt_pass pass_free_cfg = { + { + RTL_PASS, NULL, /* name */ NULL, /* gate */ free_bb_for_insn, /* execute */ @@ -416,7 +443,7 @@ struct tree_opt_pass pass_free_cfg = PROP_cfg, /* properties_destroyed */ 0, /* todo_flags_start */ 0, /* todo_flags_finish */ - 0 /* letter */ + } }; /* Return RTX to emit after when we want to emit code on the entry of function. */ @@ -440,24 +467,31 @@ emit_insn_at_entry (rtx insn) commit_edge_insertions (); } -/* Update insns block within BB. */ +/* Update BLOCK_FOR_INSN of insns between BEGIN and END + (or BARRIER if found) and notify df of the bb change. + The insn chain range is inclusive + (i.e. both BEGIN and END will be updated. */ -void -update_bb_for_insn (basic_block bb) +static void +update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb) { rtx insn; - for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn)) - { - if (!BARRIER_P (insn)) - { - set_block_for_insn (insn, bb); - df_insn_change_bb (insn); - } - if (insn == BB_END (bb)) - break; - } + end = NEXT_INSN (end); + for (insn = begin; insn != end; insn = NEXT_INSN (insn)) + if (!BARRIER_P (insn)) + df_insn_change_bb (insn, bb); +} + +/* Update BLOCK_FOR_INSN of insns in BB to BB, + and notify df of the change. */ + +void +update_bb_for_insn (basic_block bb) +{ + update_bb_for_insn_chain (BB_HEAD (bb), BB_END (bb), bb); } + /* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK note associated with the BLOCK. */ @@ -604,16 +638,7 @@ rtl_merge_blocks (basic_block a, basic_block b) /* Reassociate the insns of B with A. */ if (!b_empty) { - rtx x; - - for (x = a_end; x != b_end; x = NEXT_INSN (x)) - { - set_block_for_insn (x, a); - df_insn_change_bb (x); - } - - set_block_for_insn (b_end, a); - df_insn_change_bb (b_end); + update_bb_for_insn_chain (a_end, b_end, a); a_end = b_end; } @@ -624,8 +649,9 @@ rtl_merge_blocks (basic_block a, basic_block b) /* Return true when block A and B can be merged. */ + static bool -rtl_can_merge_blocks (basic_block a,basic_block b) +rtl_can_merge_blocks (basic_block a, basic_block b) { /* If we are partitioning hot/cold basic blocks, we don't want to mess up unconditional or indirect jumps that cross between hot @@ -817,14 +843,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout) which originally were or were created before jump table are inside the basic block. */ rtx new_insn = BB_END (src); - rtx tmp; - for (tmp = NEXT_INSN (BB_END (src)); tmp != barrier; - tmp = NEXT_INSN (tmp)) - { - set_block_for_insn (tmp, src); - df_insn_change_bb (tmp); - } + update_bb_for_insn_chain (NEXT_INSN (BB_END (src)), + PREV_INSN (barrier), src); NEXT_INSN (PREV_INSN (new_insn)) = NEXT_INSN (new_insn); PREV_INSN (NEXT_INSN (new_insn)) = PREV_INSN (new_insn); @@ -1630,10 +1651,10 @@ print_rtl_with_bb (FILE *outf, const_rtx rtx_first) free (in_bb_p); } - if (current_function_epilogue_delay_list != 0) + if (crtl->epilogue_delay_list != 0) { fprintf (outf, "\n;; Insns in epilogue delay list:\n\n"); - for (tmp_rtx = current_function_epilogue_delay_list; tmp_rtx != 0; + for (tmp_rtx = crtl->epilogue_delay_list; tmp_rtx != 0; tmp_rtx = XEXP (tmp_rtx, 1)) print_rtl_single (outf, XEXP (tmp_rtx, 0)); } @@ -2529,6 +2550,7 @@ cfg_layout_delete_block (basic_block bb) } /* Return true when blocks A and B can be safely merged. */ + static bool cfg_layout_can_merge_blocks_p (basic_block a, basic_block b) { @@ -2610,6 +2632,13 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) first = NEXT_INSN (first); gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first)); BB_HEAD (b) = NULL; + + /* emit_insn_after_noloc doesn't call df_insn_change_bb. + We need to explicitly call. */ + update_bb_for_insn_chain (NEXT_INSN (first), + BB_END (b), + a); + delete_insn (first); } /* Otherwise just re-associate the instructions. */ @@ -2617,13 +2646,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b) { rtx insn; - for (insn = BB_HEAD (b); - insn != NEXT_INSN (BB_END (b)); - insn = NEXT_INSN (insn)) - { - set_block_for_insn (insn, a); - df_insn_change_bb (insn); - } + update_bb_for_insn_chain (BB_HEAD (b), BB_END (b), a); insn = BB_HEAD (b); /* Skip possible DELETED_LABEL insn. */ @@ -2669,6 +2692,10 @@ cfg_layout_split_edge (edge e) ? NEXT_INSN (BB_END (e->src)) : get_insns (), NULL_RTX, e->src); + if (e->dest == EXIT_BLOCK_PTR) + BB_COPY_PARTITION (new_bb, e->src); + else + BB_COPY_PARTITION (new_bb, e->dest); make_edge (new_bb, e->dest, EDGE_FALLTHRU); redirect_edge_and_branch_force (e, new_bb); @@ -2692,7 +2719,8 @@ rtl_block_ends_with_call_p (basic_block bb) while (!CALL_P (insn) && insn != BB_HEAD (bb) - && keep_with_call_p (insn)) + && (keep_with_call_p (insn) + || NOTE_P (insn))) insn = PREV_INSN (insn); return (CALL_P (insn)); } @@ -2700,7 +2728,7 @@ rtl_block_ends_with_call_p (basic_block bb) /* Return 1 if BB ends with a conditional branch, 0 otherwise. */ static bool -rtl_block_ends_with_condjump_p (basic_block bb) +rtl_block_ends_with_condjump_p (const_basic_block bb) { return any_condjump_p (BB_END (bb)); } @@ -2709,7 +2737,7 @@ rtl_block_ends_with_condjump_p (basic_block bb) Helper function for rtl_flow_call_edges_add. */ static bool -need_fake_edge_p (rtx insn) +need_fake_edge_p (const_rtx insn) { if (!INSN_P (insn)) return false; @@ -2717,7 +2745,7 @@ need_fake_edge_p (rtx insn) if ((CALL_P (insn) && !SIBLING_CALL_P (insn) && !find_reg_note (insn, REG_NORETURN, NULL) - && !CONST_OR_PURE_CALL_P (insn))) + && !(RTL_CONST_OR_PURE_CALL_P (insn)))) return true; return ((GET_CODE (PATTERN (insn)) == ASM_OPERANDS @@ -3012,11 +3040,11 @@ insert_insn_end_bb_new (rtx pat, basic_block bb) it to the destination of the other edge from E->src. */ static bool -rtl_can_remove_branch_p (edge e) +rtl_can_remove_branch_p (const_edge e) { - basic_block src = e->src; - basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest; - rtx insn = BB_END (src), set; + const_basic_block src = e->src; + const_basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest; + const_rtx insn = BB_END (src), set; /* The conditions are taken from try_redirect_by_replacing_jump. */ if (target == EXIT_BLOCK_PTR) @@ -3082,7 +3110,7 @@ struct cfg_hooks rtl_cfg_hooks = { should only be used through the cfghooks interface, and we do not want to move them here since it would require also moving quite a lot of related code. They are in cfglayout.c. */ -extern bool cfg_layout_can_duplicate_bb_p (basic_block); +extern bool cfg_layout_can_duplicate_bb_p (const_basic_block); extern basic_block cfg_layout_duplicate_bb (basic_block); struct cfg_hooks cfg_layout_rtl_cfg_hooks = {