> There must be a reason why I allowed modes to differ there btw ;)

Thinking about it, I guess reason is that incomplete types do not have
resonable modes set, so requiring modes to match will prevent complete
and incomplete types to match.

Here is updated patch which uses the earlier mode check and adjust it
to skip modes only for incomplete types.

Bootstrapped/regtested ppc64-linux, OK?

        * gimple-expr.c (useless_type_conversion_p): Do not use TYPE_CANONICAL
        for defining useless conversions; make structure compatible if size
        and mode are.
Index: gimple-expr.c
===================================================================
--- gimple-expr.c       (revision 228267)
+++ gimple-expr.c       (working copy)
@@ -87,15 +87,11 @@ useless_type_conversion_p (tree outer_ty
   if (inner_type == outer_type)
     return true;
 
-  /* If we know the canonical types, compare them.  */
-  if (TYPE_CANONICAL (inner_type)
-      && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
-    return true;
-
   /* Changes in machine mode are never useless conversions unless we
      deal with aggregate types in which case we defer to later checks.  */
   if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
-      && !AGGREGATE_TYPE_P (inner_type))
+      && (!AGGREGATE_TYPE_P (inner_type)
+         || COMPLETE_TYPE_P (outer_type)))
     return false;
 
   /* If both the inner and outer types are integral types, then the
@@ -270,12 +266,23 @@ useless_type_conversion_p (tree outer_ty
       return true;
     }
 
-  /* For aggregates we rely on TYPE_CANONICAL exclusively and require
-     explicit conversions for types involving to be structurally
-     compared types.  */
+  /* For aggregates compare only the size and mode.  Accesses to fields do have
+     a type information by themselves and thus we only care if we can i.e.
+     use the types in move operations.  */
   else if (AGGREGATE_TYPE_P (inner_type)
           && TREE_CODE (inner_type) == TREE_CODE (outer_type))
-    return false;
+    return (!TYPE_SIZE (outer_type)
+           || (TYPE_SIZE (inner_type)
+               && operand_equal_p (TYPE_SIZE (inner_type),
+                                   TYPE_SIZE (outer_type), 0)));
+
+  else if (TREE_CODE (inner_type) == OFFSET_TYPE
+          && TREE_CODE (inner_type) == TREE_CODE (outer_type))
+    return useless_type_conversion_p (TREE_TYPE (outer_type),
+                                     TREE_TYPE (inner_type))
+          && useless_type_conversion_p
+               (TYPE_OFFSET_BASETYPE (outer_type),
+                TYPE_OFFSET_BASETYPE (inner_type));
 
   return false;
 }

Reply via email to