OSDN Git Service

2007-08-24 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Aug 2007 15:09:10 +0000 (15:09 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Aug 2007 15:09:10 +0000 (15:09 +0000)
PR middle-end/33166
* tree-ssa.c (useless_type_conversion_p): Split into a
recursive and a non-recursive part.
(useless_type_conversion_p_1): New function.
* tree-ssa-ccp.c (fold_stmt_r): Make sure that the result
from maybe_fold_offset_to_reference is trivially convertible
to the desired type before doing the simplification.

* gcc.c-torture/compile/pr33166.c: New testcase.

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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr33166.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c
gcc/tree-ssa.c

index 18e9586..02646a7 100644 (file)
@@ -1,3 +1,13 @@
+2007-08-24  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/33166
+       * tree-ssa.c (useless_type_conversion_p): Split into a
+       recursive and a non-recursive part.
+       (useless_type_conversion_p_1): New function.
+       * tree-ssa-ccp.c (fold_stmt_r): Make sure that the result
+       from maybe_fold_offset_to_reference is trivially convertible
+       to the desired type before doing the simplification.
+
 2007-08-24  Jakub Jelinek  <jakub@redhat.com>
 
        * expr.c (store_expr): Optimize initialization of an array
index a27c2ad..54da80e 100644 (file)
@@ -1,3 +1,8 @@
+2007-08-24  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/33166
+       * gcc.c-torture/compile/pr33166.c: New testcase.
+
 2007-08-24  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/33139
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33166.c b/gcc/testsuite/gcc.c-torture/compile/pr33166.c
new file mode 100644 (file)
index 0000000..a48c529
--- /dev/null
@@ -0,0 +1,10 @@
+static void ConvertAddr (char *saddr, void **addr)
+{
+  *addr = (void *) &saddr;
+}
+void DefineSelf (char *addr)
+{
+  ConvertAddr (addr, (void **) &addr);
+  if (addr[0] == 127 && addr[3] == 1)
+    ;
+}
index e6dfcd8..e0829f5 100644 (file)
@@ -2060,7 +2060,12 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
                      (TREE_OPERAND (expr, 0),
                       integer_zero_node,
                       TREE_TYPE (TREE_TYPE (expr)))))
-        t = build_fold_addr_expr_with_type (t, TREE_TYPE (expr));
+       {
+         tree ptr_type = build_pointer_type (TREE_TYPE (t));
+         if (!useless_type_conversion_p (TREE_TYPE (expr), ptr_type))
+           return NULL_TREE;
+          t = build_fold_addr_expr_with_type (t, ptr_type);
+       }
       break;
 
       /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF.
index e088549..633e446 100644 (file)
@@ -885,32 +885,10 @@ delete_tree_ssa (void)
   cfun->gimple_df = NULL;
 }
 
+/* Helper function for useless_type_conversion_p.  */
 
-/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
-   useless type conversion, otherwise return false.
-
-   This function implicitly defines the middle-end type system.  With
-   the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
-   holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
-   the following invariants shall be fulfilled:
-
-     1) useless_type_conversion_p is transitive.
-       If a < b and b < c then a < c.
-
-     2) useless_type_conversion_p is not symmetric.
-       From a < b does not follow a > b.
-
-     3) Types define the available set of operations applicable to values.
-       A type conversion is useless if the operations for the target type
-       is a subset of the operations for the source type.  For example
-       casts to void* are useless, casts from void* are not (void* can't
-       be dereferenced or offsetted, but copied, hence its set of operations
-       is a strict subset of that of all other data pointer types).  Casts
-       to const T* are useless (can't be written to), casts from const T*
-       to T* are not.  */
-
-bool
-useless_type_conversion_p (tree outer_type, tree inner_type)
+static bool
+useless_type_conversion_p_1 (tree outer_type, tree inner_type)
 {
   /* Qualifiers on value types do not matter.  */
   inner_type = TYPE_MAIN_VARIANT (inner_type);
@@ -964,11 +942,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
   else if (POINTER_TYPE_P (inner_type)
           && POINTER_TYPE_P (outer_type))
     {
-      /* If the outer type is (void *), then the conversion is not
-        necessary.  */
-      if (TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
-       return true;
-
       /* Don't lose casts between pointers to volatile and non-volatile
         qualified types.  Doing so would result in changing the semantics
         of later accesses.  */
@@ -1002,22 +975,22 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
         to types are effectively the same.  We can strip qualifiers
         on pointed-to types for further comparison, which is done in
         the callee.  */
-      return useless_type_conversion_p (TREE_TYPE (outer_type),
-                                       TREE_TYPE (inner_type));
+      return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
+                                         TREE_TYPE (inner_type));
     }
 
   /* Recurse for complex types.  */
   else if (TREE_CODE (inner_type) == COMPLEX_TYPE
           && TREE_CODE (outer_type) == COMPLEX_TYPE)
-    return useless_type_conversion_p (TREE_TYPE (outer_type),
-                                     TREE_TYPE (inner_type));
+    return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
+                                       TREE_TYPE (inner_type));
 
   /* Recurse for vector types with the same number of subparts.  */
   else if (TREE_CODE (inner_type) == VECTOR_TYPE
           && TREE_CODE (outer_type) == VECTOR_TYPE
           && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
-    return useless_type_conversion_p (TREE_TYPE (outer_type),
-                                     TREE_TYPE (inner_type));
+    return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
+                                       TREE_TYPE (inner_type));
 
   /* For aggregates we may need to fall back to structural equality
      checks.  */
@@ -1037,6 +1010,43 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
   return false;
 }
 
+/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
+   useless type conversion, otherwise return false.
+
+   This function implicitly defines the middle-end type system.  With
+   the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
+   holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
+   the following invariants shall be fulfilled:
+
+     1) useless_type_conversion_p is transitive.
+       If a < b and b < c then a < c.
+
+     2) useless_type_conversion_p is not symmetric.
+       From a < b does not follow a > b.
+
+     3) Types define the available set of operations applicable to values.
+       A type conversion is useless if the operations for the target type
+       is a subset of the operations for the source type.  For example
+       casts to void* are useless, casts from void* are not (void* can't
+       be dereferenced or offsetted, but copied, hence its set of operations
+       is a strict subset of that of all other data pointer types).  Casts
+       to const T* are useless (can't be written to), casts from const T*
+       to T* are not.  */
+
+bool
+useless_type_conversion_p (tree outer_type, tree inner_type)
+{
+  /* If the outer type is (void *), then the conversion is not
+     necessary.  We have to make sure to not apply this while
+     recursing though.  */
+  if (POINTER_TYPE_P (inner_type)
+      && POINTER_TYPE_P (outer_type)
+      && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
+    return true;
+
+  return useless_type_conversion_p_1 (outer_type, inner_type);
+}
+
 /* Return true if a conversion from either type of TYPE1 and TYPE2
    to the other is not required.  Otherwise return false.  */