Hi,

This patch is an update to the previous patch, which takes into account that
the middle-end is not supposed to use the unaligned DI value directly which
was passed in an unaligned stack slot due to the AAPCS parameter passing rules.

The patch works by changing use_register_for_decl to return false if the
incoming RTL is not sufficiently aligned on a STRICT_ALIGNMENT target,
as if the address of the parameter was taken (which is TREE_ADDRESSABLE).
So not taking the address of the parameter is a necessary condition
for the wrong-code in PR 89544.

It works together with this check in assign_parm_adjust_stack_rtl:
  /* If we can't trust the parm stack slot to be aligned enough for its
     ultimate type, don't use that slot after entry.  We'll make another
     stack slot, if we need one.  */
  if (stack_parm
      && ((STRICT_ALIGNMENT
           && GET_MODE_ALIGNMENT (data->nominal_mode) > MEM_ALIGN (stack_parm))
...
    stack_param = NULL

This makes assign_parms use assign_parm_setup_stack instead of
assign_parm_setup_reg, and the latter does assign a suitably aligned
stack slot, because stack_param == NULL by now, and uses emit_block_move
which avoids the issue with the back-end.

Additionally, to prevent unnecessary performance regressions,
assign_parm_find_stack_rtl is enhanced to make use of a possible larger
alignment if the parameter was passed in an aligned stack slot without
the ABI requiring it.


Bootstrapped and reg-tested with all languages on arm-linux-gnueabihf.
Is it OK for trunk?


Thanks
Bernd.
2019-03-05  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	PR middle-end/89544
	* function.c (use_register_for_decl): Avoid using unaligned stack
	values on strict alignment targets.
	(assign_parm_find_stack_rtl): Use larger alignment when possible.

testsuite:
2019-03-05  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	PR middle-end/89544
	* gcc.target/arm/unaligned-argument-1.c: New test.
	* gcc.target/arm/unaligned-argument-2.c: New test.

Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 269264)
+++ gcc/function.c	(working copy)
@@ -2210,6 +2210,12 @@ use_register_for_decl (const_tree decl)
   if (DECL_MODE (decl) == BLKmode)
     return false;
 
+  if (STRICT_ALIGNMENT && TREE_CODE (decl) == PARM_DECL
+      && DECL_INCOMING_RTL (decl) && MEM_P (DECL_INCOMING_RTL (decl))
+      && GET_MODE_ALIGNMENT (DECL_MODE (decl))
+	 > MEM_ALIGN (DECL_INCOMING_RTL (decl)))
+    return false;
+
   /* If -ffloat-store specified, don't put explicit float variables
      into registers.  */
   /* ??? This should be checked after DECL_ARTIFICIAL, but tree-ssa
@@ -2698,8 +2704,20 @@ assign_parm_find_stack_rtl (tree parm, struct assi
      intentionally forcing upward padding.  Otherwise we have to come
      up with a guess at the alignment based on OFFSET_RTX.  */
   poly_int64 offset;
-  if (data->locate.where_pad != PAD_DOWNWARD || data->entry_parm)
+  if (data->locate.where_pad == PAD_NONE || data->entry_parm)
     align = boundary;
+  else if (data->locate.where_pad == PAD_UPWARD)
+    {
+      align = boundary;
+      if (poly_int_rtx_p (offset_rtx, &offset)
+	  && STACK_POINTER_OFFSET == 0)
+	{
+	  unsigned int offset_align = known_alignment (offset) * BITS_PER_UNIT;
+	  if (offset_align == 0 || offset_align > STACK_BOUNDARY)
+	    offset_align = STACK_BOUNDARY;
+	  align = MAX (align, offset_align);
+	}
+    }
   else if (poly_int_rtx_p (offset_rtx, &offset))
     {
       align = least_bit_hwi (boundary);
Index: gcc/testsuite/gcc.target/arm/unaligned-argument-1.c
===================================================================
--- gcc/testsuite/gcc.target/arm/unaligned-argument-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/arm/unaligned-argument-1.c	(working copy)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-marm -march=armv6 -mno-unaligned-access -mfloat-abi=soft -mabi=aapcs -O3" } */
+
+struct s {
+  int a, b;
+} __attribute__((aligned(8)));
+
+struct s f0;
+
+void f(int a, int b, int c, int d, struct s f)
+{
+  f0 = f;
+}
+
+/* { dg-final { scan-assembler-times "stmdb" 0 } } */
+/* { dg-final { scan-assembler-times "ldrd\[^\\n\]*\\\[sp\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "ldrd" 1 } } */
+/* { dg-final { scan-assembler-times "strd" 1 } } */
Index: gcc/testsuite/gcc.target/arm/unaligned-argument-2.c
===================================================================
--- gcc/testsuite/gcc.target/arm/unaligned-argument-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/arm/unaligned-argument-2.c	(working copy)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-marm -march=armv6 -mno-unaligned-access -mfloat-abi=soft -mabi=aapcs -O3" } */
+
+struct s {
+  int a, b;
+} __attribute__((aligned(8)));
+
+struct s f0;
+
+void f(int a, int b, int c, int d, int e, struct s f)
+{
+  f0 = f;
+}
+
+/* { dg-final { scan-assembler-times "stmdb" 1 } } */
+/* { dg-final { scan-assembler-times "ldrd\[^\\n\]*\\\[sp\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "ldrd" 1 } } */
+/* { dg-final { scan-assembler-times "strd" 1 } } */

Reply via email to