The following fixes a confusion seein 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. I cannot really
make sense of the condition - taking MEM_ALIGN (stack_parm)
as the ABI mandated alignment of the argument stack slot means
that is a lower bound on the incoming stack boundary. But
PREFERRED_STACK_BOUNDARY is not the actual boundary and relating
it to a minimum known boundary to somehow infer known bigger
alignment of the incoming parameter looks odd.
As minimal surgery at this point I'm not removing the condition
but make it include PREFERRED_STACK_BOUNDARY to make the copy
for the testcase in question. Correctness-wise I believe the
condition should be elided.
Alan - you added this check, can you possibly guess what it was
supposed to guard against? Richard H., you approved the change in the
end, what's the reason for the PREFERRED_STACK_BOUNDARY guard? Richard
S., you became involved in the discussion at the end as well.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
OK for trunk?
Thanks,
Richard.
PR middle-end/120839
* function.cc (assign_parm_adjust_stack_rtl): Adjust
alignment check forcing a local copy.
* gcc.dg/torture/pr120839.c: New testcase.
---
gcc/function.cc | 2 +-
gcc/testsuite/gcc.dg/torture/pr120839.c | 7 +++++++
2 files changed, 8 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..e93d12785a5 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -2840,7 +2840,7 @@ 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) <= 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