re PR middle-end/29215 (extra store for memcpy)

PR middle-end/29215
	* builtins.c (SLOW_UNALIGNED_ACCESS): Define if not defined.
	(fold_builtin_memory_op): Handle even the case where just one
	of src and dest is an address of a var decl component, using
	TYPE_REF_CAN_ALIAS_ALL pointers.  Remove is_gimple_min_invariant
	and readonly_data_expr src check.
	* tree-ssa-sccvn.c (DFS): Use clear_and_done_ssa_iter to shut
	up warnings.

	* trans-array.c (trans_array_constructor_value,
	gfc_build_constant_array_constructor): Fill in TREE_PURPOSE.

	* gfortran.dg/array_memcpy_3.f90: Adjust pattern to match even
	memcpy optimized into ref-all store.
	* gcc.dg/pr29215.c: New test.

From-SVN: r142061
This commit is contained in:
Jakub Jelinek 2008-11-20 22:35:03 +01:00 committed by Jakub Jelinek
parent 1fd8faf059
commit 81f5094da4
8 changed files with 148 additions and 35 deletions

View File

@ -1,5 +1,14 @@
2008-11-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/29215
* builtins.c (SLOW_UNALIGNED_ACCESS): Define if not defined.
(fold_builtin_memory_op): Handle even the case where just one
of src and dest is an address of a var decl component, using
TYPE_REF_CAN_ALIAS_ALL pointers. Remove is_gimple_min_invariant
and readonly_data_expr src check.
* tree-ssa-sccvn.c (DFS): Use clear_and_done_ssa_iter to shut
up warnings.
PR rtl-optimization/36998
* dwarf2out.c (stack_adjust_offset): Add cur_args_size and cur_offset
arguments. Handle sp = reg and (set (foo) (mem (pre_inc (reg sp)))).

View File

@ -51,6 +51,10 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h"
#include "diagnostic.h"
#ifndef SLOW_UNALIGNED_ACCESS
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
#endif
#ifndef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
#endif
@ -8824,10 +8828,12 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
else
{
tree srctype, desttype;
int src_align, dest_align;
if (endp == 3)
{
int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
/* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types
@ -8862,44 +8868,95 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
|| !TYPE_SIZE_UNIT (srctype)
|| !TYPE_SIZE_UNIT (desttype)
|| TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
|| !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
|| !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST)
return NULL_TREE;
if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
< (int) TYPE_ALIGN (desttype)
|| (get_pointer_alignment (src, BIGGEST_ALIGNMENT)
< (int) TYPE_ALIGN (srctype)))
src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
if (dest_align < (int) TYPE_ALIGN (desttype)
|| src_align < (int) TYPE_ALIGN (srctype))
return NULL_TREE;
if (!ignore)
dest = builtin_save_expr (dest);
srcvar = build_fold_indirect_ref (src);
if (TREE_THIS_VOLATILE (srcvar))
return NULL_TREE;
if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
return NULL_TREE;
/* With memcpy, it is possible to bypass aliasing rules, so without
this check i.e. execute/20060930-2.c would be misoptimized, because
it use conflicting alias set to hold argument for the memcpy call.
This check is probably unnecessary with -fno-strict-aliasing.
Similarly for destvar. See also PR29286. */
if (!var_decl_component_p (srcvar)
/* Accept: memcpy (*char_var, "test", 1); that simplify
to char_var='t'; */
|| is_gimple_min_invariant (srcvar)
|| readonly_data_expr (src))
srcvar = NULL_TREE;
if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
{
srcvar = build_fold_indirect_ref (src);
if (TREE_THIS_VOLATILE (srcvar))
srcvar = NULL_TREE;
else if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
srcvar = NULL_TREE;
/* With memcpy, it is possible to bypass aliasing rules, so without
this check i.e. execute/20060930-2.c would be misoptimized,
because it use conflicting alias set to hold argument for the
memcpy call. This check is probably unnecessary with
-fno-strict-aliasing. Similarly for destvar. See also
PR29286. */
else if (!var_decl_component_p (srcvar))
srcvar = NULL_TREE;
}
destvar = NULL_TREE;
if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
{
destvar = build_fold_indirect_ref (dest);
if (TREE_THIS_VOLATILE (destvar))
destvar = NULL_TREE;
else if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
destvar = NULL_TREE;
else if (!var_decl_component_p (destvar))
destvar = NULL_TREE;
}
if (srcvar == NULL_TREE && destvar == NULL_TREE)
return NULL_TREE;
destvar = build_fold_indirect_ref (dest);
if (TREE_THIS_VOLATILE (destvar))
return NULL_TREE;
if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
return NULL_TREE;
if (!var_decl_component_p (destvar))
return NULL_TREE;
if (srcvar == NULL_TREE)
{
tree srcptype;
if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
return NULL_TREE;
srctype = desttype;
if (src_align < (int) TYPE_ALIGN (srctype))
{
if (AGGREGATE_TYPE_P (srctype)
|| SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
return NULL_TREE;
srctype = build_variant_type_copy (srctype);
TYPE_ALIGN (srctype) = src_align;
TYPE_USER_ALIGN (srctype) = 1;
TYPE_PACKED (srctype) = 1;
}
srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
src = fold_convert (srcptype, src);
srcvar = build_fold_indirect_ref (src);
}
else if (destvar == NULL_TREE)
{
tree destptype;
if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
return NULL_TREE;
desttype = srctype;
if (dest_align < (int) TYPE_ALIGN (desttype))
{
if (AGGREGATE_TYPE_P (desttype)
|| SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
return NULL_TREE;
desttype = build_variant_type_copy (desttype);
TYPE_ALIGN (desttype) = dest_align;
TYPE_USER_ALIGN (desttype) = 1;
TYPE_PACKED (desttype) = 1;
}
destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
dest = fold_convert (destptype, dest);
destvar = build_fold_indirect_ref (dest);
}
if (srctype == desttype
|| (gimple_in_ssa_p (cfun)

View File

@ -1,5 +1,9 @@
2008-11-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/29215
* trans-array.c (trans_array_constructor_value,
gfc_build_constant_array_constructor): Fill in TREE_PURPOSE.
* trans-intrinsic.c (gfc_conv_intrinsic_minmaxloc): Use
gfc_index_one_node.
(gfc_conv_intrinsic_size): Use gfc_index_{zero,one}_node.

View File

@ -1235,6 +1235,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
tree init;
tree bound;
tree tmptype;
HOST_WIDE_INT idx = 0;
p = c;
list = NULL_TREE;
@ -1253,7 +1254,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
(gfc_get_pchar_type (p->expr->ts.kind),
se.expr);
list = tree_cons (NULL_TREE, se.expr, list);
list = tree_cons (build_int_cst (gfc_array_index_type,
idx++), se.expr, list);
c = p;
p = p->next;
}
@ -1619,7 +1621,8 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
if (c->expr->ts.type == BT_CHARACTER && POINTER_TYPE_P (type))
se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
se.expr);
list = tree_cons (NULL_TREE, se.expr, list);
list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
se.expr, list);
c = c->next;
nelem++;
}

View File

@ -1,3 +1,10 @@
2008-11-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/29215
* gfortran.dg/array_memcpy_3.f90: Adjust pattern to match even
memcpy optimized into ref-all store.
* gcc.dg/pr29215.c: New test.
2008-11-19 Uros Bizjak <ubizjak@gmail.com>
PR target/38151

View File

@ -0,0 +1,33 @@
/* PR middle-end/29215 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
char buf[5 * sizeof (int) + 1] __attribute__((aligned (__alignof__ (int))));
static void
foo (int arg1, int arg2, int arg3, int arg4, int arg5)
{
__builtin_memcpy (buf, &arg1, sizeof (int));
__builtin_memcpy (buf + sizeof (int), &arg2, sizeof (int));
__builtin_memcpy (buf + 2 * sizeof (int), &arg3, sizeof (int));
__builtin_memcpy (buf + 3 * sizeof (int), &arg4, sizeof (int));
__builtin_memcpy (buf + 4 * sizeof (int), &arg5, sizeof (int));
}
int
main (void)
{
union { char buf[4]; int i; } u;
u.i = 0;
u.buf[0] = 'a';
u.buf[1] = 'b';
u.buf[2] = 'c';
u.buf[3] = 'd';
foo (u.i, u.i, u.i, u.i, u.i);
buf[5 * sizeof (int)] = '\0';
__builtin_puts (buf);
return 0;
}
/* { dg-final { scan-tree-dump-not "memcpy" "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */

View File

@ -11,5 +11,5 @@ subroutine bar(x)
x = (/ 3, 1, 4, 1 /)
end subroutine
! { dg-final { scan-tree-dump-times "memcpy" 2 "original" } }
! { dg-final { scan-tree-dump-times "memcpy|ref-all" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }

View File

@ -2654,7 +2654,7 @@ start_over:
usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
}
else
iter.done = true;
clear_and_done_ssa_iter (&iter);
while (1)
{