On Thu, 26 Mar 2026, Richard Sandiford wrote:
> Richard Biener <[email protected]> writes:
> > The following fixes a confusion seein 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. I cannot really
> > make sense of the condition - taking MEM_ALIGN (stack_parm)
> > as the ABI mandated alignment of the argument stack slot means
> > that is a lower bound on the incoming stack boundary. But
> > PREFERRED_STACK_BOUNDARY is not the actual boundary and relating
> > it to a minimum known boundary to somehow infer known bigger
> > alignment of the incoming parameter looks odd.
>
> I have no memory of this patch, but my reading is that
> PREFERRED_STACK_BOUNDARY is being used as the maximum attainable
> alignment. In other words, there is no point discarding the old
> underaligned stack slot if the new one wouldn't guarantee a
> greater alignment. According to this assumption, GCC's stack
> allocation code wouldn't preserve an alignment greater than
> PREFERRED_STACK_BOUNDARY even if the incoming stack pointer
> happened to be more aligned.
>
> However, this predates the dynamic stack realignment code
> (r0-88648-g2e3f842fe69ce4), so perhaps we should skip the
> PREFERRED_STACK_BOUNDARY check on targets that use that?
>
> E.g. on aarch64, if a type claims to have 32-byte alignment,
> GCC won't try to provide that alignment for arguments passed
> on the stack, whereas x86 will. https://godbolt.org/z/eWjfcoPbb
> is a not very good example. (Not very good because the parameter is
> passed by indirect reference on aarch64. I think the point still
> stands though.)
On x86 it doesn't seem to happen always (as in the PRs testcase).
But I wonder if when the ABI does not guarantee sufficient alignment
of the argument stack slot, and the target does not provide a way
to dynamically increase stack alignment to make the copy destination
properly aligned - what should we do? Don't we want to sorry ()
in that case? Because we have happily assumed the PARM_DECLs
alignment as written.
I had assumed that dynamic stack re-alignment code works everywhere
(where alloca works).
So you're suggesting to replace PREFERRED_STACK_BOUNDARY with
MAX_SUPPORTED_STACK_ALIGNMENT? And <= here.
>
> Changing < to <= doesn't look right for other targets though.
> It's likely to lead to pointless copying.
Why? If the stack can be aligned to PREFERRED_STACK_BOUNDARY
but the ABI misaligns the incoming stack slot we can very well
create a suitably aligned stack slot? So in fact the < is what
is odd in the first place? Shouldn't it be testing
STACK_BOUNDARY and not PREFERRED_STACK_BOUNDARY?
Thanks,
Richard.
>
> Thanks,
> Richard
>
> >
> > As minimal surgery at this point I'm not removing the condition
> > but make it include PREFERRED_STACK_BOUNDARY to make the copy
> > for the testcase in question. Correctness-wise I believe the
> > condition should be elided.
> >
> > Alan - you added this check, can you possibly guess what it was
> > supposed to guard against? Richard H., you approved the change in the
> > end, what's the reason for the PREFERRED_STACK_BOUNDARY guard? Richard
> > S., you became involved in the discussion at the end as well.
> >
> > Bootstrapped and tested on x86_64-unknown-linux-gnu.
> >
> > OK for trunk?
> >
> > Thanks,
> > Richard.
> >
> > PR middle-end/120839
> > * function.cc (assign_parm_adjust_stack_rtl): Adjust
> > alignment check forcing a local copy.
> >
> > * gcc.dg/torture/pr120839.c: New testcase.
> > ---
> > gcc/function.cc | 2 +-
> > gcc/testsuite/gcc.dg/torture/pr120839.c | 7 +++++++
> > 2 files changed, 8 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/testsuite/gcc.dg/torture/pr120839.c
> >
> > diff --git a/gcc/function.cc b/gcc/function.cc
> > index bba05f3380d..e93d12785a5 100644
> > --- a/gcc/function.cc
> > +++ b/gcc/function.cc
> > @@ -2840,7 +2840,7 @@ 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)))
> > stack_parm = NULL;
> >
> > /* If parm was passed in memory, and we need to convert it on entry,
> > 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; }
>
--
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)