On Mon, Mar 30, 2026 at 12:28 AM Richard Biener <[email protected]> wrote: > > On Sat, 28 Mar 2026, H.J. Lu wrote: > > > On Sat, Mar 28, 2026 at 1:16 AM Richard Biener <[email protected]> wrote: > > > > > > > > > > > > > Am 28.03.2026 um 03:36 schrieb H.J. Lu <[email protected]>: > > > > > > > > On Fri, Mar 27, 2026 at 4:14 AM Richard Biener <[email protected]> > > > > wrote: > > > >> > > > >> The following fixes a confusion seen in the x86 backend by > > > >> assign_parm_adjust_stack_rtl failing to trigger a local stack copy > > > >> for an incoming stack parameter that is not aligned according to > > > >> its type. The condition was introduced in r0-64961-gbfc45551d5ace4 > > > >> but there is the MEM_ALIGN (stack_parm) < PREFERRED_STACK_BOUNDARY > > > >> condition not triggering for the case in question where both > > > >> MEM_ALIGN and PREFERRED_STACK_BOUNDARY are 128. x86 supports > > > >> stack-realignment so we can honor the declared alignment and this > > > >> clears up the confusion. The following replaces the bound > > > >> by MAX_SUPPORTED_STACK_ALIGNMENT if SUPPORTS_STACK_ALIGNMENT > > > >> and the parameter has it's address taken and with BIGGEST_ALIGNMENT > > > >> if SUPPORTS_STACK_ALIGNMENT otherwise, only affecting x86 and nvptx > > > >> at this point. > > > >> > > > >> In addition to this it changes the i386 backends computation of > > > >> the maximum stack alignment used to bound itself to BIGGEST_ALIGNMENT > > > >> because the middle-end does not (and in general cannot) enforce actual > > > >> alignment of all stack objects according to their type. > > > >> > > > >> Bootstrapped and tested on x86_64-unknown-linux-gnu. > > > >> > > > >> Compared to v2 this uses BIGGEST_ALIGNMENT if the parameter does not > > > >> have its address taken and caps ix86_update_stack_alignment on > > > >> BIGGEST_ALIGNMENT as well. > > > >> > > > >> OK for the x86 parts? I assume the refined function.cc hunk is still > > > >> LGTM from Richard S. side. > > > >> > > > >> Note I still fail to see why we need to scan all insns in the backend > > > >> again after RTL expansion should have ensured to keep track of the > > > >> maximum needed stack alignment. But I'm trying to avoid touching > > > >> code I do not understand as much as possible. > > > >> > > > >> Thanks, > > > >> Richard. > > > >> > > > >> PR middle-end/120839 > > > >> * function.cc (assign_parm_adjust_stack_rtl): Get the parameter > > > >> as arugment. Adjust alignment check forcing a local copy for > > > >> SUPPORTS_STACK_ALIGNMENT targets if the argument is not aligned > > > >> to its type and the current alignment is less than > > > >> MAX_SUPPORTED_STACK_ALIGNMENT if the parameter has its address > > > >> taken or BIGGEST_ALIGNMENT otherwise. > > > >> (assign_parms): Adjust. > > > >> * config/i386/i386.cc (ix86_update_stack_alignment): Bound > > > >> recorded stack alignment requirement by BIGGEST_ALIGNMENT. > > > >> > > > >> * gcc.dg/torture/pr120839.c: New testcase. > > > >> * gcc.target/i386/pr120839-avx.c: Likewise. > > > >> --- > > > >> gcc/config/i386/i386.cc | 2 +- > > > >> gcc/function.cc | 14 +++++++++++--- > > > >> gcc/testsuite/gcc.dg/torture/pr120839.c | 7 +++++++ > > > >> gcc/testsuite/gcc.target/i386/pr120839-avx.c | 8 ++++++++ > > > >> 4 files changed, 27 insertions(+), 4 deletions(-) > > > >> create mode 100644 gcc/testsuite/gcc.dg/torture/pr120839.c > > > >> create mode 100644 gcc/testsuite/gcc.target/i386/pr120839-avx.c > > > >> > > > >> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > > >> index 15e0dd547a9..f2a49bbaf46 100644 > > > >> --- a/gcc/config/i386/i386.cc > > > >> +++ b/gcc/config/i386/i386.cc > > > >> @@ -8627,7 +8627,7 @@ ix86_update_stack_alignment (rtx, const_rtx pat, > > > >> void *data) > > > >> unsigned int alignment = MEM_ALIGN (op); > > > >> > > > >> if (alignment > *p->stack_alignment) > > > >> - *p->stack_alignment = alignment; > > > >> + *p->stack_alignment = MIN (alignment, > > > >> BIGGEST_ALIGNMENT); > > > > > > > > This is wrong. X86 backend supports MAX_OFILE_ALIGNMENT > > > > stack alignment. > > > > > > > >> break; > > > >> } > > > >> else > > > >> diff --git a/gcc/function.cc b/gcc/function.cc > > > >> index bba05f3380d..41987b4f7a4 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,15 @@ 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))) > > > >> + /* When we can re-align the stack ensure appropriate > > > >> alignment > > > >> + of the function local object up to BIGGEST_ALIGNMENT > > > >> if > > > >> + it is only accessed directly or up to the maximum > > > >> supported > > > >> + alignment if the address is exposed. */ > > > >> + && MEM_ALIGN (stack_parm) < (SUPPORTS_STACK_ALIGNMENT > > > >> + ? (TREE_ADDRESSABLE (parm) > > > >> + ? > > > >> MAX_SUPPORTED_STACK_ALIGNMENT > > > >> + : BIGGEST_ALIGNMENT) > > > >> + : > > > >> PREFERRED_STACK_BOUNDARY)))) > > > > > > > > I think it should be > > > > > > > > @@ -2840,7 +2840,11 @@ 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))) > > > > + /* The parm stack slot works if its address isn't taken. When > > > > + making a local copy, MAX_SUPPORTED_STACK_ALIGNMENT is > > > > + its maximum alignment. */ > > > > + && TREE_ADDRESSABLE (parm) > > > > + && MEM_ALIGN (stack_parm) < MAX_SUPPORTED_STACK_ALIGNMENT))) > > > > stack_parm = NULL; > > > > > > Even when not address taken the ABI guaranteed alignment of the stack > > > slot might be less than the declared alignment. If the alignment itself > > > is not exposed via the address we have still to avoid faulting, thus > > > BIGGEST_ALIGNMENT > > > > There should be no fault. Otherwise, caller will fault first when > > such an argument > > is pushed onto stack. > > I don't think this necessarily follows, the caller can end up using memcpy > while portions accessed in the callee can end up using aligned moves. > Also when the ABI effectively requires less alignment the caller has to > avoid using aligned accesses even when the formal alignment of the > argument is bigger. > > All this is about ABI mandated/guaranteed alignment being lower than > the types alignment.
Shouldn't it be decided by backend? > Richard. > > > > > > > > BTW, I opened: > > > > > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124671 > > > > > > > > with a run-time testcase. > > > > > > > > /* If parm was passed in memory, and we need to convert it on entry, > > > > > > > >> stack_parm = NULL; > > > >> > > > >> /* If parm was passed in memory, and we need to convert it on entry, > > > >> @@ -3714,7 +3722,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/torture/pr120839.c > > > >> b/gcc/testsuite/gcc.dg/torture/pr120839.c > > > >> new file mode 100644 > > > >> index 00000000000..158e800649f > > > >> --- /dev/null > > > >> +++ b/gcc/testsuite/gcc.dg/torture/pr120839.c > > > >> @@ -0,0 +1,7 @@ > > > >> +/* { dg-do compile } */ > > > >> + > > > >> +typedef struct { > > > >> + long double a, b; > > > >> +} c __attribute__((aligned(32))); > > > >> +double d; > > > >> +void e(c f) { d = f.a; } > > > >> diff --git a/gcc/testsuite/gcc.target/i386/pr120839-avx.c > > > >> b/gcc/testsuite/gcc.target/i386/pr120839-avx.c > > > >> new file mode 100644 > > > >> index 00000000000..1f5406e065c > > > >> --- /dev/null > > > >> +++ b/gcc/testsuite/gcc.target/i386/pr120839-avx.c > > > >> @@ -0,0 +1,8 @@ > > > >> +/* { dg-do compile } */ > > > >> +/* { dg-options "-O -mavx" } */ > > > >> + > > > >> +typedef struct { > > > >> + long double a, b; > > > >> +} c __attribute__((aligned(32))); > > > >> +double d; > > > >> +void e(c f) { d = f.a; } > > > >> -- > > > >> 2.51.0 > > > > > > > > > > > > > > > > -- > > > > H.J. > > > > > > > > > > -- > Richard Biener <[email protected]> > SUSE Software Solutions Germany GmbH, > Frankenstrasse 146, 90461 Nuernberg, Germany; > GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg) -- H.J.
