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
This commit is contained in:
Richard Biener 2014-07-11 13:42:55 +00:00 committed by Richard Biener
parent 53f5803e4d
commit 21e8fb2258
6 changed files with 86 additions and 11 deletions

View File

@ -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> 2014-07-11 Evgeny Stupachenko <evstupac@gmail.com>
* config/i386/i386.c (expand_vec_perm_pblendv): Disable for AVX. * config/i386/i386.c (expand_vec_perm_pblendv): Disable for AVX.

View File

@ -535,6 +535,10 @@ get_pointer_alignment (tree exp)
len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
evaluate the side-effects. 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'. The value returned is of type `ssizetype'.
Unfortunately, string_constant can't access the values of const char 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 /* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */ runtime. */
if (offset < 0 || offset > max) if (only_value != 2
&& (offset < 0 || offset > max))
{ {
/* Suppress multiple warnings for propagated constant strings. */ /* Suppress multiple warnings for propagated constant strings. */
if (! TREE_NO_WARNING (src)) 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; unsigned int src_align, dest_align;
tree off0; 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) if (endp == 3)
{ {
src_align = get_pointer_alignment (src);
dest_align = get_pointer_alignment (dest);
/* Both DEST and SRC must be pointer types. /* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types ??? This is what old code did. Is the testing for pointer types
really mandatory? really mandatory?
@ -8818,10 +8869,6 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (!ignore) if (!ignore)
dest = builtin_save_expr (dest); 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; destvar = dest;
STRIP_NOPS (destvar); STRIP_NOPS (destvar);
if (TREE_CODE (destvar) == ADDR_EXPR 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); expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
} }
done:
if (ignore) if (ignore)
return expr; return expr;

View File

@ -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> 2014-07-11 Marat Zakirov <m.zakirov@samsung.com>
PR target/61561 PR target/61561

View File

@ -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" } } */

View File

@ -43,8 +43,8 @@ main ()
return 0; return 0;
} }
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */ /* { 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 "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */

View File

@ -30,6 +30,6 @@ end
! { dg-final { scan-tree-dump-times "__builtin_malloc" 1 "original" } } ! { dg-final { scan-tree-dump-times "__builtin_malloc" 1 "original" } }
! But copy "ii" and "CAF": ! 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" } } ! { dg-final { cleanup-tree-dump "original" } }