For align == -1, assign_stack_local does not reduce the alignment
according to the size; it rounds the size up to a multiple of
BIGGEST_ALIGNMENT and only caps the alignment at
MAX_SUPPORTED_STACK_ALIGNMENT, which is what the patch records.  The
other reduction in assign_stack_local_2, to stack_alignment_estimated,
only happens once stack realignment has been processed, i.e. not while
expand_builtin_apply allocates the block.

The per-register offsets are not lost either: each restore is made with
adjust_address (result, mode, size), which derives its MEM_ALIGN from
the block's alignment and that offset.  On x86_64 the restores at
offsets 0, 8, 16, 32, 48 and 64 (%rax, %rdx, %st, %st(1), %xmm0, %xmm1)
get A128, A64, A128, A128, A128 and A128.

Or did you mean the size of the block itself, which __builtin_return
only gets as a pointer?  I could pass the alignment from the MEM that
assign_stack_local returns instead of recomputing it, if you prefer.

Thanks,
Igor



________________________________
From: Richard Biener <[email protected]>
Sent: Thursday, October 8, 2026 1:53:29 AM
To: Igor Shevlyakov
Cc: [email protected]; [email protected]
Subject: Re: [PATCH] builtins: Give the __builtin_return result block its real 
alignment [PR112417]

[EXTERNAL] Caution: This email originated from outside of the organization. Do 
not click links or open attachments unless you recognize the sender and know 
the content is safe.

On Wed, 7 Oct 2026, Igor Shevlyakov wrote:

> From: Igor Shevlyakov <[email protected]>
>
> expand_builtin_return wraps the address returned by __builtin_apply in
> a BLKmode MEM with the default MEM_ALIGN of 8 bits, so every
> return-register restore produced by adjust_address is treated as
> byte-aligned.  On strict-alignment targets, or targets whose address
> legitimacy or load/store selection depends on MEM_ALIGN, this picks
> misaligned access sequences or addresses the target cannot handle.
>
> The argument of __builtin_return must be the value returned by
> __builtin_apply, and expand_builtin_apply allocates that block with
> assign_stack_local (..., -1), which aligns it to BIGGEST_ALIGNMENT
> capped at MAX_SUPPORTED_STACK_ALIGNMENT.  Record that alignment on the
> MEM.
>
> The patch attached to the PR goes the other way: it expands each restore
> through expand_misaligned_mem_ref whenever MEM_ALIGN is below the mode's
> alignment.  That only pessimizes valid code: the documentation requires
> the argument of __builtin_return to be a value returned by
> __builtin_apply, and that block always has the alignment recorded here.
> The PR's testcase passes an arbitrary pointer, which is outside that
> contract.

The alignment is actually rounded down according to 'size' but that
size is lost?

>        PR rtl-optimization/112417
>
> gcc/ChangeLog:
>
>        * builtins.cc (expand_builtin_return): Set the alignment of the
>        result block.
>
> gcc/testsuite/ChangeLog:
>
>        * gcc.target/i386/pr112417.c: New test.
>
> Signed-off-by: Igor Shevlyakov <[email protected]>
> ---
> Bootstrapped and regtested on x86_64-pc-linux-gnu (-m32/-m64), no new 
> regressions.
>
>  gcc/builtins.cc                          |  4 ++++
>  gcc/testsuite/gcc.target/i386/pr112417.c | 19 +++++++++++++++++++
>  2 files changed, 23 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr112417.c
>
> diff --git a/gcc/builtins.cc b/gcc/builtins.cc
> index e31947bfed6..b8cad151624 100644
> --- a/gcc/builtins.cc
> +++ b/gcc/builtins.cc
> @@ -1845,6 +1845,10 @@ expand_builtin_return (rtx result)
>
>    apply_result_size ();
>    result = gen_rtx_MEM (BLKmode, result);
> +  /* RESULT was allocated by __builtin_apply with assign_stack_local
> +     (..., -1); record the alignment that gives it.  */
> +  set_mem_align (result, MIN (BIGGEST_ALIGNMENT,
> +                           MAX_SUPPORTED_STACK_ALIGNMENT));
>
>    if (targetm.have_untyped_return ())
>      {
> diff --git a/gcc/testsuite/gcc.target/i386/pr112417.c 
> b/gcc/testsuite/gcc.target/i386/pr112417.c
> new file mode 100644
> index 00000000000..2f60af37284
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr112417.c
> @@ -0,0 +1,19 @@
> +/* PR rtl-optimization/112417 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mno-avx -mtune=generic" } */
> +
> +/* The block returned by __builtin_apply is aligned to BIGGEST_ALIGNMENT,
> +   so __builtin_return can restore the SSE return registers with aligned
> +   loads.  */
> +
> +extern void target (int, double);
> +
> +void
> +fwd (int a, double d)
> +{
> +  void *args = __builtin_apply_args ();
> +  void *ret = __builtin_apply ((void (*) ()) target, args, 64);
> +  __builtin_return (ret);
> +}
> +
> +/* { dg-final { scan-assembler "\tmovdqa\t" } } */
>

--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)


Reply via email to