]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
x86: Check argument-linked memory used for local variable
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 28 Jul 2026 22:23:57 +0000 (06:23 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 29 Jul 2026 08:12:19 +0000 (16:12 +0800)
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>
gcc/config/i386/i386.cc
gcc/testsuite/gcc.target/i386/pr126450-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr126450-2.c [new file with mode: 0644]

index 33e5e063b991fe589f574527657d77f0b47bdc67..e83402f2c424b70ec5186b0253e954e67c87aaaf 100644 (file)
@@ -8618,7 +8618,11 @@ ix86_spill_register_argument_p (const_rtx set, const_rtx op, tree base)
   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
diff --git a/gcc/testsuite/gcc.target/i386/pr126450-1.c b/gcc/testsuite/gcc.target/i386/pr126450-1.c
new file mode 100644 (file)
index 0000000..dd5b610
--- /dev/null
@@ -0,0 +1,43 @@
+/* { 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;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126450-2.c b/gcc/testsuite/gcc.target/i386/pr126450-2.c
new file mode 100644 (file)
index 0000000..778f984
--- /dev/null
@@ -0,0 +1,15 @@
+/* { 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;
+}