/* Instruction scheduling pass. Selective scheduler and pipeliner.
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+ Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
else
EXPR_TARGET_AVAILABLE (to) = -1;
}
+ else if (EXPR_TARGET_AVAILABLE (from) == 0
+ && EXPR_LHS (from)
+ && REG_P (EXPR_LHS (from))
+ && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
+ EXPR_TARGET_AVAILABLE (to) = -1;
else
EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
}
static bool
maybe_tidy_empty_bb (basic_block bb)
{
- basic_block succ_bb, pred_bb;
+ basic_block succ_bb, pred_bb, note_bb;
VEC (basic_block, heap) *dom_bbs;
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
if (e->flags & EDGE_COMPLEX)
return false;
+ else if (e->flags & EDGE_FALLTHRU)
+ {
+ rtx note;
+ /* If prev bb ends with asm goto, see if any of the
+ ASM_OPERANDS_LABELs don't point to the fallthru
+ label. Do not attempt to redirect it in that case. */
+ if (JUMP_P (BB_END (e->src))
+ && (note = extract_asm_operands (PATTERN (BB_END (e->src)))))
+ {
+ int i, n = ASM_OPERANDS_LABEL_LENGTH (note);
+
+ for (i = 0; i < n; ++i)
+ if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (bb))
+ return false;
+ }
+ }
free_data_sets (bb);
pred_bb = NULL;
dom_bbs = NULL;
+ /* Save a pred/succ from the current region to attach the notes to. */
+ note_bb = NULL;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (in_current_region_p (e->src))
+ {
+ note_bb = e->src;
+ break;
+ }
+ if (note_bb == NULL)
+ note_bb = succ_bb;
+
/* Redirect all non-fallthru edges to the next bb. */
while (rescan_p)
{
else
{
/* This is a block without fallthru predecessor. Just delete it. */
- gcc_assert (pred_bb != NULL);
-
- if (in_current_region_p (pred_bb))
- move_bb_info (pred_bb, bb);
+ gcc_assert (note_bb);
+ move_bb_info (note_bb, bb);
remove_empty_bb (bb, true);
}
static void
move_bb_info (basic_block merge_bb, basic_block empty_bb)
{
- gcc_assert (in_current_region_p (merge_bb));
-
- concat_note_lists (BB_NOTE_LIST (empty_bb),
- &BB_NOTE_LIST (merge_bb));
+ if (in_current_region_p (merge_bb))
+ concat_note_lists (BB_NOTE_LIST (empty_bb),
+ &BB_NOTE_LIST (merge_bb));
BB_NOTE_LIST (empty_bb) = NULL_RTX;
}
rtx
create_copy_of_insn_rtx (rtx insn_rtx)
{
- rtx res;
+ rtx res, link;
if (DEBUG_INSN_P (insn_rtx))
return create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
NULL_RTX);
+
+ /* Copy all REG_NOTES except REG_EQUAL/REG_EQUIV and REG_LABEL_OPERAND
+ since mark_jump_label will make them. REG_LABEL_TARGETs are created
+ there too, but are supposed to be sticky, so we copy them. */
+ for (link = REG_NOTES (insn_rtx); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND
+ && REG_NOTE_KIND (link) != REG_EQUAL
+ && REG_NOTE_KIND (link) != REG_EQUIV)
+ {
+ if (GET_CODE (link) == EXPR_LIST)
+ add_reg_note (res, REG_NOTE_KIND (link),
+ copy_insn_1 (XEXP (link, 0)));
+ else
+ add_reg_note (res, REG_NOTE_KIND (link), XEXP (link, 0));
+ }
+
return res;
}