aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-07-11 13:42:55 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-07-11 13:42:55 +0000
commit21e8fb22580939c384699b75bcc0d7490beba819 (patch)
tree62b95556dd83989e21bbd9636f8b6f7f203b1e98 /gcc
parent53f5803e4deafeeff6db1020df703e57eee2c108 (diff)
downloadgcc-21e8fb22580939c384699b75bcc0d7490beba819.zip
gcc-21e8fb22580939c384699b75bcc0d7490beba819.tar.gz
gcc-21e8fb22580939c384699b75bcc0d7490beba819.tar.bz2
re PR middle-end/61473 (register sized memmove not inlined)
2014-07-11 Richard Biener <rguenther@suse.de> PR middle-end/61473 * builtins.c (fold_builtin_memory_op): Inline memory moves that can be implemented with a single load followed by a single store. (c_strlen): Only warn when only_value is not 2. * gcc.dg/memmove-4.c: New testcase. * gcc.dg/strlenopt-8.c: XFAIL. * gfortran.dg/coarray_lib_realloc_1.f90: Adjust. From-SVN: r212452
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtins.c64
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/memmove-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-8.c4
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f902
6 files changed, 86 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b8ab122..6fe9bfdb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-07-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61473
+ * builtins.c (fold_builtin_memory_op): Inline memory moves
+ that can be implemented with a single load followed by a
+ single store.
+ (c_strlen): Only warn when only_value is not 2.
+
2014-07-11 Evgeny Stupachenko <evstupac@gmail.com>
* config/i386/i386.c (expand_vec_perm_pblendv): Disable for AVX.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2d3d867..cc94302 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -535,6 +535,10 @@ get_pointer_alignment (tree exp)
len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
evaluate the side-effects.
+ If ONLY_VALUE is two then we do not emit warnings about out-of-bound
+ accesses. Note that this implies the result is not going to be emitted
+ into the instruction stream.
+
The value returned is of type `ssizetype'.
Unfortunately, string_constant can't access the values of const char
@@ -606,7 +610,8 @@ c_strlen (tree src, int only_value)
/* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */
- if (offset < 0 || offset > max)
+ if (only_value != 2
+ && (offset < 0 || offset > max))
{
/* Suppress multiple warnings for propagated constant strings. */
if (! TREE_NO_WARNING (src))
@@ -8637,11 +8642,57 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
unsigned int src_align, dest_align;
tree off0;
+ /* Build accesses at offset zero with a ref-all character type. */
+ off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
+ ptr_mode, true), 0);
+
+ /* If we can perform the copy efficiently with first doing all loads
+ and then all stores inline it that way. Currently efficiently
+ means that we can load all the memory into a single integer
+ register which is what MOVE_MAX gives us. */
+ src_align = get_pointer_alignment (src);
+ dest_align = get_pointer_alignment (dest);
+ if (tree_fits_uhwi_p (len)
+ && compare_tree_int (len, MOVE_MAX) <= 0
+ /* ??? Don't transform copies from strings with known length this
+ confuses the tree-ssa-strlen.c. This doesn't handle
+ the case in gcc.dg/strlenopt-8.c which is XFAILed for that
+ reason. */
+ && !c_strlen (src, 2))
+ {
+ unsigned ilen = tree_to_uhwi (len);
+ if (exact_log2 (ilen) != -1)
+ {
+ tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
+ if (type
+ && TYPE_MODE (type) != BLKmode
+ && (GET_MODE_SIZE (TYPE_MODE (type)) * BITS_PER_UNIT
+ == ilen * 8)
+ /* If the pointers are not aligned we must be able to
+ emit an unaligned load. */
+ && ((src_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type))
+ && dest_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+ || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type),
+ MIN (src_align, dest_align))))
+ {
+ tree srctype = type;
+ tree desttype = type;
+ if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+ srctype = build_aligned_type (type, src_align);
+ if (dest_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+ desttype = build_aligned_type (type, dest_align);
+ if (!ignore)
+ dest = builtin_save_expr (dest);
+ expr = build2 (MODIFY_EXPR, type,
+ fold_build2 (MEM_REF, desttype, dest, off0),
+ fold_build2 (MEM_REF, srctype, src, off0));
+ goto done;
+ }
+ }
+ }
+
if (endp == 3)
{
- src_align = get_pointer_alignment (src);
- dest_align = get_pointer_alignment (dest);
-
/* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types
really mandatory?
@@ -8818,10 +8869,6 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (!ignore)
dest = builtin_save_expr (dest);
- /* Build accesses at offset zero with a ref-all character type. */
- off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
- ptr_mode, true), 0);
-
destvar = dest;
STRIP_NOPS (destvar);
if (TREE_CODE (destvar) == ADDR_EXPR
@@ -8888,6 +8935,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
}
+done:
if (ignore)
return expr;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 63b51c6..324db90 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2014-07-11 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61473
+ * gcc.dg/memmove-4.c: New testcase.
+ * gcc.dg/strlenopt-8.c: XFAIL.
+ * gfortran.dg/coarray_lib_realloc_1.f90: Adjust.
+
2014-07-11 Marat Zakirov <m.zakirov@samsung.com>
PR target/61561
diff --git a/gcc/testsuite/gcc.dg/memmove-4.c b/gcc/testsuite/gcc.dg/memmove-4.c
new file mode 100644
index 0000000..120a4db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memmove-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+typedef int w __attribute__((mode(word)));
+
+void b(char *a, char *b, int i)
+{
+ __builtin_memmove (&a[i], &b[i], sizeof(w));
+}
+
+/* { dg-final { scan-tree-dump-not "memmove" "optimized" { xfail { ! non_strict_align } } } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-8.c b/gcc/testsuite/gcc.dg/strlenopt-8.c
index 3aaf660..3f9ad51 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-8.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-8.c
@@ -43,8 +43,8 @@ main ()
return 0;
}
-/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90
index 60d4456..4fd0e9b 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90
@@ -30,6 +30,6 @@ end
! { dg-final { scan-tree-dump-times "__builtin_malloc" 1 "original" } }
! But copy "ii" and "CAF":
-! { dg-final { scan-tree-dump-times "__builtin_memcpy" 2 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcpy|= MEM" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }