[PATCH] x86: Also check non-local variable for argument-linked memory

"H.J. Lu" <[email protected]> Sat, 1 Aug 2026 11:12:08 +0800
Newsgroups gmane.comp.gcc.patches
Message-ID <CAMe9rOrjyN=9p_o3cWBtCDEB0x=w2vkpMc9KM1h_NfM1r1v03Q@mail.gmail.com>
When checking if a register argument is used as local variable, also
return true if non-local variable is the source of the argument-linked
memory store.

gcc/

PR target/126529
* config/i386/i386.cc (ix86_spill_register_argument_p): Also
check non-local variable source for the argument-linked memory
store.

gcc/testsuite/

PR target/126529
* gcc.target/i386/pr126529.c: New test.


-- 
H.J.
0001-x86-Also-check-non-local-variable-for-argument-linke.patch (text/x-patch, 2.8 KB)
From 20a6efb5bcb6d5fa650554a6fcddff5bd4f82161 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sat, 1 Aug 2026 06:07:43 +0800
Subject: [PATCH] x86: Also check non-local variable for argument-linked memory

When checking if a register argument is used as local variable, also
return true if non-local variable is the source of the argument-linked
memory store.

gcc/

	PR target/126529
	* config/i386/i386.cc (ix86_spill_register_argument_p): Also
	check non-local variable source for the argument-linked memory
	store.

gcc/testsuite/

	PR target/126529
	* gcc.target/i386/pr126529.c: New test.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/config/i386/i386.cc                  | 14 ++++++---
 gcc/testsuite/gcc.target/i386/pr126529.c | 39 ++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126529.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 84dd3d18454..12da479a025 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8631,11 +8631,15 @@ ix86_spill_register_argument_p (const_rtx set, const_rtx op, tree base)
   rtx dest = SET_DEST (set);
   tree reg_expr = REG_EXPR (src);
 
-  /* 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));
+  /* If spilling an SSA_NAME or a non-local variable 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
+		      || (VAR_P (reg_expr)
+			  && !auto_var_in_fn_p
+				(reg_expr, current_function_decl))))));
 }
 
 /* Return true if OP, found in PAT, is a stack argument set up by the
diff --git a/gcc/testsuite/gcc.target/i386/pr126529.c b/gcc/testsuite/gcc.target/i386/pr126529.c
new file mode 100644
index 00000000000..aa53283e5e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126529.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -march=x86-64" } */
+
+typedef signed char A[[gnu::vector_size (2)]];
+typedef short B[[gnu::vector_size (16)]];
+int a, b, c, d;
+B e;
+[[gnu::vector_size(8 * sizeof (int))]] int f;
+_Bool g;
+
+__attribute__((noipa, noinline, target("avx2")))
+void *
+foo (long long x, _Bool y, int z, B w)
+{
+  A h = {};
+  short i = h[z];
+  f = 0 % f;
+  w = e;
+  d = w[g];
+  h = ((union { short s; A t; }) { i }).t;
+  b = 3 / x;
+  h = __builtin_shufflevector (h, h, 3, 2);
+lab:
+  c = h[0];
+  if (y)
+    return 0;
+  y = 1;
+  h = ~h;
+  goto lab;
+}
+
+int
+main (void)
+{
+ if (__builtin_cpu_supports ("avx2"))
+   foo (3355934481768670720LL, 0, a, e);
+
+  return 0;
+}
-- 
2.55.0