unsigned dest_hash;
/* The SET_DEST, with SUBREG, etc., stripped. */
rtx inner_dest;
+ /* Original machine mode, in case it becomes a CONST_INT. */
+ ENUM_BITFIELD(machine_mode) mode : MACHINE_MODE_BITSIZE;
/* Nonzero if the SET_SRC is in memory. */
- char src_in_memory;
+ unsigned int src_in_memory : 1;
/* Nonzero if the SET_SRC contains something
whose value cannot be predicted and understood. */
- char src_volatile;
- /* Original machine mode, in case it becomes a CONST_INT. */
- ENUM_BITFIELD(machine_mode) mode : MACHINE_MODE_BITSIZE;
+ unsigned int src_volatile : 1;
+ /* Nonzero if RTL is an artifical set that has been created to describe
+ part of an insn's effect. Zero means that RTL appears directly in
+ the insn pattern. */
+ unsigned int is_fake_set : 1;
/* Hash value of constant equivalent for SET_SRC. */
unsigned src_const_hash;
/* A constant equivalent for SET_SRC, if any. */
}
}
-/* Add an entry containing RTL X into SETS. */
+/* Add an entry containing RTL X into SETS. IS_FAKE_SET is true if X is
+ an artifical set that has been created to describe part of an insn's
+ effect. */
static inline void
-add_to_set (vec<struct set> *sets, rtx x)
+add_to_set (vec<struct set> *sets, rtx x, bool is_fake_set)
{
struct set entry = {};
entry.rtl = x;
+ entry.is_fake_set = is_fake_set;
sets->safe_push (entry);
}
&& known_eq (GET_MODE_NUNITS (GET_MODE (SET_SRC (x))), 1)))
{
/* First register the vector itself. */
- add_to_set (psets, x);
+ add_to_set (psets, x, false);
rtx src = SET_SRC (x);
/* Go over the constants of the CONST_VECTOR in forward order, to
put them in the same order in the SETS array. */
used to tell CSE how to get to a particular constant. */
rtx y = simplify_gen_vec_select (SET_DEST (x), i);
gcc_assert (y);
- add_to_set (psets, gen_rtx_SET (y, CONST_VECTOR_ELT (src, i)));
+ rtx set = gen_rtx_SET (y, CONST_VECTOR_ELT (src, i));
+ add_to_set (psets, set, true);
}
}
else
- add_to_set (psets, x);
+ add_to_set (psets, x, false);
}
else if (GET_CODE (x) == PARALLEL)
{
else if (GET_CODE (SET_SRC (y)) == CALL)
;
else
- add_to_set (psets, y);
+ add_to_set (psets, y, false);
}
}
}
int src_related_regcost = MAX_COST;
int src_elt_regcost = MAX_COST;
scalar_int_mode int_mode;
+ bool is_fake_set = sets[i].is_fake_set;
dest = SET_DEST (sets[i].rtl);
src = SET_SRC (sets[i].rtl);
mode = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
sets[i].mode = mode;
- if (src_eqv)
+ if (!is_fake_set && src_eqv)
{
machine_mode eqvmode = mode;
if (GET_CODE (dest) == STRICT_LOW_PART)
/* If this is a STRICT_LOW_PART assignment, src_eqv corresponds to the
value of the INNER register, not the destination. So it is not
a valid substitution for the source. But save it for later. */
- if (GET_CODE (dest) == STRICT_LOW_PART)
+ if (is_fake_set || GET_CODE (dest) == STRICT_LOW_PART)
src_eqv_here = 0;
else
src_eqv_here = src_eqv;
/* Terminate loop when replacement made. This must terminate since
the current contents will be tested and will always be valid. */
- while (1)
+ while (!is_fake_set)
{
rtx trial;
with the head of the class. If we do not do this, we will have
both registers live over a portion of the basic block. This way,
their lifetimes will likely abut instead of overlapping. */
- if (REG_P (dest)
+ if (!is_fake_set
+ && REG_P (dest)
&& REGNO_QTY_VALID_P (REGNO (dest)))
{
int dest_q = REG_QTY (REGNO (dest));
--- /dev/null
+/* { dg-do compile { target aarch64*-*-* } } */
+/* { dg-options "-O2" } */
+
+extern int data[];
+
+void __RTL (startwith ("vregs")) foo ()
+{
+ (function "foo"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (insn 4 (set (reg:V16QI <0>)
+ (const_vector:V16QI [(const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)])))
+ (insn 5 (set (reg:V2SI v0)
+ (const_vector:V2SI [(const_int 1) (const_int 0)])))
+ (insn 6 (set (reg:V16QI v1)
+ (const_vector:V16QI [(const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)
+ (const_int 0) (const_int 0)
+ (const_int 1) (const_int 1)])))
+ (insn 7 (set (reg:QI x0) (subreg:QI (reg:V16QI <0>) 0))
+ (expr_list:REG_EQUAL (const_int 1) (nil)))
+ (insn 8 (use (reg:V16QI <0>)))
+ (insn 9 (use (reg:V2SI v0)))
+ (insn 10 (use (reg:V16QI v1)))
+ (insn 11 (use (reg:QI x0)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+ ) ;; function
+}