As discussed on PR middle-end/78016, here is the patch.
This patch makes EXPR_LIST/INST_LIST/INT_LIST insertion bi-directional, the new node can be inserted to either the start or the end of the given list. The existed alloc_EXPR_LIST, alloc_INSN_LIST becomes wrapper of new bi-directional function, there is no functional change on them, callers of them are *not affected*. This patch then factor out those REG_NOTES copy code in emit-rtl.c and sel-sched-ir.c into a function append_insn_reg_notes in rtlanal.c, it use those new bi-directional interfaces to make sure the order of REG_NOTES are not changed during insn copy. Redundant code in emit-rtl.c and sel-sched-ir.c are deleted also. x86_64/aarch64 bootstrap OK. c/c++ regression OK. OK for trunk? gcc/ 2016-10-20 Jiong Wang <jiong.w...@arm.com> PR middle-end/78016 * lists.c (alloc_INSN_LIST_bidirection): New function. The function body is cloned from alloc_INSN_LIST with minor changes to make it support bi-directional insertion. (alloc_EXPR_LIST_bidirection): Likewise. (alloc_INT_LIST_bidirection): New function. Alloc INT_LIST node, and support bi-directional insertion into given list. (alloc_INSN_LIST): Call alloc_INSN_LIST_bidirection. (alloc_EXPR_LIST): Call alloc_EXPR_LIST_bidirection. * rtl.h (append_insn_reg_notes): New declaration. (alloc_INSN_LIST_bidirection): New declaration. (alloc_EXPR_LIST_bidirection): New declaration. (alloc_INT_LIST_bidirection): New declaration. * rtlanal.c (alloc_reg_note_bidirection): New static function. Function body is cloned from alloc_reg_note with minor changes to make it support bi-directional insertion. (alloc_reg_note): Call alloc_reg_note_bidirection. (append_insn_reg_notes): New function. * emit-rtl.c (emit_copy_of_insn_after): Use append_insn_reg_notes. * sel-sched-ir.c (create_copy_of_insn_rtx): Likewise.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 2d6d1eb..87eb1e3 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -6125,7 +6125,6 @@ rtx_insn * emit_copy_of_insn_after (rtx_insn *insn, rtx_insn *after) { rtx_insn *new_rtx; - rtx link; switch (GET_CODE (insn)) { @@ -6171,15 +6170,7 @@ emit_copy_of_insn_after (rtx_insn *insn, rtx_insn *after) /* Copy all REG_NOTES except 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); link; link = XEXP (link, 1)) - if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) - { - if (GET_CODE (link) == EXPR_LIST) - add_reg_note (new_rtx, REG_NOTE_KIND (link), - copy_insn_1 (XEXP (link, 0))); - else - add_shallow_copy_of_reg_note (new_rtx, link); - } + append_insn_reg_notes (new_rtx, insn, true, false); INSN_CODE (new_rtx) = INSN_CODE (insn); return new_rtx; diff --git a/gcc/lists.c b/gcc/lists.c index 96b4bc7..cd30b7c 100644 --- a/gcc/lists.c +++ b/gcc/lists.c @@ -98,11 +98,14 @@ remove_list_elem (rtx elem, rtx *listp) /* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST - is made. */ + is made. The new node will be appended at the end of LIST if APPEND_P is + TRUE, otherwise list is appended to the new node. */ + rtx_insn_list * -alloc_INSN_LIST (rtx val, rtx next) +alloc_INSN_LIST_bidirection (rtx val, rtx list, bool append_p) { rtx_insn_list *r; + rtx next = append_p ? NULL_RTX : list; if (unused_insn_list) { @@ -117,16 +120,33 @@ alloc_INSN_LIST (rtx val, rtx next) else r = gen_rtx_INSN_LIST (VOIDmode, val, next); + if (append_p) + { + gcc_assert (list != NULL_RTX); + XEXP (list, 1) = r; + } + return r; } +/* Allocate new INSN_LIST node for VAL, append NEXT to it. */ + +rtx_insn_list * +alloc_INSN_LIST (rtx val, rtx next) +{ + return alloc_INSN_LIST_bidirection (val, next, false); +} + /* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST - is made. */ + is made. The new node will be appended at the end of LIST if APPEND_P is + TRUE, otherwise list is appended to the new node. */ + rtx_expr_list * -alloc_EXPR_LIST (int kind, rtx val, rtx next) +alloc_EXPR_LIST_bidirection (int kind, rtx val, rtx list, bool append_p) { rtx_expr_list *r; + rtx next = append_p ? NULL_RTX : list; if (unused_expr_list) { @@ -139,9 +159,23 @@ alloc_EXPR_LIST (int kind, rtx val, rtx next) else r = gen_rtx_EXPR_LIST ((machine_mode) kind, val, next); + if (append_p) + { + gcc_assert (list != NULL_RTX); + XEXP (list, 1) = r; + } + return r; } +/* Allocate new EXPR_LIST node for KIND and VAL, append NEXT to it. */ + +rtx_expr_list * +alloc_EXPR_LIST (int kind, rtx val, rtx next) +{ + return alloc_EXPR_LIST_bidirection (kind, val, next, false); +} + /* This function will free up an entire list of EXPR_LIST nodes. */ void free_EXPR_LIST_list (rtx_expr_list **listp) @@ -242,4 +276,22 @@ remove_free_EXPR_LIST_node (rtx_expr_list **listp) return elem; } +/* Allocate new INT_LIST node for KIND and VAL, append it to LIST if APPEND_P is + TRUE, otherwise append LIST to it. */ + +rtx +alloc_INT_LIST_bidirection (int kind, int val, rtx list, bool append_p) +{ + rtx r = gen_rtx_INT_LIST ((machine_mode) kind, val, + append_p ? NULL_RTX : list); + + if (append_p) + { + gcc_assert (list != NULL_RTX); + XEXP (list, 1) = r; + } + + return r; +} + #include "gt-lists.h" diff --git a/gcc/rtl.h b/gcc/rtl.h index ce1131b..5ce0c27 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2996,6 +2996,7 @@ extern rtx alloc_reg_note (enum reg_note, rtx, rtx); extern void add_reg_note (rtx, enum reg_note, rtx); extern void add_int_reg_note (rtx, enum reg_note, int); extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx); +extern void append_insn_reg_notes (rtx_insn *, rtx_insn *, bool, bool); extern void remove_note (rtx, const_rtx); extern void remove_reg_equal_equiv_notes (rtx_insn *); extern void remove_reg_equal_equiv_notes_for_regno (unsigned int); @@ -3095,13 +3096,16 @@ extern void free_INSN_LIST_list (rtx_insn_list **); extern void free_EXPR_LIST_node (rtx); extern void free_INSN_LIST_node (rtx); extern rtx_insn_list *alloc_INSN_LIST (rtx, rtx); +extern rtx_insn_list *alloc_INSN_LIST_bidirection (rtx, rtx, bool); extern rtx_insn_list *copy_INSN_LIST (rtx_insn_list *); extern rtx_insn_list *concat_INSN_LIST (rtx_insn_list *, rtx_insn_list *); extern rtx_expr_list *alloc_EXPR_LIST (int, rtx, rtx); +extern rtx_expr_list *alloc_EXPR_LIST_bidirection (int, rtx, rtx, bool); extern void remove_free_INSN_LIST_elem (rtx_insn *, rtx_insn_list **); extern rtx remove_list_elem (rtx, rtx *); extern rtx_insn *remove_free_INSN_LIST_node (rtx_insn_list **); extern rtx remove_free_EXPR_LIST_node (rtx_expr_list **); +extern rtx alloc_INT_LIST_bidirection (int, int, rtx, bool); /* reginfo.c */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 2a0a1d2..7effdd8 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -2244,10 +2244,12 @@ int_reg_note_p (enum reg_note kind) } /* Allocate a register note with kind KIND and datum DATUM. LIST is - stored as the pointer to the next register note. */ + stored as the pointer to the existed register note. Append new note to LIST + if APPEND_P is TRUE, otherwise append LIST to new note. */ -rtx -alloc_reg_note (enum reg_note kind, rtx datum, rtx list) +static rtx +alloc_reg_note_bidirection (enum reg_note kind, rtx datum, rtx list, + bool append_p) { rtx note; @@ -2262,18 +2264,27 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list) /* These types of register notes use an INSN_LIST rather than an EXPR_LIST, so that copying is done right and dumps look better. */ - note = alloc_INSN_LIST (datum, list); + note = alloc_INSN_LIST_bidirection (datum, list, append_p); PUT_REG_NOTE_KIND (note, kind); break; default: - note = alloc_EXPR_LIST (kind, datum, list); + note = alloc_EXPR_LIST_bidirection (kind, datum, list, append_p); break; } return note; } +/* Allocate a register note with kind KIND and datum DATUM. Append LIST to the + new note. */ + +rtx +alloc_reg_note (enum reg_note kind, rtx datum, rtx list) +{ + return alloc_reg_note_bidirection (kind, datum, list, false); +} + /* Add register note with kind KIND and datum DATUM to INSN. */ void @@ -2334,6 +2345,66 @@ remove_note (rtx insn, const_rtx note) } } +/* Append all REG_NOTES in order from FROM_INSN to end of existed REG_NOTES of + TO_INSN. Skip REG_LABEL_OPERAND if skip_reg_label_p is TRUE, skip REG_EQUAL + and REG_EQUIV if skip_reg_equ_p is TRUE. */ + +void +append_insn_reg_notes (rtx_insn *to_insn, rtx_insn *from_insn, + bool skip_reg_label_p, bool skip_reg_equ_p) +{ + /* Locate to the end of existed REG_NOTES of TO_INSN. */ + rtx tail = REG_NOTES (to_insn); + + if (tail != NULL_RTX) + { + rtx tail_old; + + do { + tail_old = tail; + tail = XEXP (tail, 1); + } while (tail != NULL_RTX); + + tail = tail_old; + } + + /* Do the insertion. */ + rtx link; + enum reg_note kind; + for (link = REG_NOTES (from_insn); link; link = XEXP (link, 1)) + { + kind = REG_NOTE_KIND (link); + + if ((skip_reg_label_p && kind == REG_LABEL_OPERAND) + || (skip_reg_equ_p && (kind == REG_EQUAL || kind == REG_EQUIV))) + continue; + + if (tail == NULL_RTX) + { + /* Initialize the head of REG_NOTES for TO_RTX if necessary. */ + if (GET_CODE (link) == INT_LIST) + add_shallow_copy_of_reg_note (to_insn, link); + else + add_reg_note (to_insn, kind, (GET_CODE (link) == EXPR_LIST + ? copy_insn_1 (XEXP (link, 0)) + : XEXP (link ,0))); + tail = REG_NOTES (to_insn); + } + else + { + /* Append to the end of existed REG_NOTES of TO_RTX. */ + if (GET_CODE (link) == INT_LIST) + tail = alloc_INT_LIST_bidirection (kind, XINT (link, 0), tail, + true); + else + tail = alloc_reg_note_bidirection (kind, + (GET_CODE (link) == EXPR_LIST + ? copy_insn_1 (XEXP (link, 0)) + : XEXP (link, 0)), tail, true); + } + } +} + /* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes. */ void diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index 210b1e4..bd28f15 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -5750,7 +5750,6 @@ rtx_insn * create_copy_of_insn_rtx (rtx insn_rtx) { rtx_insn *res; - rtx link; if (DEBUG_INSN_P (insn_rtx)) return create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)), @@ -5764,17 +5763,7 @@ create_copy_of_insn_rtx (rtx insn_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)); - } + append_insn_reg_notes (res, safe_as_a <rtx_insn *> (insn_rtx), true, true); return res; }