===================================================================
@@ -3752,61 +3752,122 @@ make_call_insn_raw (rtx pattern)
return insn;
}
+/* 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. */
+ SEQUENCE.
+ This function is internal to emit-rtl.c. Use add_insn_after outside
+ this file. */
-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. 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.
+ This function is internal to emit-rtl.c. Use add_insn_before outside
+ this file. */
+
+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, but try to set BLOCK_FOR_INSN.
+ If BB is NULL, an attempt is made to infer the bb from before. */
+
+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)))
@@ -3822,55 +3883,15 @@ add_insn_after (rtx insn, rtx after, bas
&& !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. */
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)
@@ -3889,10 +3910,6 @@ add_insn_before (rtx insn, rtx before, b
|| 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;
}
@@ -4230,21 +4247,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. */
@@ -4391,18 +4393,73 @@ 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. */
/* Emit a note of subtype SUBTYPE after the insn AFTER. */
rtx
emit_note_after (enum insn_note subtype, rtx after)
{
+ /* Some notes are never emitted. */
+ gcc_assert (subtype != NOTE_INSN_DELETED_LABEL);
+
+ basic_block bb = BARRIER_P (after) ? NULL : BLOCK_FOR_INSN (after);
rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_KIND (note) = subtype;
BLOCK_FOR_INSN (note) = NULL;
+ gcc_assert (subtype != NOTE_INSN_DELETED_LABEL);
memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
- add_insn_after (note, after, NULL);
+
+ /* NOTE_INSN_SWITCH_TEXT_SECTIONS only appears between basic blocks. */
+ if (subtype == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ add_insn_after_nobb (note, after);
+ /* Notes for var tracking and EH region markers can appear between or
+ inside basic blocks. If AFTER is the tail of its basic block, do
+ not set BLOCK_FOR_INSN on the new note. */
+ else if ((subtype == NOTE_INSN_VAR_LOCATION
+ || subtype == NOTE_INSN_CALL_ARG_LOCATION
+ || subtype == NOTE_INSN_EH_REGION_BEG
+ || subtype == NOTE_INSN_EH_REGION_END)
+ && bb != NULL && BB_END (bb) == after)
+ add_insn_after_nobb (note, after);
+ else
+ add_insn_after (note, after, NULL);
+ return note;
+}
+
+/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
+
+rtx
+emit_note_before (enum insn_note subtype, rtx before)
+{
+ /* Some notes are never emitted. */
+ gcc_assert (subtype != NOTE_INSN_DELETED_LABEL);
+
+ basic_block bb = BARRIER_P (before) ? NULL : BLOCK_FOR_INSN (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)));
+
+ /* NOTE_INSN_SWITCH_TEXT_SECTIONS note only appears between basic blocks. */
+ if (subtype == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ add_insn_before_nobb (note, before);
+ /* Notes for var tracking and EH region markers can appear between or
+ inside basic blocks. If BEFORE is the head of its basic block, do
+ not set BLOCK_FOR_INSN on the new note. */
+ else if ((subtype == NOTE_INSN_VAR_LOCATION
+ || subtype == NOTE_INSN_CALL_ARG_LOCATION
+ || subtype == NOTE_INSN_EH_REGION_BEG
+ || subtype == NOTE_INSN_EH_REGION_END)
+ && bb != NULL && BB_HEAD (bb) == before)
+ add_insn_before_nobb (note, before);
+ else
+ add_insn_before (note, before, NULL);
return note;
}
===================================================================
@@ -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;
}
}
===================================================================
@@ -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_tracki
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 */
}
};