Commit 21e8fb22 by Richard Biener Committed by Richard Biener

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
parent 53f5803e
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.
......
...@@ -535,6 +535,10 @@ get_pointer_alignment (tree exp) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
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
......
/* { 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" } } */
...@@ -43,8 +43,8 @@ main () ...@@ -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" } } */
......
...@@ -30,6 +30,6 @@ end ...@@ -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" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment