[gcc r16-9406] x86: Check register argument spill by callee

"H.J. Lu via Gcc-cvs" <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:b73ad535acaa2381bce1edb6f78b7dc65d0d5d1f

commit r16-9406-gb73ad535acaa2381bce1edb6f78b7dc65d0d5d1f
Author: H.J. Lu <[email protected]>
Date:   Mon Jul 20 07:57:31 2026 +0800

    x86: Check register argument spill by callee
    
    commit b4c215b36d63e1c264d8c1bd5d34f9aef1bb8463
    Author: H.J. Lu <[email protected]>
    Date:   Sat Jun 28 06:27:25 2025 +0800
    
        Adjust check for addressable misaligned stack argument
    
    ignores arguments passed on stack since caller is responsible to align
    the outgoing stack for arguments passed on stack.  However, callee may
    spill a register argument:
    
    (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 ]))
    
    Update ix86_argument_passed_on_stack_p to check spill of register argument
    by callee.
    
    gcc/
    
            PR target/126320
            * config/i386/i386.cc (ix86_spill_register_argument_p): New
            function.
            (ix86_argument_passed_on_stack_p): Add a pattern argument.  Call
            ix86_spill_register_argument_p to check spill of register argument
            by callee.
            (ix86_update_stack_alignment): Pass pat to
            ix86_argument_passed_on_stack_p.
    
    gcc/testsuite/
    
            PR target/126320
            * gcc.target/i386/pr126320.c: New test.
    
    Signed-off-by: H.J. Lu <[email protected]>
    Co-Authored-By: Uros Bizjak <[email protected]>
    (cherry picked from commit 26058933d2a23140131b3980908554fc6f8b1f41)

Diff:
---
 gcc/config/i386/i386.cc                  | 53 ++++++++++++++++++++++++++------
 gcc/testsuite/gcc.target/i386/pr126320.c | 45 +++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 2a500e9745ac..6d5258d10f6b 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8625,18 +8625,53 @@ struct stack_access_data
   unsigned int *stack_alignment;
 };
 
-/* Return true if OP references an argument passed on stack.  */
+/* 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);
+
+  return dest == op && reg_expr == base;
+}
+
+/* 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.  */
 
 static bool
-ix86_argument_passed_on_stack_p (const_rtx op)
+ix86_argument_passed_on_stack_p (const_rtx op, const_rtx pat)
 {
   tree mem_expr = MEM_EXPR (op);
-  if (mem_expr)
-    {
-      tree var = get_base_address (mem_expr);
-      return TREE_CODE (var) == PARM_DECL;
-    }
-  return false;
+  if (!mem_expr)
+    return false;
+
+  tree var = get_base_address (mem_expr);
+  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;
 }
 
 /* Update the maximum stack slot alignment from memory alignment in PAT.  */
@@ -8658,7 +8693,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))
+	      && !ix86_argument_passed_on_stack_p (op, pat))
 	    {
 	      unsigned int alignment = MEM_ALIGN (op);
 
diff --git a/gcc/testsuite/gcc.target/i386/pr126320.c b/gcc/testsuite/gcc.target/i386/pr126320.c
new file mode 100644
index 000000000000..cad2205f3c99
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126320.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -march=x86-64" } */
+
+#include <stdint.h>
+
+typedef int64_t v2i64 __attribute__ ((vector_size (16)));
+void *g4, *f3_p2;
+int8_t g15, g23;
+v2i64 g21;
+_Bool g22, f3_c4;
+__attribute__ ((__vector_size__ (16 * sizeof (int)))) int g26;
+int16_t g29;
+
+__attribute__((noipa, noinline, target("avx2")))
+void
+do_test (v2i64 a1)
+{
+  int16_t v3;
+lbl_entry:
+  f3_p2 = &a1;
+  v3 = g29;
+  if (g22)
+    goto lbl_bf4;
+  f3_c4 = v3 - 709;
+  if (f3_c4)
+    return;
+lbl_bf4:
+  g21 = a1;
+  uint8_t __ov_tmp_g15;
+  g15 = __ov_tmp_g15;
+  a1[0] = 0;
+  g26 = g26 == ~g26;
+  g4 = f3_p2;
+  g23 = 0;
+  goto lbl_entry;
+}
+
+int
+main (void)
+{
+ if (__builtin_cpu_supports ("avx2"))
+   do_test (g21);
+
+  return 0;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.