diff options
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/bb-reorder.c | 7 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 285 | ||||
-rw-r--r-- | gcc/jump.c | 2 | ||||
-rw-r--r-- | gcc/var-tracking.c | 3 |
5 files changed, 197 insertions, 123 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58f811efd80..31c21e035d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 7605e17e7ef..abb2e391983 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -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; } } diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 5a24a7913c4..c8efb5ca4c5 100644 --- a/gcc/emit-rtl.c +++ b/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; } diff --git a/gcc/jump.c b/gcc/jump.c index 6038c255d8b..9a171f4a9d9 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -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; diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 4855fb155b3..337af5a5fdc 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -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 */ } }; |