Index: gcc/gcc/cfglayout.c |
diff --git a/gcc/gcc/cfglayout.c b/gcc/gcc/cfglayout.c |
index 27eb029d076688b67bdd35dc439d377aa6329f90..5e120570b9a030fcd073e74582df4ed6a8b04256 100644 |
--- a/gcc/gcc/cfglayout.c |
+++ b/gcc/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; |
@@ -292,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) |
{ |
@@ -309,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) |
@@ -363,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 */ |
@@ -382,10 +392,10 @@ 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 */ |
} |
@@ -585,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); |
@@ -686,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 (); |
} |
@@ -779,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) |
@@ -840,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 |
@@ -900,7 +932,7 @@ 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); |
} |
@@ -1112,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. */ |
@@ -1124,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: |
@@ -1133,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: |
@@ -1153,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; |