aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/builtins.c119
-rw-r--r--gcc/fortran/ChangeLog4
-rw-r--r--gcc/fortran/trans-array.c7
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr29215.c33
-rw-r--r--gcc/testsuite/gfortran.dg/array_memcpy_3.f902
-rw-r--r--gcc/tree-ssa-sccvn.c2
8 files changed, 148 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4b61173..5ef8190 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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)))).
diff --git a/gcc/builtins.c b/gcc/builtins.c
index fd6d0b8..0e5b834 100644
--- a/gcc/builtins.c
+++ b/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)
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 1316eb6..941186f 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -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.
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 9c48c42..1385409 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -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++;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6eaad34..3a767f1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/pr29215.c b/gcc/testsuite/gcc.dg/pr29215.c
new file mode 100644
index 0000000..aa3f82c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr29215.c
@@ -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" } } */
diff --git a/gcc/testsuite/gfortran.dg/array_memcpy_3.f90 b/gcc/testsuite/gfortran.dg/array_memcpy_3.f90
index 0591587..df6bd49 100644
--- a/gcc/testsuite/gfortran.dg/array_memcpy_3.f90
+++ b/gcc/testsuite/gfortran.dg/array_memcpy_3.f90
@@ -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" } }
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 80f7a92..e40681f 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -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)
{