re PR middle-end/43631 (var-tracking inserts notes with non-NULL BLOCK_FOR_INSN in between basic blocks)
PR middle-end/43631 * emit-rtl.c (make_note_raw): New function. (link_insn_into_chain): New static inline function. (add_insn): Use it. (add_insn_before, add_insn_after): Factor insn chain linking code... (add_insn_before_nobb, add_insn_after_nobb): ...here, new functions using link_insn_into_chain. (note_outside_basic_block_p): New helper function for emit_note_after and emit_note_before. (emit_note_after): Use nobb variant of add_insn_after if the note should not be contained in a basic block. (emit_note_before): Use nobb variant of add_insn_before if the note should not be contained in a basic block. (emit_note_copy): Use make_note_raw. (emit_note): Likewise. * bb-reorder.c (insert_section_boundary_note): Remove hack to set BLOCK_FOR_INSN to NULL manually for NOTE_INSN_SWITCH_TEXT_SECTIONS. * jump.c (cleanup_barriers): Use reorder_insns_nobb to avoid making the moved barrier the tail of the basic block it follows. * var-tracking.c (pass_variable_tracking): Add TODO_verify_flow. From-SVN: r197994
This commit is contained in:
parent
996943bea7
commit
96fba5210e
|
@ -1,3 +1,26 @@
|
|||
2013-04-16 Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
PR middle-end/43631
|
||||
* emit-rtl.c (make_note_raw): New function.
|
||||
(link_insn_into_chain): New static inline function.
|
||||
(add_insn): Use it.
|
||||
(add_insn_before, add_insn_after): Factor insn chain linking code...
|
||||
(add_insn_before_nobb, add_insn_after_nobb): ...here, new functions
|
||||
using link_insn_into_chain.
|
||||
(note_outside_basic_block_p): New helper function for emit_note_after
|
||||
and emit_note_before.
|
||||
(emit_note_after): Use nobb variant of add_insn_after if the note
|
||||
should not be contained in a basic block.
|
||||
(emit_note_before): Use nobb variant of add_insn_before if the note
|
||||
should not be contained in a basic block.
|
||||
(emit_note_copy): Use make_note_raw.
|
||||
(emit_note): Likewise.
|
||||
* bb-reorder.c (insert_section_boundary_note): Remove hack to set
|
||||
BLOCK_FOR_INSN to NULL manually for NOTE_INSN_SWITCH_TEXT_SECTIONS.
|
||||
* jump.c (cleanup_barriers): Use reorder_insns_nobb to avoid making
|
||||
the moved barrier the tail of the basic block it follows.
|
||||
* var-tracking.c (pass_variable_tracking): Add TODO_verify_flow.
|
||||
|
||||
2013-04-15 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/56962
|
||||
|
|
|
@ -2173,7 +2173,6 @@ static void
|
|||
insert_section_boundary_note (void)
|
||||
{
|
||||
basic_block bb;
|
||||
rtx new_note;
|
||||
int first_partition = 0;
|
||||
|
||||
if (!flag_reorder_blocks_and_partition)
|
||||
|
@ -2185,11 +2184,7 @@ insert_section_boundary_note (void)
|
|||
first_partition = BB_PARTITION (bb);
|
||||
if (BB_PARTITION (bb) != first_partition)
|
||||
{
|
||||
new_note = emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS,
|
||||
BB_HEAD (bb));
|
||||
/* ??? This kind of note always lives between basic blocks,
|
||||
but add_insn_before will set BLOCK_FOR_INSN anyway. */
|
||||
BLOCK_FOR_INSN (new_note) = NULL;
|
||||
emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS, BB_HEAD (bb));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
285
gcc/emit-rtl.c
285
gcc/emit-rtl.c
|
@ -3763,62 +3763,135 @@ make_call_insn_raw (rtx pattern)
|
|||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Like `make_insn_raw' but make a NOTE instead of an insn. */
|
||||
|
||||
static rtx
|
||||
make_note_raw (enum insn_note subtype)
|
||||
{
|
||||
/* Some notes are never created this way at all. These notes are
|
||||
only created by patching out insns. */
|
||||
gcc_assert (subtype != NOTE_INSN_DELETED_LABEL
|
||||
&& subtype != NOTE_INSN_DELETED_DEBUG_LABEL);
|
||||
|
||||
rtx note = rtx_alloc (NOTE);
|
||||
INSN_UID (note) = cur_insn_uid++;
|
||||
NOTE_KIND (note) = subtype;
|
||||
BLOCK_FOR_INSN (note) = NULL;
|
||||
memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
|
||||
return note;
|
||||
}
|
||||
|
||||
/* Add INSN to the end of the doubly-linked list, between PREV and NEXT.
|
||||
INSN may be any object that can appear in the chain: INSN_P and NOTE_P objects,
|
||||
but also BARRIERs and JUMP_TABLE_DATAs. PREV and NEXT may be NULL. */
|
||||
|
||||
static inline void
|
||||
link_insn_into_chain (rtx insn, rtx prev, rtx next)
|
||||
{
|
||||
PREV_INSN (insn) = prev;
|
||||
NEXT_INSN (insn) = next;
|
||||
if (prev != NULL)
|
||||
{
|
||||
NEXT_INSN (prev) = insn;
|
||||
if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
|
||||
{
|
||||
rtx sequence = PATTERN (prev);
|
||||
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
|
||||
}
|
||||
}
|
||||
if (next != NULL)
|
||||
{
|
||||
PREV_INSN (next) = insn;
|
||||
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
|
||||
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add INSN to the end of the doubly-linked list.
|
||||
INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */
|
||||
|
||||
void
|
||||
add_insn (rtx insn)
|
||||
{
|
||||
PREV_INSN (insn) = get_last_insn();
|
||||
NEXT_INSN (insn) = 0;
|
||||
|
||||
if (NULL != get_last_insn())
|
||||
NEXT_INSN (get_last_insn ()) = insn;
|
||||
|
||||
rtx prev = get_last_insn ();
|
||||
link_insn_into_chain (insn, prev, NULL);
|
||||
if (NULL == get_insns ())
|
||||
set_first_insn (insn);
|
||||
|
||||
set_last_insn (insn);
|
||||
}
|
||||
|
||||
/* Add INSN into the doubly-linked list after insn AFTER. This and
|
||||
the next should be the only functions called to insert an insn once
|
||||
delay slots have been filled since only they know how to update a
|
||||
SEQUENCE. */
|
||||
/* Add INSN into the doubly-linked list after insn AFTER. */
|
||||
|
||||
void
|
||||
add_insn_after (rtx insn, rtx after, basic_block bb)
|
||||
static void
|
||||
add_insn_after_nobb (rtx insn, rtx after)
|
||||
{
|
||||
rtx next = NEXT_INSN (after);
|
||||
|
||||
gcc_assert (!optimize || !INSN_DELETED_P (after));
|
||||
|
||||
NEXT_INSN (insn) = next;
|
||||
PREV_INSN (insn) = after;
|
||||
link_insn_into_chain (insn, after, next);
|
||||
|
||||
if (next)
|
||||
if (next == NULL)
|
||||
{
|
||||
PREV_INSN (next) = insn;
|
||||
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
|
||||
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
|
||||
if (get_last_insn () == after)
|
||||
set_last_insn (insn);
|
||||
else
|
||||
{
|
||||
struct sequence_stack *stack = seq_stack;
|
||||
/* Scan all pending sequences too. */
|
||||
for (; stack; stack = stack->next)
|
||||
if (after == stack->last)
|
||||
{
|
||||
stack->last = insn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (get_last_insn () == after)
|
||||
set_last_insn (insn);
|
||||
else
|
||||
}
|
||||
|
||||
/* Add INSN into the doubly-linked list before insn BEFORE. */
|
||||
|
||||
static void
|
||||
add_insn_before_nobb (rtx insn, rtx before)
|
||||
{
|
||||
rtx prev = PREV_INSN (before);
|
||||
|
||||
gcc_assert (!optimize || !INSN_DELETED_P (before));
|
||||
|
||||
link_insn_into_chain (insn, prev, before);
|
||||
|
||||
if (prev == NULL)
|
||||
{
|
||||
struct sequence_stack *stack = seq_stack;
|
||||
/* Scan all pending sequences too. */
|
||||
for (; stack; stack = stack->next)
|
||||
if (after == stack->last)
|
||||
{
|
||||
stack->last = insn;
|
||||
break;
|
||||
}
|
||||
if (get_insns () == before)
|
||||
set_first_insn (insn);
|
||||
else
|
||||
{
|
||||
struct sequence_stack *stack = seq_stack;
|
||||
/* Scan all pending sequences too. */
|
||||
for (; stack; stack = stack->next)
|
||||
if (before == stack->first)
|
||||
{
|
||||
stack->first = insn;
|
||||
break;
|
||||
}
|
||||
|
||||
gcc_assert (stack);
|
||||
gcc_assert (stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Like add_insn_after_nobb, but try to set BLOCK_FOR_INSN.
|
||||
If BB is NULL, an attempt is made to infer the bb from before.
|
||||
|
||||
This and the next function should be the only functions called
|
||||
to insert an insn once delay slots have been filled since only
|
||||
they know how to update a SEQUENCE. */
|
||||
|
||||
void
|
||||
add_insn_after (rtx insn, rtx after, basic_block bb)
|
||||
{
|
||||
add_insn_after_nobb (insn, after);
|
||||
if (!BARRIER_P (after)
|
||||
&& !BARRIER_P (insn)
|
||||
&& (bb = BLOCK_FOR_INSN (after)))
|
||||
|
@ -3834,55 +3907,19 @@ add_insn_after (rtx insn, rtx after, basic_block bb)
|
|||
&& !NOTE_INSN_BASIC_BLOCK_P (insn))
|
||||
BB_END (bb) = insn;
|
||||
}
|
||||
|
||||
NEXT_INSN (after) = insn;
|
||||
if (NONJUMP_INSN_P (after) && GET_CODE (PATTERN (after)) == SEQUENCE)
|
||||
{
|
||||
rtx sequence = PATTERN (after);
|
||||
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add INSN into the doubly-linked list before insn BEFORE. This and
|
||||
the previous should be the only functions called to insert an insn
|
||||
once delay slots have been filled since only they know how to
|
||||
update a SEQUENCE. If BB is NULL, an attempt is made to infer the
|
||||
bb from before. */
|
||||
/* Like add_insn_before_nobb, but try to set BLOCK_FOR_INSN.
|
||||
If BB is NULL, an attempt is made to infer the bb from before.
|
||||
|
||||
This and the previous function should be the only functions called
|
||||
to insert an insn once delay slots have been filled since only
|
||||
they know how to update a SEQUENCE. */
|
||||
|
||||
void
|
||||
add_insn_before (rtx insn, rtx before, basic_block bb)
|
||||
{
|
||||
rtx prev = PREV_INSN (before);
|
||||
|
||||
gcc_assert (!optimize || !INSN_DELETED_P (before));
|
||||
|
||||
PREV_INSN (insn) = prev;
|
||||
NEXT_INSN (insn) = before;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
NEXT_INSN (prev) = insn;
|
||||
if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
|
||||
{
|
||||
rtx sequence = PATTERN (prev);
|
||||
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
|
||||
}
|
||||
}
|
||||
else if (get_insns () == before)
|
||||
set_first_insn (insn);
|
||||
else
|
||||
{
|
||||
struct sequence_stack *stack = seq_stack;
|
||||
/* Scan all pending sequences too. */
|
||||
for (; stack; stack = stack->next)
|
||||
if (before == stack->first)
|
||||
{
|
||||
stack->first = insn;
|
||||
break;
|
||||
}
|
||||
|
||||
gcc_assert (stack);
|
||||
}
|
||||
add_insn_before_nobb (insn, before);
|
||||
|
||||
if (!bb
|
||||
&& !BARRIER_P (before)
|
||||
|
@ -3901,13 +3938,8 @@ add_insn_before (rtx insn, rtx before, basic_block bb)
|
|||
|| BARRIER_P (insn)
|
||||
|| NOTE_INSN_BASIC_BLOCK_P (insn));
|
||||
}
|
||||
|
||||
PREV_INSN (before) = insn;
|
||||
if (NONJUMP_INSN_P (before) && GET_CODE (PATTERN (before)) == SEQUENCE)
|
||||
PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
|
||||
}
|
||||
|
||||
|
||||
/* Replace insn with an deleted instruction note. */
|
||||
|
||||
void
|
||||
|
@ -4251,21 +4283,6 @@ emit_label_before (rtx label, rtx before)
|
|||
add_insn_before (label, before, NULL);
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
|
||||
|
||||
rtx
|
||||
emit_note_before (enum insn_note subtype, rtx before)
|
||||
{
|
||||
rtx note = rtx_alloc (NOTE);
|
||||
INSN_UID (note) = cur_insn_uid++;
|
||||
NOTE_KIND (note) = subtype;
|
||||
BLOCK_FOR_INSN (note) = NULL;
|
||||
memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
|
||||
|
||||
add_insn_before (note, before, NULL);
|
||||
return note;
|
||||
}
|
||||
|
||||
/* Helper for emit_insn_after, handles lists of instructions
|
||||
efficiently. */
|
||||
|
@ -4412,18 +4429,68 @@ emit_label_after (rtx label, rtx after)
|
|||
add_insn_after (label, after, NULL);
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Notes require a bit of special handling: Some notes need to have their
|
||||
BLOCK_FOR_INSN set, others should never have it set, and some should
|
||||
have it set or clear depending on the context. */
|
||||
|
||||
/* Return true iff a note of kind SUBTYPE should be emitted with routines
|
||||
that never set BLOCK_FOR_INSN on NOTE. BB_BOUNDARY is true if the
|
||||
caller is asked to emit a note before BB_HEAD, or after BB_END. */
|
||||
|
||||
static bool
|
||||
note_outside_basic_block_p (enum insn_note subtype, bool on_bb_boundary_p)
|
||||
{
|
||||
switch (subtype)
|
||||
{
|
||||
/* NOTE_INSN_SWITCH_TEXT_SECTIONS only appears between basic blocks. */
|
||||
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
|
||||
return true;
|
||||
|
||||
/* Notes for var tracking and EH region markers can appear between or
|
||||
inside basic blocks. If the caller is emitting on the basic block
|
||||
boundary, do not set BLOCK_FOR_INSN on the new note. */
|
||||
case NOTE_INSN_VAR_LOCATION:
|
||||
case NOTE_INSN_CALL_ARG_LOCATION:
|
||||
case NOTE_INSN_EH_REGION_BEG:
|
||||
case NOTE_INSN_EH_REGION_END:
|
||||
return on_bb_boundary_p;
|
||||
|
||||
/* Otherwise, BLOCK_FOR_INSN must be set. */
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit a note of subtype SUBTYPE after the insn AFTER. */
|
||||
|
||||
rtx
|
||||
emit_note_after (enum insn_note subtype, rtx after)
|
||||
{
|
||||
rtx note = rtx_alloc (NOTE);
|
||||
INSN_UID (note) = cur_insn_uid++;
|
||||
NOTE_KIND (note) = subtype;
|
||||
BLOCK_FOR_INSN (note) = NULL;
|
||||
memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
|
||||
add_insn_after (note, after, NULL);
|
||||
rtx note = make_note_raw (subtype);
|
||||
basic_block bb = BARRIER_P (after) ? NULL : BLOCK_FOR_INSN (after);
|
||||
bool on_bb_boundary_p = (bb != NULL && BB_END (bb) == after);
|
||||
|
||||
if (note_outside_basic_block_p (subtype, on_bb_boundary_p))
|
||||
add_insn_after_nobb (note, after);
|
||||
else
|
||||
add_insn_after (note, after, bb);
|
||||
return note;
|
||||
}
|
||||
|
||||
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
|
||||
|
||||
rtx
|
||||
emit_note_before (enum insn_note subtype, rtx before)
|
||||
{
|
||||
rtx note = make_note_raw (subtype);
|
||||
basic_block bb = BARRIER_P (before) ? NULL : BLOCK_FOR_INSN (before);
|
||||
bool on_bb_boundary_p = (bb != NULL && BB_HEAD (bb) == before);
|
||||
|
||||
if (note_outside_basic_block_p (subtype, on_bb_boundary_p))
|
||||
add_insn_before_nobb (note, before);
|
||||
else
|
||||
add_insn_before (note, before, bb);
|
||||
return note;
|
||||
}
|
||||
|
||||
|
@ -4866,16 +4933,10 @@ emit_barrier (void)
|
|||
rtx
|
||||
emit_note_copy (rtx orig)
|
||||
{
|
||||
rtx note;
|
||||
|
||||
note = rtx_alloc (NOTE);
|
||||
|
||||
INSN_UID (note) = cur_insn_uid++;
|
||||
enum insn_note kind = (enum insn_note) NOTE_KIND (orig);
|
||||
rtx note = make_note_raw (kind);
|
||||
NOTE_DATA (note) = NOTE_DATA (orig);
|
||||
NOTE_KIND (note) = NOTE_KIND (orig);
|
||||
BLOCK_FOR_INSN (note) = NULL;
|
||||
add_insn (note);
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
|
@ -4885,13 +4946,7 @@ emit_note_copy (rtx orig)
|
|||
rtx
|
||||
emit_note (enum insn_note kind)
|
||||
{
|
||||
rtx note;
|
||||
|
||||
note = rtx_alloc (NOTE);
|
||||
INSN_UID (note) = cur_insn_uid++;
|
||||
NOTE_KIND (note) = kind;
|
||||
memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
|
||||
BLOCK_FOR_INSN (note) = NULL;
|
||||
rtx note = make_note_raw (kind);
|
||||
add_insn (note);
|
||||
return note;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ cleanup_barriers (void)
|
|||
if (BARRIER_P (prev))
|
||||
delete_insn (insn);
|
||||
else if (prev != PREV_INSN (insn))
|
||||
reorder_insns (insn, insn, prev);
|
||||
reorder_insns_nobb (insn, insn, prev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -10238,6 +10238,7 @@ struct rtl_opt_pass pass_variable_tracking =
|
|||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_verify_rtl_sharing /* todo_flags_finish */
|
||||
TODO_verify_rtl_sharing
|
||||
| TODO_verify_flow /* todo_flags_finish */
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue