Commit 81f5094d by Jakub Jelinek Committed by Jakub Jelinek

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
parent 1fd8faf0
2008-11-20 Jakub Jelinek <jakub@redhat.com> 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 PR rtl-optimization/36998
* dwarf2out.c (stack_adjust_offset): Add cur_args_size and cur_offset * dwarf2out.c (stack_adjust_offset): Add cur_args_size and cur_offset
arguments. Handle sp = reg and (set (foo) (mem (pre_inc (reg sp)))). arguments. Handle sp = reg and (set (foo) (mem (pre_inc (reg sp)))).
......
...@@ -51,6 +51,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -51,6 +51,10 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h" #include "value-prof.h"
#include "diagnostic.h" #include "diagnostic.h"
#ifndef SLOW_UNALIGNED_ACCESS
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
#endif
#ifndef PAD_VARARGS_DOWN #ifndef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
#endif #endif
...@@ -8824,10 +8828,12 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i ...@@ -8824,10 +8828,12 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
else else
{ {
tree srctype, desttype; tree srctype, desttype;
int src_align, dest_align;
if (endp == 3) if (endp == 3)
{ {
int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
/* 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
...@@ -8862,45 +8868,96 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i ...@@ -8862,45 +8868,96 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
|| !TYPE_SIZE_UNIT (srctype) || !TYPE_SIZE_UNIT (srctype)
|| !TYPE_SIZE_UNIT (desttype) || !TYPE_SIZE_UNIT (desttype)
|| TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != 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))
return NULL_TREE; return NULL_TREE;
if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT) src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
< (int) TYPE_ALIGN (desttype) dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
|| (get_pointer_alignment (src, BIGGEST_ALIGNMENT) if (dest_align < (int) TYPE_ALIGN (desttype)
< (int) TYPE_ALIGN (srctype))) || src_align < (int) TYPE_ALIGN (srctype))
return NULL_TREE; return NULL_TREE;
if (!ignore) if (!ignore)
dest = builtin_save_expr (dest); dest = builtin_save_expr (dest);
srcvar = NULL_TREE;
if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
{
srcvar = build_fold_indirect_ref (src); srcvar = build_fold_indirect_ref (src);
if (TREE_THIS_VOLATILE (srcvar)) if (TREE_THIS_VOLATILE (srcvar))
return NULL_TREE; srcvar = NULL_TREE;
if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len)) else if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
return NULL_TREE; srcvar = NULL_TREE;
/* With memcpy, it is possible to bypass aliasing rules, so without /* With memcpy, it is possible to bypass aliasing rules, so without
this check i.e. execute/20060930-2.c would be misoptimized, because this check i.e. execute/20060930-2.c would be misoptimized,
it use conflicting alias set to hold argument for the memcpy call. because it use conflicting alias set to hold argument for the
This check is probably unnecessary with -fno-strict-aliasing. memcpy call. This check is probably unnecessary with
Similarly for destvar. See also PR29286. */ -fno-strict-aliasing. Similarly for destvar. See also
if (!var_decl_component_p (srcvar) PR29286. */
/* Accept: memcpy (*char_var, "test", 1); that simplify else if (!var_decl_component_p (srcvar))
to char_var='t'; */ srcvar = NULL_TREE;
|| is_gimple_min_invariant (srcvar) }
|| readonly_data_expr (src))
return NULL_TREE;
destvar = NULL_TREE;
if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
{
destvar = build_fold_indirect_ref (dest); destvar = build_fold_indirect_ref (dest);
if (TREE_THIS_VOLATILE (destvar)) 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;
if (srcvar == NULL_TREE)
{
tree srcptype;
if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
return NULL_TREE; return NULL_TREE;
if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
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; return NULL_TREE;
if (!var_decl_component_p (destvar))
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; 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 if (srctype == desttype
|| (gimple_in_ssa_p (cfun) || (gimple_in_ssa_p (cfun)
&& useless_type_conversion_p (desttype, srctype))) && useless_type_conversion_p (desttype, srctype)))
......
2008-11-20 Jakub Jelinek <jakub@redhat.com> 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 * trans-intrinsic.c (gfc_conv_intrinsic_minmaxloc): Use
gfc_index_one_node. gfc_index_one_node.
(gfc_conv_intrinsic_size): Use gfc_index_{zero,one}_node. (gfc_conv_intrinsic_size): Use gfc_index_{zero,one}_node.
......
...@@ -1235,6 +1235,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, ...@@ -1235,6 +1235,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
tree init; tree init;
tree bound; tree bound;
tree tmptype; tree tmptype;
HOST_WIDE_INT idx = 0;
p = c; p = c;
list = NULL_TREE; list = NULL_TREE;
...@@ -1253,7 +1254,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type, ...@@ -1253,7 +1254,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
(gfc_get_pchar_type (p->expr->ts.kind), (gfc_get_pchar_type (p->expr->ts.kind),
se.expr); 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; c = p;
p = p->next; p = p->next;
} }
...@@ -1619,7 +1621,8 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type) ...@@ -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)) 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 = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
se.expr); 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; c = c->next;
nelem++; nelem++;
} }
......
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> 2008-11-19 Uros Bizjak <ubizjak@gmail.com>
PR target/38151 PR target/38151
......
/* 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" } } */
...@@ -11,5 +11,5 @@ subroutine bar(x) ...@@ -11,5 +11,5 @@ subroutine bar(x)
x = (/ 3, 1, 4, 1 /) x = (/ 3, 1, 4, 1 /)
end subroutine 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" } } ! { dg-final { cleanup-tree-dump "original" } }
...@@ -2654,7 +2654,7 @@ start_over: ...@@ -2654,7 +2654,7 @@ start_over:
usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES); usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
} }
else else
iter.done = true; clear_and_done_ssa_iter (&iter);
while (1) while (1)
{ {
......
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