mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 03:40:26 +08:00
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:
parent
1fd8faf059
commit
81f5094da4
@ -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)))).
|
||||
|
119
gcc/builtins.c
119
gcc/builtins.c
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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
|
||||
|
33
gcc/testsuite/gcc.dg/pr29215.c
Normal file
33
gcc/testsuite/gcc.dg/pr29215.c
Normal 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" } } */
|
@ -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" } }
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user