re PR middle-end/59990 (incorrect memcpy optimization)
authorRichard Biener <rguenther@suse.de>
Fri, 31 Jan 2014 11:54:26 +0000 (11:54 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 31 Jan 2014 11:54:26 +0000 (11:54 +0000)
2014-01-31  Richard Biener  <rguenther@suse.de>

PR middle-end/59990
* builtins.c (fold_builtin_memory_op): Make sure to not
use a floating-point mode or a boolean or enumeral type for
the copy operation.

* gcc.dg/torture/pr59990.c: New testcase.

From-SVN: r207338

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr59990.c [new file with mode: 0644]

index 158f2d6a12ee91e698c734ad782704f32d099ae2..bbf6b476f97f63acdb55b7c2bd31a87752ae15e0 100644 (file)
@@ -1,3 +1,10 @@
+2014-01-31  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/59990
+       * builtins.c (fold_builtin_memory_op): Make sure to not
+       use a floating-point mode or a boolean or enumeral type for
+       the copy operation.
+
 2014-01-30  DJ Delorie  <dj@redhat.com>
 
        * config/msp430/msp430.h (LIB_SPEC): Add -lcrt
index a45380ce8776f482f168803c73d29153092e42ab..f5f55bf0e2e60ffb009a4368573ec4fbb165ecd8 100644 (file)
@@ -8851,6 +8851,12 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
       if (!POINTER_TYPE_P (TREE_TYPE (src))
          || !POINTER_TYPE_P (TREE_TYPE (dest)))
        return NULL_TREE;
+      /* In the following try to find a type that is most natural to be
+        used for the memcpy source and destination and that allows
+        the most optimization when memcpy is turned into a plain assignment
+        using that type.  In theory we could always use a char[len] type
+        but that only gains us that the destination and source possibly
+        no longer will have their address taken.  */
       /* As we fold (void *)(p + CST) to (void *)p + CST undo this here.  */
       if (TREE_CODE (src) == POINTER_PLUS_EXPR)
        {
@@ -8886,6 +8892,41 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
          || TREE_ADDRESSABLE (desttype))
        return NULL_TREE;
 
+      /* Make sure we are not copying using a floating-point mode or
+         a type whose size possibly does not match its precision.  */
+      if (FLOAT_MODE_P (TYPE_MODE (desttype))
+         || TREE_CODE (desttype) == BOOLEAN_TYPE
+         || TREE_CODE (desttype) == ENUMERAL_TYPE)
+       {
+         /* A more suitable int_mode_for_mode would return a vector
+            integer mode for a vector float mode or a integer complex
+            mode for a float complex mode if there isn't a regular
+            integer mode covering the mode of desttype.  */
+         enum machine_mode mode = int_mode_for_mode (TYPE_MODE (desttype));
+         if (mode == BLKmode)
+           desttype = NULL_TREE;
+         else
+           desttype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
+                                                      1);
+       }
+      if (FLOAT_MODE_P (TYPE_MODE (srctype))
+         || TREE_CODE (srctype) == BOOLEAN_TYPE
+         || TREE_CODE (srctype) == ENUMERAL_TYPE)
+       {
+         enum machine_mode mode = int_mode_for_mode (TYPE_MODE (srctype));
+         if (mode == BLKmode)
+           srctype = NULL_TREE;
+         else
+           srctype = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode),
+                                                     1);
+       }
+      if (!srctype)
+       srctype = desttype;
+      if (!desttype)
+       desttype = srctype;
+      if (!srctype)
+       return NULL_TREE;
+
       src_align = get_pointer_alignment (src);
       dest_align = get_pointer_alignment (dest);
       if (dest_align < TYPE_ALIGN (desttype)
@@ -8899,29 +8940,6 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
       off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
                                                         ptr_mode, true), 0);
 
-      /* For -fsanitize={bool,enum} make sure the load isn't performed in
-        the bool or enum type.  */
-      if (((flag_sanitize & SANITIZE_BOOL)
-          && TREE_CODE (desttype) == BOOLEAN_TYPE)
-         || ((flag_sanitize & SANITIZE_ENUM)
-             && TREE_CODE (desttype) == ENUMERAL_TYPE))
-       {
-         tree destitype
-           = lang_hooks.types.type_for_mode (TYPE_MODE (desttype),
-                                             TYPE_UNSIGNED (desttype));
-         desttype = build_aligned_type (destitype, TYPE_ALIGN (desttype));
-       }
-      if (((flag_sanitize & SANITIZE_BOOL)
-          && TREE_CODE (srctype) == BOOLEAN_TYPE)
-         || ((flag_sanitize & SANITIZE_ENUM)
-             && TREE_CODE (srctype) == ENUMERAL_TYPE))
-       {
-         tree srcitype
-           = lang_hooks.types.type_for_mode (TYPE_MODE (srctype),
-                                             TYPE_UNSIGNED (srctype));
-         srctype = build_aligned_type (srcitype, TYPE_ALIGN (srctype));
-       }
-
       destvar = dest;
       STRIP_NOPS (destvar);
       if (TREE_CODE (destvar) == ADDR_EXPR
index 435b0556f41d877d4a250fc49c849060b2c0f4f0..87fff131c64e0a0280c2c63b59d1ab8cce87ff96 100644 (file)
@@ -1,3 +1,8 @@
+2014-01-31  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/59990
+       * gcc.dg/torture/pr59990.c: New testcase.
+
 2014-01-31  Jakub Jelinek  <jakub@redhat.com>
 
        * lib/tsan-dg.exp (tsan_init): Try to run a trivial program,
diff --git a/gcc/testsuite/gcc.dg/torture/pr59990.c b/gcc/testsuite/gcc.dg/torture/pr59990.c
new file mode 100644 (file)
index 0000000..e54f9b7
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+unsigned char value[4] = { 66, 9, 160, 255 };
+
+int main (void)
+{
+  volatile float f;
+  unsigned char a[4];
+
+  __builtin_memcpy ((void *)&f, value, 4);
+  __builtin_memcpy (a, (void *)&f, 4);
+  if (a[2] != 160)
+    abort ();
+
+  return 0;
+}