Hi,

On Wed, 20 Apr 2011, Richard Guenther wrote:

> > + /* A hashtable of trees that potentially refer to variables or functions
> > +    that must be replaced with their prevailing variant.  */
> > + static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node))) 
> > htab_t
> > +   tree_with_vars;
> > + /* A hashtable of top-level trees that can potentially be merged with 
> > trees
> > +    from other compilation units.  */
> 
> It would have been nice to have the top-level tree merging as a separate
> patch, as I am not convinced it is correct, but see below ...

I'll split it out.

> > +       {
> > +         tree *t2 = (tree *) htab_find_slot (top_decls, t, INSERT);
> > +         if (*t2)
> > +           t = *t2;
> > +         else
> > +           *t2 = t;
> 
> I don't think we can share TREE_LISTs.  Where do they hang off
> when you do this?  Are not all but one of those dead?  All
> TREE_LIST manipulation routines I know of do not even think about
> the possibility of shared lists.

Well, it clearly works for the use in global trees :-)  The problem I 
solved with this is, that all trees are stored in the reader cache.  If 
(say) two function types, or enum types are merged, one of their 
TYPE_ARG_TYPES or TYPE_VALUES lists should be dead.  But as they're still 
referred from the cache they aren't collected.  I could remove them from 
the cache in a similar way to how I deal with the FIELD_DECLs.  Or I could 
store tree_list nodes not in the cache at all.  The latter seems more 
worthwhile to me, so I'm going to try this.

> > + /* Fix up fields of a field_decl T.  */
> > +
> > + static void
> > + lto_ft_field_decl (tree t)
> > + {
> > +   lto_ft_decl_common (t);
> > +   LTO_FIXUP_TYPE (DECL_FIELD_OFFSET (t));
> > +   LTO_FIXUP_TYPE (DECL_BIT_FIELD_TYPE (t));
> > +   LTO_FIXUP_TYPE (DECL_QUALIFIER (t));
> 
> here (and earlier) we had some no_fixup_p asserts.  What happened to
> them?

no_fixup_p checked only that the tree wasn't a type or a 
var/function_decl.

> In particular, don't we need to fixup the DECL_FIELD_BIT_OFFSET 
> integer-cst?

But I was indeed too eager to remove those lines, I should still deal with 
DECL_SECTION_NAME, DECL_FIELD_BIT_OFFSET and BINFO_OFFSET.  Thanks for 
catching this.

> > +
> > +       /* First fixup the fields of T.  */
> > +           lto_fixup_types (t);
> > +
> > +       /* Now try to find a canonical variant of T itself.  */
> > +       if (TYPE_P (t))
> > +       {
> 
> If t is a type, why fix up its field if it may not be the canonical variant?

Because type merging to work sometimes requires already canonicalized 
fields, at least that's what I found in investigating why some types 
weren't merged that should have been.  Hence I'm first canonicalizing all 
fields of everything and then see if something merged.

> > +         if (t == oldt
> > +             && TYPE_MAIN_VARIANT (t) != t)
> > +           {
> > +             /* If this is its own type, link it into the variant
> > +                chain.  */
> > +             TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT 
> > (t));
> > +             TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t;
> 
> Hmm - isn't this taken care of in lto_fixup_types?

Nope.  I've taken it out of the (old) lto_fixup_type, because (now that 
I've removed the seen pointer_set) it can be called for the same type 
multiple times, which would lead to it being included multiple times in 
the NEXT_VARIANT chain.  I found it more clear to do this kind of list 
manipulation at the place where we're sure to see every type only once.

> > +             for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
> > +                  f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
> > +               if (TREE_CODE (f1) == FIELD_DECL
> > +                   && f1 != f2
> 
> This should always be true unless TYPE_FIELDS (t) == TYPE_FIELDS (oldt)

Think shared field_decl chains.  I'll have fixed up the chain for one of 
the type pairs already and can later come to a type referring exactly the 
same field_decls again.

> > +                   && lto_streamer_cache_lookup (cache, f2, &ix))
> 
> This lookup should always succeed, no?

Yes.  I'll assert this.

> > +                 {
> > +                   gcc_assert (DECL_NAME (f1) == DECL_NAME (f2));
> > +                   /* If we're going to replace an element which we'd
> > +                      still visit in the next iterations, we wouldn't
> > +                      handle it, so do it here.  */
> > +                   if (ix < i)
> > +                     lto_fixup_types (f2);
> 
> ?  But it's dead, no?

That is true, but it can refer to integer_cst which I can only fix up by 
walking the fields.  If I don't do that, then even though the field_decl 
will not be in the cache anymore, its integer_cst (and their non-fixed up 
types) will stay uncollected.

> > +                   lto_streamer_cache_insert_at (cache, f1, ix);
> > +                 }
> 
> Btw, nice.  Does this get rid of the need for the field-decl fixup code
> in input_gimple_stmt?

Hmm, it's gross but seems to me still required for the diagnostic and to 
emit the VIEW_CONVERT_EXPR, at least for invalid input code.  OTOH if the 
streamed out code ensures that a field_decl in a component_ref always is 
included in its DECL_CONTEXT, then the new merging should indeed make sure 
that this also holds after streaming in.  Do we have testcases 
specifically trying this code?  greping for "mismatching" in 
testsuite/ doesn't show anything relevant.


Ciao,
Michael.

Reply via email to