On Fri, Jul 4, 2025 at 9:33 AM H.J. Lu <hjl.to...@gmail.com> wrote:
>
> On Fri, Jul 4, 2025 at 2:37 PM Richard Sandiford
> <richard.sandif...@arm.com> wrote:
> >
> > "H.J. Lu" <hjl.to...@gmail.com> writes:
> > > On Thu, Jul 3, 2025 at 11:02 PM Richard Sandiford
> > > <richard.sandif...@arm.com> wrote:
> > >>
> > >> "H.J. Lu" <hjl.to...@gmail.com> writes:
> > >> > Since a backend may ignore user type alignment for arguments passed on
> > >> > stack, update alignment for arguments passed on stack when copying 
> > >> > MEM's
> > >> > memory attributes.
> > >> >
> > >> > gcc/
> > >> >
> > >> > PR target/120839
> > >> > * emit-rtl.cc (set_mem_attrs): Update alignment for argument on
> > >> > stack.
> > >> >
> > >> > gcc/testsuite/
> > >> >
> > >> > PR target/120839
> > >> > * gcc.target/i386/pr120839-1.c: New test.
> > >> > * gcc.target/i386/pr120839-2.c: Likewise.
> > >> >
> > >> >
> > >> > --
> > >> > H.J.
> > >> >
> > >> > From 3f8a9bfb4beae47bfc0da20b517a5b3b06a1cbcc Mon Sep 17 00:00:00 2001
> > >> > From: "H.J. Lu" <hjl.to...@gmail.com>
> > >> > Date: Sat, 28 Jun 2025 06:27:25 +0800
> > >> > Subject: [PATCH] Update alignment for argument on stack
> > >> >
> > >> > Since a backend may ignore user type alignment for arguments passed on
> > >> > stack, update alignment for arguments passed on stack when copying 
> > >> > MEM's
> > >> > memory attributes.
> > >> >
> > >> > gcc/
> > >> >
> > >> >       PR target/120839
> > >> >       * emit-rtl.cc (set_mem_attrs): Update alignment for argument on
> > >> >       stack.
> > >> >
> > >> > gcc/testsuite/
> > >> >
> > >> >       PR target/120839
> > >> >       * gcc.target/i386/pr120839-1.c: New test.
> > >> >       * gcc.target/i386/pr120839-2.c: Likewise.
> > >> >
> > >> > Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
> > >> > ---
> > >> >  gcc/emit-rtl.cc                            | 14 ++++++++++++++
> > >> >  gcc/testsuite/gcc.target/i386/pr120839-1.c | 14 ++++++++++++++
> > >> >  gcc/testsuite/gcc.target/i386/pr120839-2.c | 19 +++++++++++++++++++
> > >> >  3 files changed, 47 insertions(+)
> > >> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr120839-1.c
> > >> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr120839-2.c
> > >> >
> > >> > diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> > >> > index f4fc92bb37a..0d1616361ca 100644
> > >> > --- a/gcc/emit-rtl.cc
> > >> > +++ b/gcc/emit-rtl.cc
> > >> > @@ -389,6 +389,20 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
> > >> >      {
> > >> >        MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
> > >> >        memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
> > >> > +      if (MEM_EXPR (mem))
> > >> > +     {
> > >> > +       tree base_address = get_base_address (MEM_EXPR (mem));
> > >> > +       if (base_address && TREE_CODE (base_address) == PARM_DECL)
> > >> > +         {
> > >> > +           /* User alignment on type may be ignored for parameter
> > >> > +              passed on stack.  */
> > >> > +           tree type = TREE_TYPE (base_address);
> > >> > +           unsigned int alignment
> > >> > +             = targetm.calls.function_arg_boundary (TYPE_MODE (type),
> > >> > +                                                    type);
> > >> > +           set_mem_align (mem, alignment);
> > >> > +         }
> > >> > +     }
> > >> >      }
> > >> >  }
> > >>
> > >> This doesn't feel like the right place to address this.  set_mem_attrs
> > >> is just supposed to install the attributes that it has been given,
> > >> without second-guessing the contents.
> > >>
> > >> Where does the incorrect alignment ultimately come from?  (As in,
> > >> which piece of code creates the MEM and fails to give it the correct
> > >> alignment?)
> > >
> > > x86 has
> > >
> > > static unsigned int
> > > ix86_function_arg_boundary (machine_mode mode, const_tree type)
> > > {
> > >   unsigned int align;
> > >   if (type)
> > >     {
> > >       /* Since the main variant type is used for call, we convert it to
> > >          the main variant type.  */
> > >       type = TYPE_MAIN_VARIANT (type);
> > >       align = TYPE_ALIGN (type);
> > >       if (TYPE_EMPTY_P (type))
> > >         return PARM_BOUNDARY;
> > >     }
> > >
> > > Because of
> > >
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120900
> > >
> > > for C,
> > >
> > > typedef struct {
> > >   long double a, b
> > > } c __attribute__((aligned(32)));
> > >
> > > when such a variable is passed on stack, its alignment
> > > on stack is 16, not 32.  However, when set_mem_attrs
> >                                     ^^^^^^^^^^^^^^^^^^
> > > is called to set MEM_ALIGN for such a variable on stack,
> >   ^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > it sets MEM_ALIGN to 32, instead of 16.
> >
> > But what I meant was: which piece of code calls set_mem_attrs
> > to set MEM_ALIGN in this case?  The bug seems further up the
> > call stack to me.
> >
>
> Breakpoint 1, set_mem_attrs (mem=0x7fffe9605510, attrs=0x7fffffffccd0)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:381
> 381   if (mem_attrs_eq_p (attrs, mode_mem_attrs[(int) GET_MODE (mem)]))
> (gdb) bt
> #0  set_mem_attrs (mem=0x7fffe9605510, attrs=0x7fffffffccd0)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:381
> #1  0x00000000008096d3 in set_mem_attributes_minus_bitpos (ref=0x7fffe9605510,
>     t=0x7fffe9810bb0, objectp=1, bitpos=...)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:2191
> #2  0x0000000000809729 in set_mem_attributes (ref=0x7fffe9605510,
>     t=0x7fffe9810bb0, objectp=1)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:2197
> #3  0x000000000090d1a6 in assign_parm_find_stack_rtl (parm=0x7fffe9810bb0,
>     data=0x7fffffffcee0)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/function.cc:2681
> #4  0x0000000000911278 in assign_parms (fndecl=0x7fffe99d2900)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/function.cc:3691
> #5  0x0000000000915be8 in expand_function_start (subr=0x7fffe99d2900)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/function.cc:5201
> #6  0x00000000006c5b6b in (anonymous namespace)::pass_expand::execute (
>     this=0x486c0e0, fun=0x7ffff7fbc190)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/cfgexpand.cc:7168
> #7  0x0000000000d02703 in execute_one_pass (pass=0x486c0e0)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/passes.cc:2648
> #8  0x0000000000d02afb in execute_pass_list_1 (pass=0x486c0e0)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/passes.cc:2757
> ...
> (gdb) call debug (mem)
> (mem/c:BLK (reg/f:DI 92 virtual-incoming-args) [0  A8])
> (gdb) f 1
> #1  0x00000000008096d3 in set_mem_attributes_minus_bitpos (ref=0x7fffe9605510,
>     t=0x7fffe9810bb0, objectp=1, bitpos=...)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:2191
> 2191   set_mem_attrs (ref, &attrs);
> (gdb) p attrs
> $2 = {expr = 0x7fffe9810bb0, offset = {coeffs = {0}}, size = {coeffs = {32}},
>   alias = 2, align = 256, addrspace = 0 '\000', offset_known_p = true,
>   size_known_p = true}
> (gdb)
> Breakpoint 2, set_mem_attributes_minus_bitpos (ref=0x7fffe9605510,
>     t=0x7fffe9810bb0, objectp=1, bitpos=...)
>     at /export/gnu/import/git/gitlab/x86-gcc-test/gcc/emit-rtl.cc:2163
> 2163       get_object_alignment_1 (t, &obj_align, &obj_bitpos);
> (gdb) next
> 2164       unsigned int diff_align = known_alignment (obj_bitpos - bitpos);
> (gdb)
> 2165       if (diff_align != 0)
> (gdb) p obj_align
> $3 = 256
> (gdb)
> (gdb) next
> 2167       attrs.align = MAX (attrs.align, obj_align);
> (gdb) p attrs.align
> $4 = 256
> (gdb)
>
> 256 is wrong only because
>
> typedef struct {
>   long double a;
>   long double b;
> } c __attribute__((aligned(32)));
>
> is passed on stack.
>
> The problems are in get_object_alignment_2 and 
> set_mem_attributes_minus_bitpos.

I think the problem is that the IL doesn't reflect reality.  When the PARM_DECL
(or its type) has the specified alignment that has to reflect reality.  Consider

void foo (c x)
{
   __typeof (x) *tem = &x;
   x->a;
}

when the target doesn't honor the alignment of 'x' then the accesses
based off 'tem'
will be wrong.

The middle-end has, in similar cases, the "fix" for such bad backends
to generate a
callee copy for the incoming argument (with insufficient alignment) to
a local stack
variable with (sufficient alignment).  Why is that not triggering here?

> Here is the v2 patch:
>
> Since a backend may ignore user type alignment for arguments passed on
> stack, call targetm.calls.function_arg_boundary to get alignment of
> parameter on stack and don't increase it.
>
> gcc/
>
> PR target/120839
> * builtins.cc (get_object_alignment_2): Call
> targetm.calls.function_arg_boundary to get alignment of
> parameter on stack.
> * emit-rtl.cc (set_mem_attributes_minus_bitpos): Don't
> increase alignment of parameter passed on stack.
>
> gcc/testsuite/
>
> PR target/120839
> * gcc.target/i386/pr120839-1.c: New test.
> * gcc.target/i386/pr120839-2.c: Likewise.
>
> --
> H.J.

Reply via email to