Hi,
so this is variant without the BLKmode subreg that passes testing on 
ppc64-linux.
The case of parlallel and copy_blkmode_to_reg appears to be handled upstream
in expand_assignment.

Honza

        * expr.c (store_expr_with_bounds): Handle aggregate moves from
        BLKmode.
        * gimple-expr.c (useless_type_conversion_p): Do not use TYPE_CANONICAL
        to define gimple type system; compare aggregates only by size.
Index: expr.c
===================================================================
--- expr.c      (revision 228267)
+++ expr.c      (working copy)
@@ -5462,7 +5462,13 @@ store_expr_with_bounds (tree exp, rtx ta
     {
       if (GET_MODE (temp) != GET_MODE (target) && GET_MODE (temp) != VOIDmode)
        {
-         if (GET_MODE (target) == BLKmode)
+         if (GET_MODE (temp) == BLKmode && GET_MODE (target) != BLKmode)
+           {
+             gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (exp)));
+             gcc_assert (MEM_P (temp));
+             temp = adjust_address_nv (temp, GET_MODE (target), 0);
+           }
+         else if (GET_MODE (target) == BLKmode)
            {
              /* Handle calls that return BLKmode values in registers.  */
              if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
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)));
+
+  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