Hi,

this patch fixes misaligned reads through MEM_REFs such as the one in
the testcase which currently fails on both sparc64 and ia64 (again,
the array and the loop are there to cross ia64 cache line and fail
there too).  The patch has to be applied last in the series so that
the current LHS expansion does not attempt to use the new code.

The mechanism is again very similar, except that we call
extract_bit_field instead now.  We do not need to care about the
mem_ref_refers_to_non_mem_p case because that is already handled at
this stage.  On the other hand, messing with complex types actually
breaks currently working testcases such as the one from the previous
patch (I have not really fully investigated what goes on so far but it
genuinely seems to work) so again I punt for complex modes.

There are two more movmisalign_optab generations in this function.
There is the TARGET_MEM_REF case which I intend to piggy-back on in
the same way like MEM_REF is handled in this patch once it leaves the
RFC stage.  Finally, movmisalign_optab is also generated in
VIEW_CONVERT_EXPR case but as far as I understand the code, misaligned
loads are already handled there (only perhaps we should use
SLOW_UNALIGNED_ACCESS instead of STRICT_ALIGNMENT there?).

Thanks,

Martin


2012-02-28  Martin Jambor  <mjam...@suse.cz>

        * expr.c (expand_expr_real_1): handle misaligned scalar reads from
        memory through MEM_REFs by calling extract_bit_field.

        * testsuite/gcc.dg/misaligned-expand-1.c: New test.


Index: src/gcc/expr.c
===================================================================
--- src.orig/gcc/expr.c
+++ src/gcc/expr.c
@@ -9453,21 +9453,29 @@ expand_expr_real_1 (tree exp, rtx target
        if (TREE_THIS_VOLATILE (exp))
          MEM_VOLATILE_P (temp) = 1;
        if (mode != BLKmode
-           && align < GET_MODE_ALIGNMENT (mode)
-           /* If the target does not have special handling for unaligned
-              loads of mode then it can use regular moves for them.  */
-           && ((icode = optab_handler (movmisalign_optab, mode))
-               != CODE_FOR_nothing))
+           && !COMPLEX_MODE_P (mode)
+           && align < GET_MODE_ALIGNMENT (mode))
          {
-           struct expand_operand ops[2];
+           if ((icode = optab_handler (movmisalign_optab, mode))
+               != CODE_FOR_nothing)
+             {
+               struct expand_operand ops[2];
 
-           /* We've already validated the memory, and we're creating a
-              new pseudo destination.  The predicates really can't fail,
-              nor can the generator.  */
-           create_output_operand (&ops[0], NULL_RTX, mode);
-           create_fixed_operand (&ops[1], temp);
-           expand_insn (icode, 2, ops);
-           return ops[0].value;
+               /* We've already validated the memory, and we're creating a
+                  new pseudo destination.  The predicates really can't fail,
+                  nor can the generator.  */
+               create_output_operand (&ops[0], NULL_RTX, mode);
+               create_fixed_operand (&ops[1], temp);
+               expand_insn (icode, 2, ops);
+               return ops[0].value;
+             }
+           else if (!COMPLEX_MODE_P (mode)
+                    && SLOW_UNALIGNED_ACCESS (mode, align))
+             temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
+                                       0, TYPE_UNSIGNED (TREE_TYPE (exp)), 
true,
+                                       (modifier == EXPAND_STACK_PARM
+                                        ? NULL_RTX : target),
+                                       mode, mode);
          }
        return temp;
       }
Index: src/gcc/testsuite/gcc.dg/misaligned-expand-1.c
===================================================================
--- /dev/null
+++ src/gcc/testsuite/gcc.dg/misaligned-expand-1.c
@@ -0,0 +1,41 @@
+/* Test that expand can generate correct loads of misaligned data even on
+   strict alignment platforms.  */
+
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+
+extern void abort ();
+
+typedef unsigned int myint __attribute__((aligned(1)));
+
+unsigned int
+foo (myint *p)
+{
+  return *p;
+}
+
+#define cst 0xdeadbeef
+#define NUM 8
+
+struct blah
+{
+  char c;
+  myint i[NUM];
+};
+
+struct blah g;
+
+int
+main (int argc, char **argv)
+{
+  int i, k;
+  for (k = 0; k < NUM; k++)
+    {
+      g.i[k] = cst;
+      i = foo (&g.i[k]);
+
+      if (i != cst)
+       abort ();
+    }
+  return 0;
+}

Reply via email to