@@ -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;
@@ -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"
@@ -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 */
@@ -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
@@ -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;
}