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

We still have these. I know of Fotran and C++ Fe producing those.
The patch makes fields shared only if they was shared before.  

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