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:
parent
53f5803e4d
commit
21e8fb2258
@ -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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
12
gcc/testsuite/gcc.dg/memmove-4.c
Normal file
12
gcc/testsuite/gcc.dg/memmove-4.c
Normal 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" } } */
|
@ -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
|
|||||||
! { 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" } }
|
||||||
|
Loading…
Reference in New Issue
Block a user