[PATCH v2] x86: Check DECL_INCOMING_RTL for argument passing check

"H.J. Lu" <[email protected]> Sun, 2 Aug 2026 14:33:21 +0800
Newsgroups gmane.comp.gcc.patches
Message-ID <CAMe9rOrzNtocAyFi=-ULpxHOS3XuUZ48yxSsKg=CR2tfXN-WZQ@mail.gmail.com>
On Sat, Aug 1, 2026 at 4:49 PM Uros Bizjak <[email protected]> wrote:
>
> On Sat, Aug 1, 2026 at 5:12 AM H.J. Lu <[email protected]> wrote:
> >
> > 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.
>
> This is the third patch in the same area, so it IMO points to a more
> systematic issue. Please find someone else that is able to thoroughly
> review the patch (and the core issue that lies behind these problems)
> from the generic middle-end side of the compiler.
>
> Uros.

Here is the v2 patch to check the argument's  DECL_INCOMING_RTL
instead.

--
H.J.
---
If an argument's DECL_INCOMING_RTL is a memory operand, it is passed on
stack by caller.  Change ix86_argument_passed_on_stack_p to return true
if the argument's DECL_INCOMING_RTL is a memory operand.

gcc/

PR target/126529
PR target/126450
PR target/126320
* config/i386/i386.cc (ix86_spill_register_argument_p): Removed.
(ix86_argument_passed_on_stack_p): Remove the second argument.
Return true if the argument's DECL_INCOMING_RTL is a memory
operand.
(ix86_update_stack_alignment): Updated.

gcc/testsuite/

PR target/126529
PR target/126450
PR target/126320
* gcc.target/i386/pr126529-1.c: New test.
* gcc.target/i386/pr126529-2.c: Likewise.
* gcc.target/i386/pr126529-3.c: Likewise.
* gcc.target/i386/pr126529-4.c: Likewise.


-- 
H.J.
v2-0001-x86-Check-DECL_INCOMING_RTL-for-argument-passing-.patch (application/x-patch, 8.4 KB)
From 8d28655d110e3beb6f080233ae895e32ebb03afc Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sat, 1 Aug 2026 06:07:43 +0800
Subject: [PATCH v2] x86: Check DECL_INCOMING_RTL for argument passing check

If an argument's DECL_INCOMING_RTL is a memory operand, it is passed on
stack by caller.  Change ix86_argument_passed_on_stack_p to return true
if the argument's DECL_INCOMING_RTL is a memory operand.

gcc/

	PR target/126529
	PR target/126450
	PR target/126320
	* config/i386/i386.cc (ix86_spill_register_argument_p): Removed.
	(ix86_argument_passed_on_stack_p): Remove the second argument.
	Return true if the argument's DECL_INCOMING_RTL is a memory
	operand.
	(ix86_update_stack_alignment): Updated.

gcc/testsuite/

	PR target/126529
	PR target/126450
	PR target/126320
	* gcc.target/i386/pr126529-1.c: New test.
	* gcc.target/i386/pr126529-2.c: Likewise.
	* gcc.target/i386/pr126529-3.c: Likewise.
	* gcc.target/i386/pr126529-4.c: Likewise.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/config/i386/i386.cc                    | 46 +++-------------------
 gcc/testsuite/gcc.target/i386/pr126529-1.c | 39 ++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126529-2.c | 40 +++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126529-3.c | 32 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr126529-4.c | 33 ++++++++++++++++
 5 files changed, 149 insertions(+), 41 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126529-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126529-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126529-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126529-4.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 84dd3d18454..d3778da9862 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8609,42 +8609,10 @@ struct stack_access_data
   unsigned int *stack_alignment;
 };
 
-/* SET stores into OP, a MEM linked to parameter BASE.  Return true if
-   SET stores BASE's argument register into OP.  This is a spill: the
-   callee saves its own register argument to the stack.  It is not a
-   stack argument set up by the caller:
-
-     (set (mem/c:V2DI (plus:DI (reg/f:DI 7 sp)
-		(const_int -16 [0xfffffffffffffff0])) [4 a1+0 S16 A128])
-	  (reg:V2DI 20 xmm0 [ a1 ]))
- */
-
-static bool
-ix86_spill_register_argument_p (const_rtx set, const_rtx op, tree base)
-{
-  rtx src = SET_SRC (set);
-
-  /* Not a hard register store, so not a spill.  */
-  if (!REG_P (src) || !HARD_REGISTER_P (src))
-    return false;
-
-  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));
-}
-
-/* Return true if OP, found in PAT, is a stack argument set up by the
-   caller.  Return false if OP is a register argument that the callee
-   spilled to its own stack frame.  Both cases share the same MEM_EXPR,
-   so we must check PAT to tell them apart.  */
+/* Return true if OP is a stack argument set up by the caller.  */
 
 static bool
-ix86_argument_passed_on_stack_p (const_rtx op, const_rtx pat)
+ix86_argument_passed_on_stack_p (const_rtx op)
 {
   tree mem_expr = MEM_EXPR (op);
   if (!mem_expr)
@@ -8654,12 +8622,8 @@ ix86_argument_passed_on_stack_p (const_rtx op, const_rtx pat)
   if (TREE_CODE (var) != PARM_DECL)
     return false;
 
-  /* PAT is always a single SET here: note_stores splits PARALLEL
-     patterns into separate SETs before calling this function.  */
-  if (GET_CODE (pat) == SET)
-    return !ix86_spill_register_argument_p (pat, op, var);
-
-  return true;
+  /* Return true if OP is passed in memory.  */
+  return MEM_P (DECL_INCOMING_RTL (var));
 }
 
 /* Update the maximum stack slot alignment from memory alignment in PAT.  */
@@ -8681,7 +8645,7 @@ ix86_update_stack_alignment (rtx, const_rtx pat, void *data)
 	     responsible to align the outgoing stack for arguments
 	     passed on stack.  */
 	  if (reg_mentioned_p (p->reg, XEXP (op, 0))
-	      && !ix86_argument_passed_on_stack_p (op, pat))
+	      && !ix86_argument_passed_on_stack_p (op))
 	    {
 	      unsigned int alignment = MEM_ALIGN (op);
 
diff --git a/gcc/testsuite/gcc.target/i386/pr126529-1.c b/gcc/testsuite/gcc.target/i386/pr126529-1.c
new file mode 100644
index 00000000000..aa53283e5e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126529-1.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;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126529-2.c b/gcc/testsuite/gcc.target/i386/pr126529-2.c
new file mode 100644
index 00000000000..d37c0bf5997
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126529-2.c
@@ -0,0 +1,40 @@
+/* { 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 (float f1, float f2, float f3, float f4, float f5, float f6, float f7,
+     float f8, 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 (1, 2, 3, 4, 5, 6, 7, 8, 3355934481768670720LL, 0, a, e);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126529-3.c b/gcc/testsuite/gcc.target/i386/pr126529-3.c
new file mode 100644
index 00000000000..740b21b1b28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126529-3.c
@@ -0,0 +1,32 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -march=x86-64-v3" } */
+/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]+\\$-32,\[\\t \]*%\[re\]?sp" } } */
+/* { dg-final { scan-assembler "vmovdqa\[\\t \]+%ymm" } } */
+
+typedef signed char A[[gnu::vector_size (2)]];
+typedef short B[[gnu::vector_size (32)]];
+int a, b, c, d;
+B e;
+[[gnu::vector_size(8 * sizeof (int))]] int f;
+_Bool g;
+
+[[gnu::noipa]] void *
+foo (float f1, float f2, float f3, float f4, float f5, float f6, float f7,
+     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;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126529-4.c b/gcc/testsuite/gcc.target/i386/pr126529-4.c
new file mode 100644
index 00000000000..2c08d56ca23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126529-4.c
@@ -0,0 +1,33 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -march=x86-64-v3" } */
+/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]+\\$-32,\[\\t \]*%\[re\]?sp" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]+\\$-32,\[\\t \]*%\[re\]?sp" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "vmovdqa\[\\t \]+%ymm" } } */
+
+typedef signed char A[[gnu::vector_size (2)]];
+typedef short B[[gnu::vector_size (32)]];
+int a, b, c, d;
+B e;
+[[gnu::vector_size(8 * sizeof (int))]] int f;
+_Bool g;
+
+[[gnu::noipa]] void *
+foo (float f1, float f2, float f3, float f4, float f5, float f6, float f7,
+     float f8, 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;
+}
-- 
2.55.0