aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-01-31 11:54:26 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-01-31 11:54:26 +0000
commitfdfd537bcb069aacb9921c0567edcef7cf4cfbae (patch)
tree10490efcd99d7b2f362558ef38f3c6b16634e18f
parent798888a05059cba666420de3607e19efab36b123 (diff)
downloadgcc-fdfd537bcb069aacb9921c0567edcef7cf4cfbae.zip
gcc-fdfd537bcb069aacb9921c0567edcef7cf4cfbae.tar.gz
gcc-fdfd537bcb069aacb9921c0567edcef7cf4cfbae.tar.bz2
re PR middle-end/59990 (incorrect memcpy optimization)
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/builtins.c64
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59990.c18
4 files changed, 71 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 158f2d6..bbf6b47 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index a45380c..f5f55bf 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 435b055..87fff13 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..e54f9b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59990.c
@@ -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;
+}