This speeds up LTO type merging by only calling gimple_register_type on those types that possibly can require fixup (by means on how the uniquification process is designed). This makes the behavior for pre-loaded type nodes consistent, as we do not throw them at gimple_register_type directly but at the moment we do so indirectly if they are refered to by any streamed in tree node.
A slightly more complex variant of the patch (un-setting TYPE_VISITED after processing) has passed LTO bootstrap and regtest on x86_64-unknown-linux-gnu as well as a SPEC 2k6 build. Re-bootstrapping and testing together with some other patch now. Richard. 2011-12-21 Richard Guenther <rguent...@suse.de> lto/ * lto.c (GIMPLE_REGISTER_TYPE): New define. (LTO_FIXUP_TREE): Use it. (uniquify_nodes): Mark new non-prevailing types and avoid calling gimple_register_type on others. (lto_read_decls): Add comment. Index: gcc/lto/lto.c =================================================================== *** gcc/lto/lto.c (revision 182525) --- gcc/lto/lto.c (working copy) *************** remember_with_vars (tree t) *** 306,318 **** *(tree *) htab_find_slot (tree_with_vars, t, INSERT) = t; } #define LTO_FIXUP_TREE(tt) \ do \ { \ if (tt) \ { \ if (TYPE_P (tt)) \ ! (tt) = gimple_register_type (tt); \ if (VAR_OR_FUNCTION_DECL_P (tt) && TREE_PUBLIC (tt)) \ remember_with_vars (t); \ } \ --- 306,321 ---- *(tree *) htab_find_slot (tree_with_vars, t, INSERT) = t; } + #define GIMPLE_REGISTER_TYPE(tt) \ + (TREE_VISITED (tt) ? gimple_register_type (tt) : tt) + #define LTO_FIXUP_TREE(tt) \ do \ { \ if (tt) \ { \ if (TYPE_P (tt)) \ ! (tt) = GIMPLE_REGISTER_TYPE (tt); \ if (VAR_OR_FUNCTION_DECL_P (tt) && TREE_PUBLIC (tt)) \ remember_with_vars (t); \ } \ *************** uniquify_nodes (struct data_in *data_in, *** 731,737 **** { tree t = VEC_index (tree, cache->nodes, i); if (t && TYPE_P (t)) ! gimple_register_type (t); } /* Second fixup all trees in the new cache entries. */ --- 734,747 ---- { tree t = VEC_index (tree, cache->nodes, i); if (t && TYPE_P (t)) ! { ! tree newt = gimple_register_type (t); ! /* Mark non-prevailing types so we fix them up. No need ! to reset that flag afterwards - nothing that refers ! to those types is left and they are collected. */ ! if (newt != t) ! TREE_VISITED (t) = 1; ! } } /* Second fixup all trees in the new cache entries. */ *************** uniquify_nodes (struct data_in *data_in, *** 749,755 **** continue; /* Now try to find a canonical variant of T itself. */ ! t = gimple_register_type (t); if (t == oldt) { --- 759,765 ---- continue; /* Now try to find a canonical variant of T itself. */ ! t = GIMPLE_REGISTER_TYPE (t); if (t == oldt) { *************** uniquify_nodes (struct data_in *data_in, *** 771,777 **** } /* Query our new main variant. */ ! mv = gimple_register_type (TYPE_MAIN_VARIANT (t)); /* If we were the variant leader and we get replaced ourselves drop all variants from our list. */ --- 781,787 ---- } /* Query our new main variant. */ ! mv = GIMPLE_REGISTER_TYPE (TYPE_MAIN_VARIANT (t)); /* If we were the variant leader and we get replaced ourselves drop all variants from our list. */ *************** lto_read_decls (struct lto_file_decl_dat *** 901,906 **** --- 919,927 ---- data_in = lto_data_in_create (decl_data, (const char *) data + string_offset, header->string_size, resolutions); + /* We do not uniquify the pre-loaded cache entries, those are middle-end + internal types that should not be merged. */ + /* Read the global declarations and types. */ while (ib_main.p < ib_main.len) {