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