2008-11-05 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Nov 2008 12:17:10 +0000 (12:17 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Nov 2008 12:17:10 +0000 (12:17 +0000)
PR middle-end/37742
* tree-ssa.c (useless_type_conversion_p_1): Check different restrict
qualified pointer conversion before stripping qualifiers.
* gimplify.c (create_tmp_from_val): Use correctly qualified type.
* tree-flow.h (may_propagate_address_into_dereference): Declare.
* tree-ssa-ccp.c (may_propagate_address_into_dereference): New function.
(ccp_fold): Use it.
* tree-ssa-forwprop.c (rhs_to_tree): Remove useless conversions,
properly canonicalize binary ops.
(forward_propagate_addr_expr_1): Use
may_propagate_address_into_dereference.

cp/
* decl.c (start_preparsed_function): Use the correct type for
building the RESULT_DECL.

* gcc.c-torture/compile/pr37742.c: New testcase.
* g++.dg/pr37742.C: Likewise.
* gcc.dg/tree-ssa/forwprop-7.c: Check for two volatile loads.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141606 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr37742.C [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/pr37742.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c
gcc/tree-flow.h
gcc/tree-ssa-ccp.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa.c

index cade56f..4a6b0c2 100644 (file)
@@ -1,3 +1,17 @@
+2008-11-05  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/37742
+       * tree-ssa.c (useless_type_conversion_p_1): Check different restrict
+       qualified pointer conversion before stripping qualifiers.
+       * gimplify.c (create_tmp_from_val): Use correctly qualified type.
+       * tree-flow.h (may_propagate_address_into_dereference): Declare.
+       * tree-ssa-ccp.c (may_propagate_address_into_dereference): New function.
+       (ccp_fold): Use it.
+       * tree-ssa-forwprop.c (rhs_to_tree): Remove useless conversions,
+       properly canonicalize binary ops.
+       (forward_propagate_addr_expr_1): Use
+       may_propagate_address_into_dereference.
+
 2008-11-05  Uros Bizjak  <ubizjak@gmail.com>
 
        PR middle-end/37286
index 34257e5..3b4f8b1 100644 (file)
@@ -1,3 +1,9 @@
+2008-11-05  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/37742
+       * decl.c (start_preparsed_function): Use the correct type for
+       building the RESULT_DECL.
+
 2008-10-31  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/37967
index 754f433..945b947 100644 (file)
@@ -11492,7 +11492,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
     {
       tree resdecl;
 
-      resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+      resdecl = build_decl (RESULT_DECL, 0, restype);
       DECL_ARTIFICIAL (resdecl) = 1;
       DECL_IGNORED_P (resdecl) = 1;
       DECL_RESULT (decl1) = resdecl;
index d2625a7..bec4257 100644 (file)
@@ -565,7 +565,7 @@ create_tmp_var (tree type, const char *prefix)
 static inline tree
 create_tmp_from_val (tree val)
 {
-  return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
+  return create_tmp_var (TREE_TYPE (val), get_name (val));
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
index 2522278..79811bd 100644 (file)
@@ -1,3 +1,10 @@
+2008-11-05  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/37742
+       * gcc.c-torture/compile/pr37742.c: New testcase.
+       * g++.dg/pr37742.C: Likewise.
+       * gcc.dg/tree-ssa/forwprop-7.c: Check for two volatile loads.
+
 2008-11-05  Uros Bizjak  <ubizjak@gmail.com>
 
        PR middle-end/37286
diff --git a/gcc/testsuite/g++.dg/pr37742.C b/gcc/testsuite/g++.dg/pr37742.C
new file mode 100644 (file)
index 0000000..784eb49
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+typedef long unsigned int size_t;
+void*   __valarray_get_memory(size_t __n);
+int*__restrict__
+__valarray_get_storage(size_t __n)
+{
+  return static_cast<int* __restrict__>(__valarray_get_memory(__n));
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37742.c b/gcc/testsuite/gcc.c-torture/compile/pr37742.c
new file mode 100644 (file)
index 0000000..4ef00be
--- /dev/null
@@ -0,0 +1,21 @@
+void foo(int* __restrict__ p, int* q, int* p1, int *q1)
+{
+  int i;
+
+  p = p1;
+  q = q1;
+
+  for (i = 0; i < 4; ++i)
+    *++q = *++p + 1;
+}
+
+void bar(int* p, int* __restrict__ q, int* p1, int *q1)
+{
+  int i;
+
+  p = p1;
+  q = q1;
+
+  for (i = 0; i < 4; ++i)
+    *++q = *++p + 1;
+}
index 6b894b5..0d2bac5 100644 (file)
@@ -8,7 +8,9 @@ int foo(void)
   return *p + *p;
 }
 
-/* We should not convert the cast to a VCE in forwprop1 as we have a volatile reference.  */
+/* We should not convert the cast to a VCE in forwprop1 as we have a
+   volatile reference.  */
+
 /* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 0 "forwprop1"} } */
-/* { dg-final { scan-tree-dump-times "volatile int" 2 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "={v}" 2 "forwprop1"} } */
 /* { dg-final { cleanup-tree-dump "forwprop1" } } */
index fe649dd..6004978 100644 (file)
@@ -905,6 +905,8 @@ bool fold_stmt (gimple_stmt_iterator *);
 bool fold_stmt_inplace (gimple);
 tree get_symbol_constant_value (tree);
 tree fold_const_aggregate_ref (tree);
+bool may_propagate_address_into_dereference (tree, tree);
+
 
 /* In tree-vrp.c  */
 tree vrp_evaluate_conditional (enum tree_code, tree, tree, gimple);
index 0365697..a7d5be3 100644 (file)
@@ -851,6 +851,31 @@ ccp_visit_phi_node (gimple phi)
     return SSA_PROP_NOT_INTERESTING;
 }
 
+/* Return true if we may propagate the address expression ADDR into the 
+   dereference DEREF and cancel them.  */
+
+bool
+may_propagate_address_into_dereference (tree addr, tree deref)
+{
+  gcc_assert (INDIRECT_REF_P (deref)
+             && TREE_CODE (addr) == ADDR_EXPR);
+
+  /* If the address is invariant then we do not need to preserve restrict
+     qualifications.  But we do need to preserve volatile qualifiers until
+     we can annotate the folded dereference itself properly.  */
+  if (is_gimple_min_invariant (addr)
+      && (!TREE_THIS_VOLATILE (deref)
+         || TYPE_VOLATILE (TREE_TYPE (addr))))
+    return useless_type_conversion_p (TREE_TYPE (deref),
+                                     TREE_TYPE (TREE_OPERAND (addr, 0)));
+
+  /* Else both the address substitution and the folding must result in
+     a valid useless type conversion sequence.  */
+  return (useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (deref, 0)),
+                                    TREE_TYPE (addr))
+         && useless_type_conversion_p (TREE_TYPE (deref),
+                                       TREE_TYPE (TREE_OPERAND (addr, 0))));
+}
 
 /* CCP specific front-end to the non-destructive constant folding
    routines.
@@ -897,12 +922,8 @@ ccp_fold (gimple stmt)
                      prop_value_t *val = get_value (TREE_OPERAND (*base, 0));
                      if (val->lattice_val == CONSTANT
                          && TREE_CODE (val->value) == ADDR_EXPR
-                         && useless_type_conversion_p
-                         (TREE_TYPE (TREE_OPERAND (*base, 0)),
-                          TREE_TYPE (val->value))
-                         && useless_type_conversion_p
-                         (TREE_TYPE (*base),
-                          TREE_TYPE (TREE_OPERAND (val->value, 0))))
+                         && may_propagate_address_into_dereference
+                              (val->value, *base))
                        {
                          /* We need to return a new tree, not modify the IL
                             or share parts of it.  So play some tricks to
index 7a5233b..a04e7ca 100644 (file)
@@ -334,10 +334,10 @@ rhs_to_tree (tree type, gimple stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
   if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
-    return fold_convert (type, build2 (code, type, gimple_assign_rhs1 (stmt),
-                         gimple_assign_rhs2 (stmt)));
+    return fold_build2 (code, type, gimple_assign_rhs1 (stmt),
+                       gimple_assign_rhs2 (stmt));
   else if (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS)
-    return fold_convert (type, build1 (code, type, gimple_assign_rhs1 (stmt)));
+    return build1 (code, type, gimple_assign_rhs1 (stmt));
   else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
     return gimple_assign_rhs1 (stmt);
   else
@@ -719,12 +719,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
      propagate the ADDR_EXPR into the use of NAME and fold the result.  */
   if (TREE_CODE (lhs) == INDIRECT_REF
       && TREE_OPERAND (lhs, 0) == name
-      && useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (lhs, 0)),
-                                   TREE_TYPE (def_rhs))
-      /* ???  This looks redundant, but is required for bogus types
-        that can sometimes occur.  */
-      && useless_type_conversion_p (TREE_TYPE (lhs),
-                                   TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
+      && may_propagate_address_into_dereference (def_rhs, lhs))
     {
       *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
       fold_stmt_inplace (use_stmt);
@@ -747,12 +742,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
      propagate the ADDR_EXPR into the use of NAME and fold the result.  */
   if (TREE_CODE (rhs) == INDIRECT_REF
       && TREE_OPERAND (rhs, 0) == name
-      && useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (rhs, 0)),
-                                   TREE_TYPE (def_rhs))
-      /* ???  This looks redundant, but is required for bogus types
-        that can sometimes occur.  */
-      && useless_type_conversion_p (TREE_TYPE (rhs),
-                                   TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
+      && may_propagate_address_into_dereference (def_rhs, rhs))
     {
       *rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
       fold_stmt_inplace (use_stmt);
index 8f238a3..935cad6 100644 (file)
@@ -1071,7 +1071,18 @@ delete_tree_ssa (void)
 static bool
 useless_type_conversion_p_1 (tree outer_type, tree inner_type)
 {
-  /* Qualifiers on value types do not matter.  */
+  /* Do the following before stripping toplevel qualifiers.  */
+  if (POINTER_TYPE_P (inner_type)
+      && POINTER_TYPE_P (outer_type))
+    {
+      /* Do not lose casts to restrict qualified pointers.  */
+      if ((TYPE_RESTRICT (outer_type)
+          != TYPE_RESTRICT (inner_type))
+         && TYPE_RESTRICT (outer_type))
+       return false;
+    }
+
+  /* From now on qualifiers on value types do not matter.  */
   inner_type = TYPE_MAIN_VARIANT (inner_type);
   outer_type = TYPE_MAIN_VARIANT (outer_type);
 
@@ -1147,12 +1158,6 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
       /* We do not care for const qualification of the pointed-to types
         as const qualification has no semantic value to the middle-end.  */
 
-      /* Do not lose casts to restrict qualified pointers.  */
-      if ((TYPE_RESTRICT (outer_type)
-          != TYPE_RESTRICT (inner_type))
-         && TYPE_RESTRICT (outer_type))
-       return false;
-
       /* Otherwise pointers/references are equivalent if their pointed
         to types are effectively the same.  We can strip qualifiers
         on pointed-to types for further comparison, which is done in