On Fri, 2 Oct 2015, Jan Hubicka wrote:

> > 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.

Hmm.  I still think that the mode shouldn't be relevant.  Isn't this
only about the cases where the aggregate ends up not having its address
taken and thus we don't allocate a stack slot for it but end up
using a register with mode?  ISTR expansion has special cases dealing
with some of the mismatch cases and a fallback spilling to the stack.

I think we should fix that rather than disallowing aggregate assignments
(which are memory ops to GIMPLE) based on the mode of the aggregate.

> 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;
> -

So I'd like to see an incremental patch committed that just removes
this early check and retains it for the AGGREGATE_TYPE_P and
OFFSET_TYPE cases.

Such patch is pre-approved.

>    /* 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)));

!TYPE_SIZE should return false, not true, unless both inner and outer
type have !TYPE_SIZE.  Btw, I wonder whether using TYPE_CANONICAL
for AGGREGATE_TYPE_Ps still makes sense because alias-compatible
types should have the same size, no?

> +  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));

I'd rather sort out the offset type issue differently and stay
with TYPE_CANONICAL compare here for that time.

Richard.

>    return false;
>  }
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to