/* 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
Free Software Foundation, Inc.
This file is part of GCC.
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 */
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 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.
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);
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. */
if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
{
basic_block nb;
-
- if (simplejump_p (BB_END (e->src)))
+ 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)
{
- if (INSN_LOCATOR (BB_END (e->src)) == (int) e->goto_locus)
- continue;
- if (INSN_LOCATOR (BB_END (e->src)) == 0)
- {
- INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
- continue;
- }
+ INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
+ continue;
}
if (e->dest != EXIT_BLOCK_PTR)
{
insn = BB_HEAD (e->dest);
- if (!INSN_P (insn))
- insn = next_insn (insn);
- if (insn && INSN_P (insn)
- && INSN_LOCATOR (insn) == (int) e->goto_locus)
+ 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);
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. */
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:
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;