On Fri, 20 May 2011, Michael Matz wrote: > Hi, > > for various changes we can run into the situation that frontends fill the > cache with a different number of common nodes than the LTO frontend, > leading to confusion of which numbers mean which tree. This can happen > when some global trees are NULL, or when some global trees are > pointer-equal to others in one frontend but not the other. We can't > really avoid filling the cache with doubled pointers if need be. So, do > away with the pointer map and just always append to the cache. > > Based on a patch from Richi. Regstrapping on x86_64-linux in progress. > Okay for trunk?
Ok. Thanks, Richard. > > Ciao, > Michael. > > * lto-streamer.c (lto_record_common_node): Don't track seen nodes, > use lto_streamer_cache_append directly instead of returning a VEC. > (preload_common_node): Remove. > (lto_get_common_nodes): Rename to lto_preload_common_nodes, don't > track seen nodes. > (lto_streamer_cache_create): Call lto_preload_common_nodes. > > Index: lto-streamer.c > =================================================================== > --- lto-streamer.c (revision 173940) > +++ lto-streamer.c (working copy) > @@ -475,17 +475,21 @@ lto_streamer_cache_get (struct lto_strea > } > > > -/* Record NODE in COMMON_NODES if it is not NULL and is not already in > - SEEN_NODES. */ > +/* Record NODE in CACHE. */ > > static void > -lto_record_common_node (tree *nodep, VEC(tree, heap) **common_nodes, > - struct pointer_set_t *seen_nodes) > +lto_record_common_node (struct lto_streamer_cache_d *cache, tree *nodep) > { > tree node = *nodep; > > - if (node == NULL_TREE) > - return; > + /* We have to make sure to fill exactly the same number of > + elements for all frontends. That can include NULL trees. > + As our hash table can't deal with zero entries we'll simply stream > + a random other tree. A NULL tree never will be looked up so it > + doesn't matter which tree we replace it with, just to be sure > + use error_mark_node. */ > + if (!node) > + node = error_mark_node; > > if (TYPE_P (node)) > { > @@ -500,28 +504,32 @@ lto_record_common_node (tree *nodep, VEC > *nodep = node; > } > > - /* Return if node is already seen. */ > - if (pointer_set_insert (seen_nodes, node)) > - return; > - > - VEC_safe_push (tree, heap, *common_nodes, node); > + lto_streamer_cache_append (cache, node); > > if (POINTER_TYPE_P (node) > || TREE_CODE (node) == COMPLEX_TYPE > || TREE_CODE (node) == ARRAY_TYPE) > - lto_record_common_node (&TREE_TYPE (node), common_nodes, seen_nodes); > + lto_record_common_node (cache, &TREE_TYPE (node)); > + else if (TREE_CODE (node) == RECORD_TYPE) > + { > + /* The FIELD_DECLs of structures should be shared, so that every > + COMPONENT_REF uses the same tree node when referencing a field. > + Pointer equality between FIELD_DECLs is used by the alias > + machinery to compute overlapping memory references (See > + nonoverlapping_component_refs_p). */ > + tree f; > + for (f = TYPE_FIELDS (node); f; f = TREE_CHAIN (f)) > + lto_record_common_node (cache, &f); > + } > } > > - > -/* Generate a vector of common nodes and make sure they are merged > +/* Preload common nodes into CACHE and make sure they are merged > properly according to the gimple type table. */ > > -static VEC(tree,heap) * > -lto_get_common_nodes (void) > +static void > +lto_preload_common_nodes (struct lto_streamer_cache_d *cache) > { > unsigned i; > - VEC(tree,heap) *common_nodes = NULL; > - struct pointer_set_t *seen_nodes; > > /* The MAIN_IDENTIFIER_NODE is normally set up by the front-end, but the > LTO back-end must agree. Currently, the only languages that set this > @@ -545,59 +553,24 @@ lto_get_common_nodes (void) > gcc_assert (fileptr_type_node == ptr_type_node); > gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node); > > - seen_nodes = pointer_set_create (); > - > /* Skip itk_char. char_type_node is shared with the appropriately > signed variant. */ > for (i = itk_signed_char; i < itk_none; i++) > - lto_record_common_node (&integer_types[i], &common_nodes, seen_nodes); > + lto_record_common_node (cache, &integer_types[i]); > > for (i = 0; i < TYPE_KIND_LAST; i++) > - lto_record_common_node (&sizetype_tab[i], &common_nodes, seen_nodes); > + lto_record_common_node (cache, &sizetype_tab[i]); > > for (i = 0; i < TI_MAX; i++) > - lto_record_common_node (&global_trees[i], &common_nodes, seen_nodes); > - > - pointer_set_destroy (seen_nodes); > - > - return common_nodes; > -} > - > - > -/* Assign an index to tree node T and enter it in the streamer cache > - CACHE. */ > - > -static void > -preload_common_node (struct lto_streamer_cache_d *cache, tree t) > -{ > - gcc_assert (t); > - > - lto_streamer_cache_insert (cache, t, NULL); > - > - /* The FIELD_DECLs of structures should be shared, so that every > - COMPONENT_REF uses the same tree node when referencing a field. > - Pointer equality between FIELD_DECLs is used by the alias > - machinery to compute overlapping memory references (See > - nonoverlapping_component_refs_p). */ > - if (TREE_CODE (t) == RECORD_TYPE) > - { > - tree f; > - > - for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f)) > - preload_common_node (cache, f); > - } > + lto_record_common_node (cache, &global_trees[i]); > } > > - > /* Create a cache of pickled nodes. */ > > struct lto_streamer_cache_d * > lto_streamer_cache_create (void) > { > struct lto_streamer_cache_d *cache; > - VEC(tree, heap) *common_nodes; > - unsigned i; > - tree node; > > cache = XCNEW (struct lto_streamer_cache_d); > > @@ -606,12 +579,7 @@ lto_streamer_cache_create (void) > /* Load all the well-known tree nodes that are always created by > the compiler on startup. This prevents writing them out > unnecessarily. */ > - common_nodes = lto_get_common_nodes (); > - > - FOR_EACH_VEC_ELT (tree, common_nodes, i, node) > - preload_common_node (cache, node); > - > - VEC_free(tree, heap, common_nodes); > + lto_preload_common_nodes (cache); > > return cache; > } > > -- Richard Guenther <rguent...@suse.de> Novell / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer