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.


-- 
H.J.
From 1a6b15cc09445a28ce9be3be4ae41da6e595ae34 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Wed, 29 Jul 2026 06:23:57 +0800
Subject: [PATCH] x86: Check argument-linked memory used for local variable

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 <[email protected]>
---
 gcc/config/i386/i386.cc                    |  6 ++-
 gcc/testsuite/gcc.target/i386/pr126450-1.c | 43 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126450-2.c | 15 ++++++++
 3 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126450-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126450-2.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index ae3a9ad595e..9f1d4b32ccc 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8631,7 +8631,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
index 00000000000..dd5b610ffe7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126450-1.c
@@ -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
index 00000000000..778f984d798
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126450-2.c
@@ -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;
+}
-- 
2.55.0

Reply via email to