[gcc r16-8339] Adjust check for addressable misaligned stack argument
H.J. Lu
hjl@gcc.gnu.org
Mon Mar 30 22:50:16 GMT 2026
https://gcc.gnu.org/g:b4c215b36d63e1c264d8c1bd5d34f9aef1bb8463
commit r16-8339-gb4c215b36d63e1c264d8c1bd5d34f9aef1bb8463
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat Jun 28 06:27:25 2025 +0800
Adjust check for addressable misaligned stack argument
Adjust alignment check forcing a local copy if the argument on stack is
not aligned to its type and the current alignment, which is determined
by the backend, is less than MAX_SUPPORTED_STACK_ALIGNMENT when the
parameter has its address taken.
For x86, ignore argument passed on stack when updating stack alignment
since caller is responsible to align the outgoing stack for arguments
passed on stack.
gcc/
PR target/120839
PR middle-end/124671
* function.cc (assign_parm_adjust_stack_rtl): Get the parameter
as argument. Adjust alignment check forcing a local copy.
(assign_parms): Adjust.
* config/i386/i386.cc (ix86_argument_passed_on_stack_p): New.
(ix86_update_stack_alignment): Ignore argument passed on stack.
gcc/testsuite/
PR target/120839
PR middle-end/124671
* gcc.dg/pr124671.c: New test.
* gcc.target/i386/pr120839-1a.c: Likewise.
* gcc.target/i386/pr120839-1b.c: Likewise.
* gcc.target/i386/pr120839-2.c: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Co-Authored-By: Richard Biener <rguenther@suse.de>
Diff:
---
gcc/config/i386/i386.cc | 20 ++++++++++++++++-
gcc/function.cc | 12 +++++++---
gcc/testsuite/gcc.dg/pr124671.c | 34 +++++++++++++++++++++++++++++
gcc/testsuite/gcc.target/i386/pr120839-1a.c | 15 +++++++++++++
gcc/testsuite/gcc.target/i386/pr120839-1b.c | 5 +++++
gcc/testsuite/gcc.target/i386/pr120839-2.c | 19 ++++++++++++++++
6 files changed, 101 insertions(+), 4 deletions(-)
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 15e0dd547a9c..3f7fe0bcf0cc 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8607,6 +8607,20 @@ struct stack_access_data
unsigned int *stack_alignment;
};
+/* Return true if OP references an argument passed on stack. */
+
+static bool
+ix86_argument_passed_on_stack_p (const_rtx op)
+{
+ tree mem_expr = MEM_EXPR (op);
+ if (mem_expr)
+ {
+ tree var = get_base_address (mem_expr);
+ return TREE_CODE (var) == PARM_DECL;
+ }
+ return false;
+}
+
/* Update the maximum stack slot alignment from memory alignment in PAT. */
static void
@@ -8622,7 +8636,11 @@ ix86_update_stack_alignment (rtx, const_rtx pat, void *data)
auto op = *iter;
if (MEM_P (op))
{
- if (reg_mentioned_p (p->reg, XEXP (op, 0)))
+ /* NB: Ignore arguments passed on stack since caller is
+ 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))
{
unsigned int alignment = MEM_ALIGN (op);
diff --git a/gcc/function.cc b/gcc/function.cc
index bba05f3380dd..46c0d8b54c2f 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -2825,7 +2825,7 @@ assign_parm_remove_parallels (struct assign_parm_data_one *data)
always valid and properly aligned. */
static void
-assign_parm_adjust_stack_rtl (struct assign_parm_data_one *data)
+assign_parm_adjust_stack_rtl (tree parm, struct assign_parm_data_one *data)
{
rtx stack_parm = data->stack_parm;
@@ -2840,7 +2840,13 @@ assign_parm_adjust_stack_rtl (struct assign_parm_data_one *data)
MEM_ALIGN (stack_parm))))
|| (data->nominal_type
&& TYPE_ALIGN (data->nominal_type) > MEM_ALIGN (stack_parm)
- && MEM_ALIGN (stack_parm) < PREFERRED_STACK_BOUNDARY)))
+ && (MEM_ALIGN (stack_parm) < PREFERRED_STACK_BOUNDARY
+ /* If its address is taken, make a local copy whose
+ maximum alignment is MAX_SUPPORTED_STACK_ALIGNMENT.
+ */
+ || (TREE_ADDRESSABLE (parm)
+ && (MEM_ALIGN (stack_parm)
+ < MAX_SUPPORTED_STACK_ALIGNMENT))))))
stack_parm = NULL;
/* If parm was passed in memory, and we need to convert it on entry,
@@ -3714,7 +3720,7 @@ assign_parms (tree fndecl)
else
set_decl_incoming_rtl (parm, data.entry_parm, false);
- assign_parm_adjust_stack_rtl (&data);
+ assign_parm_adjust_stack_rtl (parm, &data);
if (assign_parm_setup_block_p (&data))
assign_parm_setup_block (&all, parm, &data);
diff --git a/gcc/testsuite/gcc.dg/pr124671.c b/gcc/testsuite/gcc.dg/pr124671.c
new file mode 100644
index 000000000000..339757f849e9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr124671.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target automatic_stack_alignment } } */
+/* { dg-options "-O2" } */
+
+#define ALIGNMENT 256
+
+#include <stddef.h>
+
+typedef struct {
+ long double a;
+ long double b;
+} c __attribute__((aligned(ALIGNMENT)));
+
+__attribute__ ((noipa))
+void foo (c *p)
+{
+ if ((((ptrdiff_t) p) & (ALIGNMENT - 1)) != 0)
+ __builtin_abort ();
+}
+
+__attribute__ ((noipa))
+void
+bar (c f)
+{
+ foo (&f);
+}
+
+c f;
+
+int
+main()
+{
+ bar (f);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120839-1a.c b/gcc/testsuite/gcc.target/i386/pr120839-1a.c
new file mode 100644
index 000000000000..34d4d4271e24
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120839-1a.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-32,\[\\t \]*%\[re\]?sp" { xfail ia32 } } } */
+
+typedef struct
+{
+ long double a;
+ long double b;
+} c __attribute__((aligned(32)));
+extern double d;
+void
+bar (c f)
+{
+ d = f.a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120839-1b.c b/gcc/testsuite/gcc.target/i386/pr120839-1b.c
new file mode 100644
index 000000000000..d9dafc19afb7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120839-1b.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2" } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-32,\[\\t \]*%\[re\]?sp" { xfail ia32 } } } */
+
+#include "pr120839-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr120839-2.c b/gcc/testsuite/gcc.target/i386/pr120839-2.c
new file mode 100644
index 000000000000..e5b711c966fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120839-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-32,\[\\t \]*%\[re\]?sp" } } */
+
+typedef struct
+{
+ long double a;
+ long double b;
+} c __attribute__((aligned(32)));
+extern c x;
+extern double d;
+extern void bar (c);
+void
+foo (void)
+{
+ x.a = d;
+ x.b = d;
+ bar (x);
+}
More information about the Gcc-cvs
mailing list