On Sun, Jun 29, 2014 at 12:44 AM, Jan Hubicka <hubi...@ucw.cz> wrote:
> Hi,
> this patch fixes another problem where we manage to produce a variant of
> variadic array that has different TYPE_SIZE (but an equivalent expression).
> This happens because remap_type_1 blindly copies all expressions referred by
> variadic type while for variants it may just reuse ones it earlier copied when
> producing a copy of the main variant.
>
> Bootstrapped/regtested x86_64-linux, lto-bootstrapped and tested on Firefox
> build with the main variant checking patch in, comitted.

Note that we do have variant types which do _not_ share the fields list
of the main variant (see PR61456).  Not sure if your patches fix that.
But if they didn't yet the following patch silently re-write those types.

Richard.

> Honza
>
>         * tree-inline.c (remap_type_1): Do not duplicate fields
>         that are shared in between type and its main variant.
> Index: tree-inline.c
> ===================================================================
> --- tree-inline.c       (revision 212098)
> +++ tree-inline.c       (working copy)
> @@ -451,6 +451,8 @@ remap_type_1 (tree type, copy_body_data
>    TYPE_POINTER_TO (new_tree) = NULL;
>    TYPE_REFERENCE_TO (new_tree) = NULL;
>
> +  /* Copy all types that may contain references to local variables; be sure 
> to
> +     preserve sharing in between type and its main variant when possible.  */
>    switch (TREE_CODE (new_tree))
>      {
>      case INTEGER_TYPE:
> @@ -458,40 +460,72 @@ remap_type_1 (tree type, copy_body_data
>      case FIXED_POINT_TYPE:
>      case ENUMERAL_TYPE:
>      case BOOLEAN_TYPE:
> -      t = TYPE_MIN_VALUE (new_tree);
> -      if (t && TREE_CODE (t) != INTEGER_CST)
> -        walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL);
> -
> -      t = TYPE_MAX_VALUE (new_tree);
> -      if (t && TREE_CODE (t) != INTEGER_CST)
> -        walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL);
> +      if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> +       {
> +         gcc_checking_assert (TYPE_MIN_VALUE (type) == TYPE_MIN_VALUE 
> (TYPE_MAIN_VARIANT (type)));
> +         gcc_checking_assert (TYPE_MAX_VALUE (type) == TYPE_MAX_VALUE 
> (TYPE_MAIN_VARIANT (type)));
> +
> +         TYPE_MIN_VALUE (new_tree) = TYPE_MIN_VALUE (TYPE_MAIN_VARIANT 
> (new_tree));
> +         TYPE_MAX_VALUE (new_tree) = TYPE_MAX_VALUE (TYPE_MAIN_VARIANT 
> (new_tree));
> +       }
> +      else
> +       {
> +         t = TYPE_MIN_VALUE (new_tree);
> +         if (t && TREE_CODE (t) != INTEGER_CST)
> +           walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, 
> NULL);
> +
> +         t = TYPE_MAX_VALUE (new_tree);
> +         if (t && TREE_CODE (t) != INTEGER_CST)
> +           walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, 
> NULL);
> +       }
>        return new_tree;
>
>      case FUNCTION_TYPE:
> -      TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> -      walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
> +      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> +         && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
> +       TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
> +      else
> +        TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> +      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> +         && TYPE_ARG_TYPES (type) == TYPE_ARG_TYPES (TYPE_MAIN_VARIANT 
> (type)))
> +       TYPE_ARG_TYPES (new_tree) = TYPE_ARG_TYPES (TYPE_MAIN_VARIANT 
> (new_tree));
> +      else
> +        walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
>        return new_tree;
>
>      case ARRAY_TYPE:
> -      TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
> -      TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
> +      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
> +         && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
> +       TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
> +
> +      if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> +       {
> +         gcc_checking_assert (TYPE_DOMAIN (type) == TYPE_DOMAIN 
> (TYPE_MAIN_VARIANT (type)));
> +         TYPE_DOMAIN (new_tree) = TYPE_DOMAIN (TYPE_MAIN_VARIANT (new_tree));
> +       }
> +      else
> +       TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
>        break;
>
>      case RECORD_TYPE:
>      case UNION_TYPE:
>      case QUAL_UNION_TYPE:
> -      {
> -       tree f, nf = NULL;
> -
> -       for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
> -         {
> -           t = remap_decl (f, id);
> -           DECL_CONTEXT (t) = new_tree;
> -           DECL_CHAIN (t) = nf;
> -           nf = t;
> -         }
> -       TYPE_FIELDS (new_tree) = nreverse (nf);
> -      }
> +      if (TYPE_MAIN_VARIANT (type) != type
> +         && TYPE_FIELDS (type) == TYPE_FIELDS (TYPE_MAIN_VARIANT (type)))
> +       TYPE_FIELDS (new_tree) = TYPE_FIELDS (TYPE_MAIN_VARIANT (new_tree));
> +      else
> +       {
> +         tree f, nf = NULL;
> +
> +         for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
> +           {
> +             t = remap_decl (f, id);
> +             DECL_CONTEXT (t) = new_tree;
> +             DECL_CHAIN (t) = nf;
> +             nf = t;
> +           }
> +         TYPE_FIELDS (new_tree) = nreverse (nf);
> +       }
>        break;
>
>      case OFFSET_TYPE:
> @@ -500,8 +534,20 @@ remap_type_1 (tree type, copy_body_data
>        gcc_unreachable ();
>      }
>
> -  walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
> -  walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
> +  /* All variants of type share the same size, so use the already remaped 
> data.  */
> +  if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
> +    {
> +      gcc_checking_assert (TYPE_SIZE (type) == TYPE_SIZE (TYPE_MAIN_VARIANT 
> (type)));
> +      gcc_checking_assert (TYPE_SIZE_UNIT (type) == TYPE_SIZE_UNIT 
> (TYPE_MAIN_VARIANT (type)));
> +
> +      TYPE_SIZE (new_tree) = TYPE_SIZE (TYPE_MAIN_VARIANT (new_tree));
> +      TYPE_SIZE_UNIT (new_tree) = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT 
> (new_tree));
> +    }
> +  else
> +    {
> +      walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
> +      walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
> +    }
>
>    return new_tree;
>  }

Reply via email to