[gcc r16-9435] x86: Check argument-linked memory used for local variable

"H.J. Lu via Gcc-cvs" <[email protected]> Wed, 29 Jul 2026 20:51:00 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:ad1212765889961594a678912c21c55d1e447679

commit r16-9435-gad1212765889961594a678912c21c55d1e447679
Author: H.J. Lu <[email protected]>
Date:   Wed Jul 29 06:23:57 2026 +0800

    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]>
    (cherry picked from commit ea27cb48a346633d6bfabcde75f88affb9463e40)

Diff:
---
 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(-)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 6d5258d10f6b..4dfb90acf3f6 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8647,7 +8647,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 000000000000..dd5b610ffe75
--- /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 000000000000..778f984d7989
--- /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;
+}