Patchwork Fix unaligned access generated by IVOPTS

login
register
mail settings
Submitter Eric Botcazou
Date Sept. 13, 2013, 2:56 p.m.
Message ID <4055194.c4aClY8qGv@polaris>
Download mbox | patch
Permalink /patch/274793/
State New
Headers show

Comments

Eric Botcazou - Sept. 13, 2013, 2:56 p.m.
Hi,

in Ada we can have misaligned array components in record types, that is to say 
object with BLKmode whose alignment is lower than that of their type.  In this 
case IVOPTS can generate misaligned TARGET_MEM_REFs, which will lead to an 
unaligned access on strict-alignment platforms.

Tested on SPARC/Solaris, OK for the mainline?


2013-09-13  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-ssa-loop-ivopts.c (may_be_unaligned_p): Deal with BLKmode as
	the access mode.


2013-09-13  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/loop_optimization17.adb: New test.
	* gnat.dg/loop_optimization17_pkg.ad[sb]: New helper.
Richard Guenther - Sept. 16, 2013, 9:47 a.m.
On Fri, Sep 13, 2013 at 4:56 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> Hi,
>
> in Ada we can have misaligned array components in record types, that is to say
> object with BLKmode whose alignment is lower than that of their type.  In this
> case IVOPTS can generate misaligned TARGET_MEM_REFs, which will lead to an
> unaligned access on strict-alignment platforms.
>
> Tested on SPARC/Solaris, OK for the mainline?

I think that may_be_unaligned_p is just seriously out-dated ... shouldn't it be
sth like

  get_object_alignment_1 (ref, &align, &bitpos);
  if step * BITS_PER_UNIT + bitpos is misaligned
...

or rather all this may_be_unaligned_p stuff should be dropped and IVOPTs
should finally generate proper [TARGET_]MEM_REFs instead?  That is,
we already handle aliasing fine:

  ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff,
                        reference_alias_ptr_type (*use->op_p),
                        iv, base_hint, data->speed);

so just also handle alignment properly by passing down
get_object_alignment (*use->op_p) and in create_mem_ref_raw
do at the end do the

  if (TYPE_MODE (type) != BLKmode
      && GET_MODE_ALIGNMENT (TYPE_MODE (type)) > align)
    type = build_aligned_type (type, align);

for BLKmode we already look at TYPE_ALIGN and as we do not change
the access type(?) either the previous code was already wrong or it was
fine, so there is nothing to do.

So - if you want to give it a try...?

Thanks,
Richard.

> 2013-09-13  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * tree-ssa-loop-ivopts.c (may_be_unaligned_p): Deal with BLKmode as
>         the access mode.
>
>
> 2013-09-13  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * gnat.dg/loop_optimization17.adb: New test.
>         * gnat.dg/loop_optimization17_pkg.ad[sb]: New helper.
>
>
> --
> Eric Botcazou

Patch

Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c	(revision 202431)
+++ tree-ssa-loop-ivopts.c	(working copy)
@@ -1658,7 +1658,7 @@  may_be_unaligned_p (tree ref, tree step)
   tree toffset;
   enum machine_mode mode;
   int unsignedp, volatilep;
-  unsigned base_align;
+  unsigned base_align, align;
 
   /* TARGET_MEM_REFs are translated directly to valid MEMs on the target,
      thus they are not misaligned.  */
@@ -1674,22 +1674,23 @@  may_be_unaligned_p (tree ref, tree step)
   base_align = get_object_alignment (base);
   base_align = MAX (base_align, TYPE_ALIGN (base_type));
 
-  if (mode != BLKmode)
-    {
-      unsigned mode_align = GET_MODE_ALIGNMENT (mode);
-
-      if (base_align < mode_align
-	  || (bitpos % mode_align) != 0
-	  || (bitpos % BITS_PER_UNIT) != 0)
-	return true;
-
-      if (toffset
-	  && (highest_pow2_factor (toffset) * BITS_PER_UNIT) < mode_align)
-	return true;
-
-      if ((highest_pow2_factor (step) * BITS_PER_UNIT) < mode_align)
-	return true;
-    }
+  /* If the mode is BLKmode, then a block move will be used with the
+     alignment of the object's type.  */
+  if (mode == BLKmode)
+    align = TYPE_ALIGN (TREE_TYPE (ref));
+  else
+    align = GET_MODE_ALIGNMENT (mode);
+
+  if (base_align < align
+      || (bitpos % align) != 0
+      || (bitpos % BITS_PER_UNIT) != 0)
+    return true;
+
+  if (toffset && (highest_pow2_factor (toffset) * BITS_PER_UNIT) < align)
+    return true;
+
+  if ((highest_pow2_factor (step) * BITS_PER_UNIT) < align)
+    return true;
 
   return false;
 }