Hi,
this implements the idea we discussed at Cauldron to not use TYPE_CANONICAL for
useless_type_conversion_p.  The basic idea is that TYPE_CANONICAL is language
specific and should not be part of definition of the Gimple type system that 
should
be quite agnostic of language.

useless_type_conversion_p clearly is about operations on the type and those do 
not
depends on TYPE_CANONICAL or alias info. For LTO and C/Fortran interpoerability
rules we are forced to make TYPE_CANONICAL more coarse than it needs to be
that results in troubles with useless_type_conversion_p use.

After dropping the check I needed to solve two issues. First is that we need a
definition of useless conversions for aggregates. As discussed earlier I made
it to depend only on size. The basic idea is that only operations you can do on
gimple with those are moves and field accesses. Field accesses have
corresponding type into in COMPONENT_REF or MEM_REF, so we do not care about
conversions of those.  This caused three Ada failures on PPC64, because we can
not move between structures of same size but different mode.

Other failure introduced was 2 cases in C++ testsuite because we currently
do not handle OFFSET_TYPE at all.  I added the obvious check for TREE_TYPE
and BASE_TYPE to be compatible.
I think we can allow more of conversions between OFFSET_TYPEs and integer
types, but I would like to leave this for incremental changes. (It is probalby
not too important anyway).

Bootstrapped/regtested x86_64-linux except Ada and ppc64-linux for all languages
including Ada. OK?

I have reviewed the uses of useless_type_conversion_p on non-register types
and there are some oddities, will send separate patches for those.

Honza

        * 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,11 +87,6 @@ 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)
@@ -270,12 +265,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)))
+          && TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+  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