Commit 64d7685c by Jakub Jelinek Committed by Jakub Jelinek

builtins.c (fold_builtin_memory_op): Optimize memmove into memcpy if we can…

builtins.c (fold_builtin_memory_op): Optimize memmove into memcpy if we can prove source and destination don't overlap.

	* builtins.c (fold_builtin_memory_op): Optimize memmove
	into memcpy if we can prove source and destination don't overlap.

	* gcc.dg/memmove-2.c: New test.
	* gcc.dg/memmove-3.c: New test.

From-SVN: r145127
parent 9f5e9983
2009-03-27 Jakub Jelinek <jakub@redhat.com>
* builtins.c (fold_builtin_memory_op): Optimize memmove
into memcpy if we can prove source and destination don't overlap.
* tree-inline.c: Include gt-tree-inline.h.
(clone_fn_id_num): New variable.
(clone_function_name): New function.
......
......@@ -8879,17 +8879,76 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
really mandatory?
If either SRC is readonly or length is 1, we can use memcpy. */
if (dest_align && src_align
&& (readonly_data_expr (src)
|| (host_integerp (len, 1)
&& (MIN (src_align, dest_align) / BITS_PER_UNIT >=
tree_low_cst (len, 1)))))
if (!dest_align || !src_align)
return NULL_TREE;
if (readonly_data_expr (src)
|| (host_integerp (len, 1)
&& (MIN (src_align, dest_align) / BITS_PER_UNIT
>= tree_low_cst (len, 1))))
{
tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return NULL_TREE;
return build_call_expr (fn, 3, dest, src, len);
}
/* If *src and *dest can't overlap, optimize into memcpy as well. */
srcvar = build_fold_indirect_ref (src);
destvar = build_fold_indirect_ref (dest);
if (srcvar
&& !TREE_THIS_VOLATILE (srcvar)
&& destvar
&& !TREE_THIS_VOLATILE (destvar))
{
tree src_base, dest_base, fn;
HOST_WIDE_INT src_offset = 0, dest_offset = 0;
HOST_WIDE_INT size = -1;
HOST_WIDE_INT maxsize = -1;
src_base = srcvar;
if (handled_component_p (src_base))
src_base = get_ref_base_and_extent (src_base, &src_offset,
&size, &maxsize);
dest_base = destvar;
if (handled_component_p (dest_base))
dest_base = get_ref_base_and_extent (dest_base, &dest_offset,
&size, &maxsize);
if (host_integerp (len, 1))
{
maxsize = tree_low_cst (len, 1);
if (maxsize
> INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT)
maxsize = -1;
else
maxsize *= BITS_PER_UNIT;
}
else
maxsize = -1;
if (SSA_VAR_P (src_base)
&& SSA_VAR_P (dest_base))
{
if (operand_equal_p (src_base, dest_base, 0)
&& ranges_overlap_p (src_offset, maxsize,
dest_offset, maxsize))
return NULL_TREE;
}
else if (TREE_CODE (src_base) == INDIRECT_REF
&& TREE_CODE (dest_base) == INDIRECT_REF)
{
if (! operand_equal_p (TREE_OPERAND (src_base, 0),
TREE_OPERAND (dest_base, 0), 0)
|| ranges_overlap_p (src_offset, maxsize,
dest_offset, maxsize))
return NULL_TREE;
}
else
return NULL_TREE;
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return NULL_TREE;
return build_call_expr (fn, 3, dest, src, len);
}
return NULL_TREE;
}
......
2009-03-27 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/memmove-2.c: New test.
* gcc.dg/memmove-3.c: New test.
* gcc.dg/ipa/ipacost-1.c: Adjust match pattern for change
in clone naming.
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-times "memmove" 0 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
char a[40];
extern void bar (char *);
void
foo (void)
{
char b[10];
__builtin_memmove (&a[0], &a[20], 20);
__builtin_memmove (&b[1], &a[25], 9);
bar (b);
}
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-times "memmove" 3 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
char a[40];
struct A { char a[30]; };
void
foo (struct A *p, char *q, char *r)
{
char b[10];
__builtin_memmove (&a[1], &a[19], 20);
__builtin_memmove (&p->a[1], &p->a[9], 10);
__builtin_memmove (q, r, 9);
}
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