Richard Biener <[email protected]> writes:
> 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,
> only affecting x86 and nvptx at this point.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
>
> OK?

LGTM

> Btw, for the testcase I see aarch64 producing
>
> e:
> .LFB0:
>         .cfi_startproc
>         stp     x29, x30, [sp, -64]!
>         .cfi_def_cfa_offset 64
>         .cfi_offset 29, -64
>         .cfi_offset 30, -56
>         mov     x29, sp
>         add     x0, sp, 47
>         and     x0, x0, -32
>         stp     q0, q1, [x0]
>         bl      __trunctfdf2
>         adrp    x0, .LANCHOR0
>         str     d0, [x0, #:lo12:.LANCHOR0]
>         ldp     x29, x30, [sp], 64
>         .cfi_restore 30
>         .cfi_restore 29
>         .cfi_def_cfa_offset 0
>         ret
>
> so it does seem to dynamically align the stack and we expand
>
> (insn 8 7 9 2 (set (mem/c:TF (reg/f:DI 108) [2 f+0 S16 A256]) 
>         (reg:TF 103)) "t.c":5:13 -1
>      (nil))
> ...
> (insn 15 14 16 2 (set (reg:TF 32 v0)
>         (mem/c:TF (reg/f:DI 108) [1 f.a+0 S16 A256])) "t.c":5:20 -1
>      (nil))
>
> but the port doesn't define MAX_STACK_ALIGNMENTm has STACK_BOUNDARY
> 128 and no PREFERRED_STACK_BOUNDARY.  Doesn't that tell us there's
> some generic code handling large stack allocations?

Yeah, like you said to in the earlier thread, we can individually
allocate things with higher alignment using alloca with padding.
SUPPORTS_STACK_ALIGNMENT is whether we can align the stack pointer
itself to a higher value, and thus use "static" allocation and constant
offsets even for alignments greater than STACK_BOUNDARY.

So perhaps this can indeed be tweaked for !SUPPORTS_STACK_ALIGNMENT
targets.  But any change there should probably be motivated by a
testcase for such a target.  You mentioned in the v1 covering note about
wanting something conservative for this late stage.  The new patch seems
like a good balance to me FWIW.

Thanks,
Richard

>
>       PR middle-end/120839
>       * function.cc (assign_parm_adjust_stack_rtl): 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.
>
>       * gcc.dg/torture/pr120839.c: New testcase.
> ---
>  gcc/function.cc                         | 4 +++-
>  gcc/testsuite/gcc.dg/torture/pr120839.c | 7 +++++++
>  2 files changed, 10 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..5b3018f364e 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -2840,7 +2840,9 @@ 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) < (SUPPORTS_STACK_ALIGNMENT
> +                                        ? MAX_SUPPORTED_STACK_ALIGNMENT
> +                                        : 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; }

Reply via email to