On Wed, Apr 20, 2011 at 3:17 PM, Michael Matz <m...@suse.de> wrote: > 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.
Thanks. >> > + { >> > + 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. That sounds like a bug in type-merging. You don't happen to have a small testcase? ;) >> > + 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. Ok. >> > + 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. But only in case the first one is already equal. What I wanted to say is that we shouldn't have partially shared chains, so if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt)) for (...) if (TREE_CODE (f1) == FIELD_DECL) ... should be enough, no? In fact, why restrict fixing up the cache to FIELD_DECLs and not also do it for TYPE_DECLs or FUNCTION_DECLs that may reside in this chain? >> > + && 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. Ick, ok ... maybe amend the comment. >> > + 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. The lto testsuite harness doesn't support dg-error/warning, so there are no testcases. There are testcases that ICEd (type verification) before introducing these fixups though. Richard. > > Ciao, > Michael.