From: Richard Biener Date: Fri, 11 Jul 2014 13:42:55 +0000 (+0000) Subject: re PR middle-end/61473 (register sized memmove not inlined) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=21e8fb22580939c384699b75bcc0d7490beba819;p=gcc.git re PR middle-end/61473 (register sized memmove not inlined) 2014-07-11 Richard Biener 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b8ab1223d73..6fe9bfdb719 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-07-11 Richard Biener + + 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 * config/i386/i386.c (expand_vec_perm_pblendv): Disable for AVX. diff --git a/gcc/builtins.c b/gcc/builtins.c index 2d3d867b0b2..cc94302d0cf 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 63b51c67589..324db906363 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-07-11 Richard Biener + + 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 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 00000000000..120a4db219e --- /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 3aaf660a12c..3f9ad511263 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 60d4456323f..4fd0e9b899f 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" } }