X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcfglayout.c;h=5e120570b9a030fcd073e74582df4ed6a8b04256;hp=0885af79b3f6134212314d0c2706c6efc0962b2f;hb=9b4c8635741ce4c64bf9b849298d4ac9a7500a84;hpb=20099e352f87c3265c44cd3341fd3aec25cb0fb4 diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 0885af79b3f..5e120570b9a 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -1,5 +1,5 @@ /* Basic block reordering routines for the GNU compiler. - Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -112,9 +112,7 @@ skip_insns_after_block (basic_block bb) case CODE_LABEL: if (NEXT_INSN (insn) - && JUMP_P (NEXT_INSN (insn)) - && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC - || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC)) + && JUMP_TABLE_DATA_P (NEXT_INSN (insn))) { insn = NEXT_INSN (insn); last_insn = insn; @@ -240,7 +238,7 @@ int epilogue_locator; /* Hold current location information and last location information, so the datastructures are built lazily only when some instructions in given place are needed. */ -location_t curr_location, last_location; +static location_t curr_location, last_location; static tree curr_block, last_block; static int curr_rtl_loc = -1; @@ -271,6 +269,19 @@ insn_locators_finalize (void) curr_rtl_loc = -1; } +/* Allocate insn locator datastructure. */ +void +insn_locators_free (void) +{ + prologue_locator = epilogue_locator = 0; + + VEC_free (int, heap, block_locators_locs); + VEC_free (tree,gc, block_locators_blocks); + VEC_free (int, heap, locations_locators_locs); + VEC_free (location_t, heap, locations_locators_vals); +} + + /* Set current location. */ void set_curr_insn_source_location (location_t location) @@ -279,12 +290,17 @@ set_curr_insn_source_location (location_t location) time locators are not initialized. */ if (curr_rtl_loc == -1) return; - if (location == last_location) - return; curr_location = location; } -/* Set current scope block. */ +/* Get current location. */ +location_t +get_curr_insn_source_location (void) +{ + return curr_location; +} + +/* Set current scope block. */ void set_curr_insn_block (tree b) { @@ -296,6 +312,13 @@ set_curr_insn_block (tree b) curr_block = b; } +/* Get current scope block. */ +tree +get_curr_insn_block (void) +{ + return curr_block; +} + /* Return current insn locator. */ int curr_insn_locator (void) @@ -350,9 +373,9 @@ struct rtl_opt_pass pass_into_cfg_layout_mode = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_NONE, /* tv_id */ 0, /* properties_required */ - 0, /* properties_provided */ + PROP_cfglayout, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_dump_func, /* todo_flags_finish */ @@ -369,16 +392,16 @@ struct rtl_opt_pass pass_outof_cfg_layout_mode = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_NONE, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ - 0, /* properties_destroyed */ + PROP_cfglayout, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_dump_func, /* todo_flags_finish */ } }; -/* Return sope resulting from combination of S1 and S2. */ +/* Return scope resulting from combination of S1 and S2. */ static tree choose_inner_scope (tree s1, tree s2) { @@ -435,13 +458,12 @@ change_scope (rtx orig_insn, tree s1, tree s2) } } -/* Return lexical scope block insn belong to. */ +/* Return lexical scope block locator belongs to. */ static tree -insn_scope (const_rtx insn) +locator_scope (int loc) { int max = VEC_length (int, block_locators_locs); int min = 0; - int loc = INSN_LOCATOR (insn); /* When block_locators_locs was initialized, the pro- and epilogue insns didn't exist yet and can therefore not be found this way. @@ -475,8 +497,15 @@ insn_scope (const_rtx insn) return VEC_index (tree, block_locators_blocks, min); } +/* Return lexical scope block insn belongs to. */ +static tree +insn_scope (const_rtx insn) +{ + return locator_scope (INSN_LOCATOR (insn)); +} + /* Return line number of the statement specified by the locator. */ -static location_t +location_t locator_location (int loc) { int max = VEC_length (int, locations_locators_locs); @@ -538,6 +567,17 @@ insn_file (const_rtx insn) return locator_file (INSN_LOCATOR (insn)); } +/* Return true if LOC1 and LOC2 locators have the same location and scope. */ +bool +locator_eq (int loc1, int loc2) +{ + if (loc1 == loc2) + return true; + if (locator_location (loc1) != locator_location (loc2)) + return false; + return locator_scope (loc1) == locator_scope (loc2); +} + /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based on the scope tree and the newly reordered instructions. */ @@ -555,9 +595,7 @@ reemit_insn_block_notes (void) tree this_block; /* Avoid putting scope notes between jump table and its label. */ - if (JUMP_P (insn) - && (GET_CODE (PATTERN (insn)) == ADDR_VEC - || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)) + if (JUMP_TABLE_DATA_P (insn)) continue; this_block = insn_scope (insn); @@ -656,7 +694,7 @@ relink_block_chain (bool stay_in_cfglayout_mode) free_original_copy_tables (); if (stay_in_cfglayout_mode) initialize_original_copy_tables (); - + /* Finally, put basic_block_info in the new order. */ compact_blocks (); } @@ -749,6 +787,18 @@ fixup_reorder_chain (void) { if (any_condjump_p (bb_end_insn)) { + /* This might happen if the conditional jump has side + effects and could therefore not be optimized away. + Make the basic block to end with a barrier in order + to prevent rtl_verify_flow_info from complaining. */ + if (!e_fall) + { + gcc_assert (!onlyjump_p (bb_end_insn) + || returnjump_p (bb_end_insn)); + bb->il.rtl->footer = emit_barrier_after (bb_end_insn); + continue; + } + /* If the old fallthru is still next, nothing to do. */ if (bb->aux == e_fall->dest || e_fall->dest == EXIT_BLOCK_PTR) @@ -810,6 +860,18 @@ fixup_reorder_chain (void) continue; } } + else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL) + { + /* If the old fallthru is still next or if + asm goto doesn't have a fallthru (e.g. when followed by + __builtin_unreachable ()), nothing to do. */ + if (! e_fall + || bb->aux == e_fall->dest + || e_fall->dest == EXIT_BLOCK_PTR) + continue; + + /* Otherwise we'll have to use the fallthru fixup below. */ + } else { /* Otherwise we have some return, switch or computed @@ -855,8 +917,7 @@ fixup_reorder_chain (void) && JUMP_P (BB_END (bb)) && !any_condjump_p (BB_END (bb)) && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST - (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); + add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX); } } @@ -871,10 +932,56 @@ fixup_reorder_chain (void) FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALLTHRU) break; - + if (e && !can_fallthru (e->src, e->dest)) force_nonfallthru (e); } + + /* Ensure goto_locus from edges has some instructions with that locus + in RTL. */ + if (!optimize) + FOR_EACH_BB (bb) + { + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->goto_locus && !(e->flags & EDGE_ABNORMAL)) + { + basic_block nb; + rtx end; + + insn = BB_END (e->src); + end = PREV_INSN (BB_HEAD (e->src)); + while (insn != end + && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0)) + insn = PREV_INSN (insn); + if (insn != end + && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus)) + continue; + if (simplejump_p (BB_END (e->src)) + && INSN_LOCATOR (BB_END (e->src)) == 0) + { + INSN_LOCATOR (BB_END (e->src)) = e->goto_locus; + continue; + } + if (e->dest != EXIT_BLOCK_PTR) + { + insn = BB_HEAD (e->dest); + end = NEXT_INSN (BB_END (e->dest)); + while (insn != end && !INSN_P (insn)) + insn = NEXT_INSN (insn); + if (insn != end && INSN_LOCATOR (insn) + && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus)) + continue; + } + nb = split_edge (e); + if (!INSN_P (BB_END (nb))) + BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb), + nb); + INSN_LOCATOR (BB_END (nb)) = e->goto_locus; + } + } } /* Perform sanity checks on the insn chain. @@ -1037,7 +1144,7 @@ cfg_layout_can_duplicate_bb_p (const_basic_block bb) rtx duplicate_insn_chain (rtx from, rtx to) { - rtx insn, last; + rtx insn, last, copy; /* Avoid updating of boundaries of previous basic block. The note will get removed from insn stream in fixup. */ @@ -1049,6 +1156,7 @@ duplicate_insn_chain (rtx from, rtx to) { switch (GET_CODE (insn)) { + case DEBUG_INSN: case INSN: case CALL_INSN: case JUMP_INSN: @@ -1058,7 +1166,8 @@ duplicate_insn_chain (rtx from, rtx to) if (GET_CODE (PATTERN (insn)) == ADDR_VEC || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) break; - emit_copy_of_insn_after (insn, get_last_insn ()); + copy = emit_copy_of_insn_after (insn, get_last_insn ()); + maybe_copy_epilogue_insn (insn, copy); break; case CODE_LABEL: @@ -1078,23 +1187,18 @@ duplicate_insn_chain (rtx from, rtx to) case NOTE_INSN_DELETED: case NOTE_INSN_DELETED_LABEL: /* No problem to strip these. */ - case NOTE_INSN_EPILOGUE_BEG: - /* Debug code expect these notes to exist just once. - Keep them in the master copy. - ??? It probably makes more sense to duplicate them for each - epilogue copy. */ case NOTE_INSN_FUNCTION_BEG: /* There is always just single entry to function. */ case NOTE_INSN_BASIC_BLOCK: break; + case NOTE_INSN_EPILOGUE_BEG: case NOTE_INSN_SWITCH_TEXT_SECTIONS: emit_note_copy (insn); break; default: - /* All other notes should have already been eliminated. - */ + /* All other notes should have already been eliminated. */ gcc_unreachable (); } break;