> On Sun, Jun 29, 2014 at 12:44 AM, Jan Hubicka <[email protected]> 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;
> > }