On Wed, Jul 6, 2016 at 12:44 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Wed, Jul 6, 2016 at 12:21 PM, Richard Biener > <richard.guent...@gmail.com> wrote: >> On Wed, Jul 6, 2016 at 11:33 AM, Eric Botcazou <ebotca...@adacore.com> wrote: >>>> I see. I think the solution is to perform cgraph/varpool merging >>>> before attempting to read in >>>> the global decl stream. IIRC Micha had (old) patches for this. >>> >>> How can you merge varpool nodes if you haven't merged types? > > You merge them just in the way the linker instructs you via the > resolution table. > >>>> But I wonder why we don't tree-merge 'n' here (from my C example) and >>>> thus figure >>>> that the type domain of x is equal? Or is it that 'n' and 'x' are in >>>> the same SCC (they >>>> referece each other in some way)? In this case the bug would be that we >>>> fail to treat them equal optimistically. That said, I don't see how >>>> TYPE_CANONICAL computation is relevant - what is relevant is the failure to >>>> merge the two types. >>>> In debugging this I'd start to see if the hashes are not equal or if >>>> they are equal >>>> at which node we consider them to differ. >>> >>> We just have 2 different DECLs with different DECL_UIDs, the definition >>> from a >>> compilation unit and a reference from another compilation unit, so the >>> hashes >>> naturally differ too. What's supposed to have them reconciled at this >>> point? >> >> I am talking about tree/SCC merging which happily merges global decls as >> well. >> It uses custom hashing (see lto-streamer-out.c:hash_tree) which doesn't hash >> DECL_UID (obviously). This merging process should be optimistic for all >> nodes >> in the same SCC as well. >> >> That said, I expect the types to be tree merged and wonder why they are not. >> >> If they were merged they'd obviously share TYPE_CANONICAL because there >> would be only one type to compute TYPE_CANONICAL for. > > It probably boils down to one unit refering to the DECL with DECL_EXTERNAL set > and one to the DECL with TREE_STATIC set? This would mean that > hashing/comparing > should be set up to "merge" those but the merging ultimatively rejected by > some > toplevel logic (so we get users merged). But as said, early symtab > merging would > fix this as well.
So sth like Index: gcc/lto-streamer-out.c =================================================================== --- gcc/lto-streamer-out.c (revision 238039) +++ gcc/lto-streamer-out.c (working copy) @@ -996,7 +996,7 @@ hash_tree (struct streamer_tree_cache_d else hstate.add_flag (TREE_NO_WARNING (t)); hstate.add_flag (TREE_NOTHROW (t)); - hstate.add_flag (TREE_STATIC (t)); + //hstate.add_flag (TREE_STATIC (t)); hstate.add_flag (TREE_PROTECTED (t)); hstate.add_flag (TREE_DEPRECATED (t)); if (code != TREE_BINFO) @@ -1050,7 +1050,7 @@ hash_tree (struct streamer_tree_cache_d hstate.add_flag (DECL_ARTIFICIAL (t)); hstate.add_flag (DECL_USER_ALIGN (t)); hstate.add_flag (DECL_PRESERVE_P (t)); - hstate.add_flag (DECL_EXTERNAL (t)); + //hstate.add_flag (DECL_EXTERNAL (t)); hstate.add_flag (DECL_GIMPLE_REG_P (t)); hstate.commit_flag (); hstate.add_int (DECL_ALIGN (t)); Index: gcc/lto/lto.c =================================================================== --- gcc/lto/lto.c (revision 238039) +++ gcc/lto/lto.c (working copy) @@ -1263,7 +1263,8 @@ compare_tree_sccs_1 (tree t1, tree t2, t tree t1_ = (E1), t2_ = (E2); \ if (t1_ != t2_ \ && (!t1_ || !t2_ \ - || !TREE_VISITED (t2_) \ + || (!TREE_VISITED (t2_) \ + && !same_decls (t1_, t2_)) \ || (!TREE_ASM_WRITTEN (t2_) \ && !compare_tree_sccs_1 (t1_, t2_, map)))) \ return false; \ plus the magic new function same_decls which would check if the trees are var/function decls with the same assembler name. The function can't use the cgraph as that is not yet read in unfortunately - I still think we should do that so we can see the prevailing nodes early. Richard. > > Richard. > >> Richard. >> >>> The TYPE_CANONICAL computation is relevant because, with GCC 6, the >>> criterion >>> for compatibility of pointer types is the alias set, which is based on the >>> TYPE_CANONICAL of the pointed-to type, so we fail to merge pointer types >>> because warn_type_compatibility_p returns non-zero if TYPE_CANONICAL >>> differs. >>> >>> -- >>> Eric Botcazou