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.
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" } } */
--
2.55.0