re PR middle-end/29215 (extra store for memcpy)
authorJakub Jelinek <jakub@redhat.com>
Thu, 20 Nov 2008 21:35:03 +0000 (22:35 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 20 Nov 2008 21:35:03 +0000 (22:35 +0100)
PR middle-end/29215
* builtins.c (SLOW_UNALIGNED_ACCESS): Define if not defined.
(fold_builtin_memory_op): Handle even the case where just one
of src and dest is an address of a var decl component, using
TYPE_REF_CAN_ALIAS_ALL pointers.  Remove is_gimple_min_invariant
and readonly_data_expr src check.
* tree-ssa-sccvn.c (DFS): Use clear_and_done_ssa_iter to shut
up warnings.

* trans-array.c (trans_array_constructor_value,
gfc_build_constant_array_constructor): Fill in TREE_PURPOSE.

* gfortran.dg/array_memcpy_3.f90: Adjust pattern to match even
memcpy optimized into ref-all store.
* gcc.dg/pr29215.c: New test.

From-SVN: r142061

gcc/ChangeLog
gcc/builtins.c
gcc/fortran/ChangeLog
gcc/fortran/trans-array.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr29215.c [new file with mode: 0644]
gcc/testsuite/gfortran.dg/array_memcpy_3.f90
gcc/tree-ssa-sccvn.c

index 4b61173..5ef8190 100644 (file)
@@ -1,5 +1,14 @@
 2008-11-20  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/29215
+       * builtins.c (SLOW_UNALIGNED_ACCESS): Define if not defined.
+       (fold_builtin_memory_op): Handle even the case where just one
+       of src and dest is an address of a var decl component, using
+       TYPE_REF_CAN_ALIAS_ALL pointers.  Remove is_gimple_min_invariant
+       and readonly_data_expr src check.
+       * tree-ssa-sccvn.c (DFS): Use clear_and_done_ssa_iter to shut
+       up warnings.
+
        PR rtl-optimization/36998
        * dwarf2out.c (stack_adjust_offset): Add cur_args_size and cur_offset
        arguments.  Handle sp = reg and (set (foo) (mem (pre_inc (reg sp)))).
index fd6d0b8..0e5b834 100644 (file)
@@ -51,6 +51,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "diagnostic.h"
 
+#ifndef SLOW_UNALIGNED_ACCESS
+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
+#endif
+
 #ifndef PAD_VARARGS_DOWN
 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
 #endif
@@ -8824,10 +8828,12 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
   else
     {
       tree srctype, desttype;
+      int src_align, dest_align;
+
       if (endp == 3)
        {
-          int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
-          int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+         src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
+         dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
 
          /* Both DEST and SRC must be pointer types. 
             ??? This is what old code did.  Is the testing for pointer types
@@ -8862,44 +8868,95 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
          || !TYPE_SIZE_UNIT (srctype)
          || !TYPE_SIZE_UNIT (desttype)
          || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
-         || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
-         || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
-         || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
+         || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST)
        return NULL_TREE;
 
-      if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT) 
-         < (int) TYPE_ALIGN (desttype)
-         || (get_pointer_alignment (src, BIGGEST_ALIGNMENT) 
-             < (int) TYPE_ALIGN (srctype)))
+      src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
+      dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+      if (dest_align < (int) TYPE_ALIGN (desttype)
+         || src_align < (int) TYPE_ALIGN (srctype))
        return NULL_TREE;
 
       if (!ignore)
         dest = builtin_save_expr (dest);
 
-      srcvar = build_fold_indirect_ref (src);
-      if (TREE_THIS_VOLATILE (srcvar))
-       return NULL_TREE;
-      if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
-       return NULL_TREE;
-      /* With memcpy, it is possible to bypass aliasing rules, so without
-         this check i.e. execute/20060930-2.c would be misoptimized, because
-        it use conflicting alias set to hold argument for the memcpy call.
-        This check is probably unnecessary with -fno-strict-aliasing.
-        Similarly for destvar.  See also PR29286.  */
-      if (!var_decl_component_p (srcvar)
-         /* Accept: memcpy (*char_var, "test", 1); that simplify
-            to char_var='t';  */
-         || is_gimple_min_invariant (srcvar)
-         || readonly_data_expr (src))
+      srcvar = NULL_TREE;
+      if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
+       {
+         srcvar = build_fold_indirect_ref (src);
+         if (TREE_THIS_VOLATILE (srcvar))
+           srcvar = NULL_TREE;
+         else if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
+           srcvar = NULL_TREE;
+         /* With memcpy, it is possible to bypass aliasing rules, so without
+            this check i.e. execute/20060930-2.c would be misoptimized,
+            because it use conflicting alias set to hold argument for the
+            memcpy call.  This check is probably unnecessary with
+            -fno-strict-aliasing.  Similarly for destvar.  See also
+            PR29286.  */
+         else if (!var_decl_component_p (srcvar))
+           srcvar = NULL_TREE;
+       }
+
+      destvar = NULL_TREE;
+      if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
+       {
+         destvar = build_fold_indirect_ref (dest);
+         if (TREE_THIS_VOLATILE (destvar))
+           destvar = NULL_TREE;
+         else if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
+           destvar = NULL_TREE;
+         else if (!var_decl_component_p (destvar))
+           destvar = NULL_TREE;
+       }
+
+      if (srcvar == NULL_TREE && destvar == NULL_TREE)
        return NULL_TREE;
 
-      destvar = build_fold_indirect_ref (dest);
-      if (TREE_THIS_VOLATILE (destvar))
-       return NULL_TREE;
-      if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
-       return NULL_TREE;
-      if (!var_decl_component_p (destvar))
-       return NULL_TREE;
+      if (srcvar == NULL_TREE)
+       {
+         tree srcptype;
+         if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
+           return NULL_TREE;
+
+         srctype = desttype;
+         if (src_align < (int) TYPE_ALIGN (srctype))
+           {
+             if (AGGREGATE_TYPE_P (srctype)
+                 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
+               return NULL_TREE;
+
+             srctype = build_variant_type_copy (srctype);
+             TYPE_ALIGN (srctype) = src_align;
+             TYPE_USER_ALIGN (srctype) = 1;
+             TYPE_PACKED (srctype) = 1;
+           }
+         srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
+         src = fold_convert (srcptype, src);
+         srcvar = build_fold_indirect_ref (src);
+       }
+      else if (destvar == NULL_TREE)
+       {
+         tree destptype;
+         if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
+           return NULL_TREE;
+
+         desttype = srctype;
+         if (dest_align < (int) TYPE_ALIGN (desttype))
+           {
+             if (AGGREGATE_TYPE_P (desttype)
+                 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
+               return NULL_TREE;
+
+             desttype = build_variant_type_copy (desttype);
+             TYPE_ALIGN (desttype) = dest_align;
+             TYPE_USER_ALIGN (desttype) = 1;
+             TYPE_PACKED (desttype) = 1;
+           }
+         destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
+         dest = fold_convert (destptype, dest);
+         destvar = build_fold_indirect_ref (dest);
+       }
 
       if (srctype == desttype
          || (gimple_in_ssa_p (cfun)
index 1316eb6..941186f 100644 (file)
@@ -1,5 +1,9 @@
 2008-11-20  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/29215
+       * trans-array.c (trans_array_constructor_value,
+       gfc_build_constant_array_constructor): Fill in TREE_PURPOSE.
+
        * trans-intrinsic.c (gfc_conv_intrinsic_minmaxloc): Use
        gfc_index_one_node.
        (gfc_conv_intrinsic_size): Use gfc_index_{zero,one}_node.
index 9c48c42..1385409 100644 (file)
@@ -1235,6 +1235,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
              tree init;
              tree bound;
              tree tmptype;
+             HOST_WIDE_INT idx = 0;
 
              p = c;
              list = NULL_TREE;
@@ -1253,7 +1254,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                                (gfc_get_pchar_type (p->expr->ts.kind),
                                 se.expr);
 
-                 list = tree_cons (NULL_TREE, se.expr, list);
+                 list = tree_cons (build_int_cst (gfc_array_index_type,
+                                                  idx++), se.expr, list);
                  c = p;
                  p = p->next;
                }
@@ -1619,7 +1621,8 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
       if (c->expr->ts.type == BT_CHARACTER && POINTER_TYPE_P (type))
        se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
                                       se.expr);
-      list = tree_cons (NULL_TREE, se.expr, list);
+      list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
+                       se.expr, list);
       c = c->next;
       nelem++;
     }
index 6eaad34..3a767f1 100644 (file)
@@ -1,3 +1,10 @@
+2008-11-20  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/29215
+       * gfortran.dg/array_memcpy_3.f90: Adjust pattern to match even
+       memcpy optimized into ref-all store.
+       * gcc.dg/pr29215.c: New test.
+
 2008-11-19  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/38151
diff --git a/gcc/testsuite/gcc.dg/pr29215.c b/gcc/testsuite/gcc.dg/pr29215.c
new file mode 100644 (file)
index 0000000..aa3f82c
--- /dev/null
@@ -0,0 +1,33 @@
+/* PR middle-end/29215 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple" } */
+
+char buf[5 * sizeof (int) + 1] __attribute__((aligned (__alignof__ (int))));
+
+static void
+foo (int arg1, int arg2, int arg3, int arg4, int arg5)
+{
+  __builtin_memcpy (buf, &arg1, sizeof (int));
+  __builtin_memcpy (buf + sizeof (int), &arg2, sizeof (int));
+  __builtin_memcpy (buf + 2 * sizeof (int), &arg3, sizeof (int));
+  __builtin_memcpy (buf + 3 * sizeof (int), &arg4, sizeof (int));
+  __builtin_memcpy (buf + 4 * sizeof (int), &arg5, sizeof (int));
+}
+
+int
+main (void)
+{
+  union { char buf[4]; int i; } u;
+  u.i = 0;
+  u.buf[0] = 'a';
+  u.buf[1] = 'b';
+  u.buf[2] = 'c';
+  u.buf[3] = 'd';
+  foo (u.i, u.i, u.i, u.i, u.i);
+  buf[5 * sizeof (int)] = '\0';
+  __builtin_puts (buf);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "memcpy" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
index 0591587..df6bd49 100644 (file)
@@ -11,5 +11,5 @@ subroutine bar(x)
   x = (/ 3, 1, 4, 1 /)
 end subroutine
 
-! { dg-final { scan-tree-dump-times "memcpy" 2 "original" } }
+! { dg-final { scan-tree-dump-times "memcpy|ref-all" 2 "original" } }
 ! { dg-final { cleanup-tree-dump "original" } }
index 80f7a92..e40681f 100644 (file)
@@ -2654,7 +2654,7 @@ start_over:
        usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
     }
   else
-    iter.done = true;
+    clear_and_done_ssa_iter (&iter);
 
   while (1)
     {