Since in
typedef int V [[gnu::vector_size (16)]];
long long a, b, c, d, e;
short f;
[[gnu::vector_size (8 * sizeof (int))]] int g;
V h;
_Bool i;
void
foo (V x)
{
_Bool j = 0;
short l = 0;
l1:
b = l;
x = h;
...
}
the register argument, x, is used as local variable, also return true if
spilling an SSA_NAME into an argument-linked memory.
gcc/
PR target/126450
* config/i386/i386.cc (ix86_spill_register_argument_p): Check
the argument-linked memory used to store local variable.
gcc/testsuite/
PR target/126450
* gcc.target/i386/pr126450-1.c: New test.
* gcc.target/i386/pr126450-2.c: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
rtx dest = SET_DEST (set);
tree reg_expr = REG_EXPR (src);
- return dest == op && reg_expr == base;
+ /* If spilling an SSA_NAME into OP, the argument-linked memory is
+ also used to store a local variable. */
+ return dest == op && (reg_expr == base
+ || (reg_expr
+ && TREE_CODE (reg_expr) == SSA_NAME));
}
/* Return true if OP, found in PAT, is a stack argument set up by the
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -march=x86-64" } */
+
+typedef int V [[gnu::vector_size (16)]];
+long long a, b, c, d, e;
+short f;
+[[gnu::vector_size (8 * sizeof (int))]] int g;
+V h;
+_Bool i;
+
+__attribute__((noipa, noinline, target("avx2")))
+void
+foo (V x)
+{
+ _Bool j = 0;
+ short l = 0;
+l1:
+ b = l;
+ x = h;
+ l = c % 4;
+ i = f = e % 6;
+ e = x[j];
+ g = g > g;
+ if (d)
+ goto l2;
+l3:
+ j = l;
+ if (j)
+ goto l1;
+ a = l;
+l2:
+ if (e)
+ goto l3;
+}
+
+int
+main (void)
+{
+ if (__builtin_cpu_supports ("avx2"))
+ foo (h);
+
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int UDItype __attribute__ ((mode (DI)));
+typedef __attribute__ ((aligned)) struct
+{
+ UDItype w[2];
+} UINT128;
+
+UINT128
+__bid128_copySign (UINT128 x)
+{
+ x.w[1] = x.w[1] & 8000000000000000ULL;
+ return x;
+}