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?

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?

        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; }
-- 
2.51.0

Reply via email to