&& aarch64_mem_pair_operand (operands[0], DImode))
|| known_eq (GET_MODE_SIZE (<MODE>mode), 8))))
operands[1] = force_reg (<MODE>mode, operands[1]);
+
+ /* If a constant is too complex to force to memory (e.g. because it
+ contains CONST_POLY_INTs), build it up from individual elements instead.
+ We should only need to do this before RA; aarch64_legitimate_constant_p
+ should ensure that we don't try to rematerialize the constant later. */
+ if (GET_CODE (operands[1]) == CONST_VECTOR
+ && targetm.cannot_force_const_mem (<MODE>mode, operands[1]))
+ {
+ aarch64_expand_vector_init (operands[0], operands[1]);
+ DONE;
+ }
"
)
{
/* Support CSE and rematerialization of common constants. */
if (CONST_INT_P (x)
- || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)
- || GET_CODE (x) == CONST_VECTOR)
+ || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
return true;
+ /* Only accept variable-length vector constants if they can be
+ handled directly.
+
+ ??? It would be possible (but complex) to handle rematerialization
+ of other constants via secondary reloads. */
+ if (!GET_MODE_SIZE (mode).is_constant ())
+ return aarch64_simd_valid_immediate (x, NULL);
+
+ /* Otherwise, accept any CONST_VECTOR that, if all else fails, can at
+ least be forced to memory and loaded from there. */
+ if (GET_CODE (x) == CONST_VECTOR)
+ return !targetm.cannot_force_const_mem (mode, x);
+
/* Do not allow vector struct mode constants for Advanced SIMD.
We could support 0 and -1 easily, but they need support in
aarch64-simd.md. */
if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT))
return false;
- /* Only accept variable-length vector constants if they can be
- handled directly.
-
- ??? It would be possible to handle rematerialization of other
- constants via secondary reloads. */
- if (vec_flags & VEC_ANY_SVE)
- return aarch64_simd_valid_immediate (x, NULL);
-
if (GET_CODE (x) == HIGH)
x = XEXP (x, 0);
valid_for_const_vector_p (machine_mode, rtx x)
{
return (CONST_SCALAR_INT_P (x)
+ || CONST_POLY_INT_P (x)
|| CONST_DOUBLE_AS_FLOAT_P (x)
|| CONST_FIXED_P (x));
}
rtx
rtx_vector_builder::apply_step (rtx base, unsigned int factor,
- const wide_int &step) const
+ const poly_wide_int &step) const
{
scalar_int_mode int_mode = as_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
- return immed_wide_int_const (wi::add (rtx_mode_t (base, int_mode),
- factor * step),
+ return immed_wide_int_const (wi::to_poly_wide (base, int_mode)
+ + factor * step,
int_mode);
}
bool equal_p (rtx, rtx) const;
bool allow_steps_p () const;
bool integral_p (rtx) const;
- wide_int step (rtx, rtx) const;
- rtx apply_step (rtx, unsigned int, const wide_int &) const;
+ poly_wide_int step (rtx, rtx) const;
+ rtx apply_step (rtx, unsigned int, const poly_wide_int &) const;
bool can_elide_p (rtx) const { return true; }
void note_representative (rtx *, rtx) {}
/* Return the value of element ELT2 minus the value of element ELT1.
Both elements are known to be CONST_SCALAR_INT_Ps. */
-inline wide_int
+inline poly_wide_int
rtx_vector_builder::step (rtx elt1, rtx elt2) const
{
- return wi::sub (rtx_mode_t (elt2, GET_MODE_INNER (m_mode)),
- rtx_mode_t (elt1, GET_MODE_INNER (m_mode)));
+ return (wi::to_poly_wide (elt2, GET_MODE_INNER (m_mode))
+ - wi::to_poly_wide (elt1, GET_MODE_INNER (m_mode)));
}
#endif
--- /dev/null
+int a;
+short b, c;
+short d(short e, short f) { return e + f; }
+void g(void) {
+ a = -9;
+ for (; a != 51; a = d(a, 5))
+ b |= c;
+}
--- /dev/null
+int a, c;
+char b;
+int d() {
+ a = 0;
+ for (; a <= 21; a = (short)a + 1)
+ b &= c;
+}
--- /dev/null
+/* { dg-options "-O3" } */
+
+int a;
+short b, c;
+short d(short e, short f) { return e + f; }
+void g(void) {
+ a = -9;
+ for (; a != 51; a = d(a, 5))
+ b |= c;
+}
--- /dev/null
+/* { dg-options "-O3" } */
+
+int a, c;
+char b;
+int d() {
+ a = 0;
+ for (; a <= 21; a = (short)a + 1)
+ b &= c;
+}