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.