gimple.c (gimple_register_type_1): Do not fiddle with main-variant or pointer-to chains.

2011-05-20  Richard Guenther  <rguenther@suse.de>

	* gimple.c (gimple_register_type_1): Do not fiddle with
	main-variant or pointer-to chains.  Delay all fixup to
	uniquify_nodes.

	lto/
	* lto.c (lto_ft_common): Remove pointer-to chain teardown.
	(lto_ft_type): Move main-variant and pointer-to chain building ...
	(uniquify_nodes): ... here.  Compute TYPE_CANONICAL also here,
	in a separate final loop.

From-SVN: r173938
This commit is contained in:
Richard Guenther 2011-05-20 09:35:03 +00:00 committed by Richard Biener
parent b59eb51cac
commit fb291a1ea7
4 changed files with 135 additions and 212 deletions

View File

@ -1,3 +1,9 @@
2011-05-20 Richard Guenther <rguenther@suse.de>
* gimple.c (gimple_register_type_1): Do not fiddle with
main-variant or pointer-to chains. Delay all fixup to
uniquify_nodes.
2011-05-19 Quentin Neill <quentin.neill@amd.com> 2011-05-19 Quentin Neill <quentin.neill@amd.com>
* config/i386/sse.md (fma4_fmsubadd): Use <ssemodesuffix>. * config/i386/sse.md (fma4_fmsubadd): Use <ssemodesuffix>.

View File

@ -4476,7 +4476,6 @@ gimple_register_type_1 (tree t, bool registering_mv)
{ {
void **slot; void **slot;
gimple_type_leader_entry *leader; gimple_type_leader_entry *leader;
tree mv_leader;
/* If we registered this type before return the cached result. */ /* If we registered this type before return the cached result. */
leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE]; leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE];
@ -4495,91 +4494,23 @@ gimple_register_type_1 (tree t, bool registering_mv)
case we do not care for the main variant leader. */ case we do not care for the main variant leader. */
if (!registering_mv if (!registering_mv
&& TYPE_MAIN_VARIANT (t) != t) && TYPE_MAIN_VARIANT (t) != t)
mv_leader = gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true); gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
else
mv_leader = t;
/* See if we already have an equivalent type registered. */
slot = htab_find_slot (gimple_types, t, INSERT); slot = htab_find_slot (gimple_types, t, INSERT);
if (*slot if (*slot
&& *(tree *)slot != t) && *(tree *)slot != t)
{ {
tree new_type = (tree) *((tree *) slot); tree new_type = (tree) *((tree *) slot);
/* Do not merge types with different addressability. */
gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type));
/* If t is not its main variant then make t unreachable from its
main variant list. Otherwise we'd queue up a lot of duplicates
there. */
if (t != TYPE_MAIN_VARIANT (t))
{
tree tem = TYPE_MAIN_VARIANT (t);
while (tem && TYPE_NEXT_VARIANT (tem) != t)
tem = TYPE_NEXT_VARIANT (tem);
if (tem)
TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
TYPE_NEXT_VARIANT (t) = NULL_TREE;
}
/* If we are a pointer then remove us from the pointer-to or
reference-to chain. Otherwise we'd queue up a lot of duplicates
there. */
if (TREE_CODE (t) == POINTER_TYPE)
{
if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
else
{
tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
while (tem && TYPE_NEXT_PTR_TO (tem) != t)
tem = TYPE_NEXT_PTR_TO (tem);
if (tem)
TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
}
TYPE_NEXT_PTR_TO (t) = NULL_TREE;
}
else if (TREE_CODE (t) == REFERENCE_TYPE)
{
if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
else
{
tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
while (tem && TYPE_NEXT_REF_TO (tem) != t)
tem = TYPE_NEXT_REF_TO (tem);
if (tem)
TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
}
TYPE_NEXT_REF_TO (t) = NULL_TREE;
}
leader->type = t; leader->type = t;
leader->leader = new_type; leader->leader = new_type;
t = new_type; return new_type;
}
else
{
leader->type = t;
leader->leader = t;
/* We're the type leader. Make our TYPE_MAIN_VARIANT valid. */
if (TYPE_MAIN_VARIANT (t) != t
&& TYPE_MAIN_VARIANT (t) != mv_leader)
{
/* Remove us from our main variant list as we are not the variant
leader and the variant leader will change. */
tree tem = TYPE_MAIN_VARIANT (t);
while (tem && TYPE_NEXT_VARIANT (tem) != t)
tem = TYPE_NEXT_VARIANT (tem);
if (tem)
TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
TYPE_NEXT_VARIANT (t) = NULL_TREE;
/* Adjust our main variant. Linking us into its variant list
will happen at fixup time. */
TYPE_MAIN_VARIANT (t) = mv_leader;
}
*slot = (void *) t;
} }
/* If not, insert it to the cache and the hash. */
leader->type = t;
leader->leader = t;
*slot = (void *) t;
return t; return t;
} }

View File

@ -1,3 +1,10 @@
2011-05-20 Richard Guenther <rguenther@suse.de>
* lto.c (lto_ft_common): Remove pointer-to chain teardown.
(lto_ft_type): Move main-variant and pointer-to chain building ...
(uniquify_nodes): ... here. Compute TYPE_CANONICAL also here,
in a separate final loop.
2011-05-19 Richard Guenther <rguenther@suse.de> 2011-05-19 Richard Guenther <rguenther@suse.de>
* lto.c (uniquify_nodes): First register all types before * lto.c (uniquify_nodes): First register all types before

View File

@ -259,45 +259,9 @@ static void lto_fixup_types (tree);
static void static void
lto_ft_common (tree t) lto_ft_common (tree t)
{ {
/* The following re-creates the TYPE_REFERENCE_TO and TYPE_POINTER_TO
lists. We do not stream TYPE_REFERENCE_TO, TYPE_POINTER_TO or
TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO.
First remove us from any pointer list we are on. */
if (TREE_CODE (t) == POINTER_TYPE)
{
if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
else
{
tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
while (tem && TYPE_NEXT_PTR_TO (tem) != t)
tem = TYPE_NEXT_PTR_TO (tem);
if (tem)
TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
}
TYPE_NEXT_PTR_TO (t) = NULL_TREE;
}
else if (TREE_CODE (t) == REFERENCE_TYPE)
{
if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
else
{
tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
while (tem && TYPE_NEXT_REF_TO (tem) != t)
tem = TYPE_NEXT_REF_TO (tem);
if (tem)
TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
}
TYPE_NEXT_REF_TO (t) = NULL_TREE;
}
/* Fixup our type. */ /* Fixup our type. */
LTO_FIXUP_TREE (TREE_TYPE (t)); LTO_FIXUP_TREE (TREE_TYPE (t));
/* Second put us on the list of pointers of the new pointed-to type
if we are a main variant. This is done in lto_ft_type after
fixing up our main variant. */
LTO_FIXUP_TREE (TREE_CHAIN (t)); LTO_FIXUP_TREE (TREE_CHAIN (t));
} }
@ -374,8 +338,6 @@ lto_ft_field_decl (tree t)
static void static void
lto_ft_type (tree t) lto_ft_type (tree t)
{ {
tree tem, mv;
lto_ft_common (t); lto_ft_common (t);
LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t)); LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t));
LTO_FIXUP_TREE (TYPE_SIZE (t)); LTO_FIXUP_TREE (TYPE_SIZE (t));
@ -392,67 +354,6 @@ lto_ft_type (tree t)
LTO_FIXUP_TREE (t->type_non_common.binfo); LTO_FIXUP_TREE (t->type_non_common.binfo);
LTO_FIXUP_TREE (TYPE_CONTEXT (t)); LTO_FIXUP_TREE (TYPE_CONTEXT (t));
/* Compute the canonical type of t and fix that up. From this point
there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
and its type-based alias problems. */
if (!TYPE_CANONICAL (t))
{
TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
LTO_FIXUP_TREE (TYPE_CANONICAL (t));
}
/* The following re-creates proper variant lists while fixing up
the variant leaders. We do not stream TYPE_NEXT_VARIANT so the
variant list state before fixup is broken. */
/* Remove us from our main variant list if we are not the variant leader. */
if (TYPE_MAIN_VARIANT (t) != t)
{
tem = TYPE_MAIN_VARIANT (t);
while (tem && TYPE_NEXT_VARIANT (tem) != t)
tem = TYPE_NEXT_VARIANT (tem);
if (tem)
TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
TYPE_NEXT_VARIANT (t) = NULL_TREE;
}
/* 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. */
if (TYPE_MAIN_VARIANT (t) == t
&& mv != t)
{
tem = t;
while (tem)
{
tree tem2 = TYPE_NEXT_VARIANT (tem);
TYPE_NEXT_VARIANT (tem) = NULL_TREE;
tem = tem2;
}
}
/* Finally adjust our main variant and fix it up. */
TYPE_MAIN_VARIANT (t) = mv;
LTO_FIXUP_TREE (TYPE_MAIN_VARIANT (t));
/* As the second step of reconstructing the pointer chains put us
on the list of pointers of the new pointed-to type
if we are a main variant. See lto_ft_common for the first step. */
if (TREE_CODE (t) == POINTER_TYPE
&& TYPE_MAIN_VARIANT (t) == t)
{
TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
TYPE_POINTER_TO (TREE_TYPE (t)) = t;
}
else if (TREE_CODE (t) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (t) == t)
{
TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
}
} }
/* Fix up fields of a BINFO T. */ /* Fix up fields of a BINFO T. */
@ -608,19 +509,21 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
/* Go backwards because childs streamed for the first time come /* Go backwards because childs streamed for the first time come
as part of their parents, and hence are created after them. */ as part of their parents, and hence are created after them. */
/* First register all types in the cache.
This makes sure to have the original structure in the type cycles
when registering them and computing hashes. */
for (i = len; i-- > from;) for (i = len; i-- > from;)
{ {
tree t = VEC_index (tree, cache->nodes, i); tree t = VEC_index (tree, cache->nodes, i);
if (!t) if (!t
|| !TYPE_P (t))
continue; continue;
/* Now try to find a canonical variant of T itself. */ gimple_register_type (t);
if (TYPE_P (t))
gimple_register_type (t);
} }
/* Go backwards because childs streamed for the first time come /* Second fixup all trees in the new cache entries. */
as part of their parents, and hence are created after them. */
for (i = len; i-- > from;) for (i = len; i-- > from;)
{ {
tree t = VEC_index (tree, cache->nodes, i); tree t = VEC_index (tree, cache->nodes, i);
@ -631,43 +534,103 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
/* First fixup the fields of T. */ /* First fixup the fields of T. */
lto_fixup_types (t); lto_fixup_types (t);
if (!TYPE_P (t))
continue;
/* Now try to find a canonical variant of T itself. */ /* Now try to find a canonical variant of T itself. */
if (TYPE_P (t)) t = gimple_register_type (t);
if (t == oldt)
{ {
t = gimple_register_type (t); /* The following re-creates proper variant lists while fixing up
if (t == oldt the variant leaders. We do not stream TYPE_NEXT_VARIANT so the
&& TYPE_MAIN_VARIANT (t) != t) variant list state before fixup is broken. */
tree tem, mv;
/* Remove us from our main variant list if we are not the
variant leader. */
if (TYPE_MAIN_VARIANT (t) != t)
{ {
/* If this is its own type, link it into the variant chain. */ tem = TYPE_MAIN_VARIANT (t);
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)); while (tem && TYPE_NEXT_VARIANT (tem) != t)
TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t; tem = TYPE_NEXT_VARIANT (tem);
if (tem)
TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
TYPE_NEXT_VARIANT (t) = NULL_TREE;
}
/* 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. */
if (TYPE_MAIN_VARIANT (t) == t
&& mv != t)
{
tem = t;
while (tem)
{
tree tem2 = TYPE_NEXT_VARIANT (tem);
TYPE_NEXT_VARIANT (tem) = NULL_TREE;
tem = tem2;
}
}
/* If we are not our own variant leader link us into our new leaders
variant list. */
if (mv != t)
{
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv);
TYPE_NEXT_VARIANT (mv) = t;
}
/* Finally adjust our main variant and fix it up. */
TYPE_MAIN_VARIANT (t) = mv;
/* The following reconstructs the pointer chains
of the new pointed-to type if we are a main variant. We do
not stream those so they are broken before fixup. */
if (TREE_CODE (t) == POINTER_TYPE
&& TYPE_MAIN_VARIANT (t) == t)
{
TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
TYPE_POINTER_TO (TREE_TYPE (t)) = t;
}
else if (TREE_CODE (t) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (t) == t)
{
TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
} }
} }
if (t != oldt)
else if (RECORD_OR_UNION_TYPE_P (t))
{ {
if (RECORD_OR_UNION_TYPE_P (t)) tree f1, f2;
{ if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt))
tree f1, f2; for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt)) f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt); {
f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) unsigned ix;
{ gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2));
unsigned ix; if (!lto_streamer_cache_lookup (cache, f2, &ix))
gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2)); gcc_unreachable ();
if (!lto_streamer_cache_lookup (cache, f2, &ix)) /* If we're going to replace an element which we'd
gcc_unreachable (); still visit in the next iterations, we wouldn't
/* If we're going to replace an element which we'd handle it, so do it here. We do have to handle it
still visit in the next iterations, we wouldn't even though the field_decl itself will be removed,
handle it, so do it here. We do have to handle it as it could refer to e.g. integer_cst which we
even though the field_decl itself will be removed, wouldn't reach via any other way, hence they
as it could refer to e.g. integer_cst which we (and their type) would stay uncollected. */
wouldn't reach via any other way, hence they /* ??? We should rather make sure to replace all
(and their type) would stay uncollected. */ references to f2 with f1. That means handling
if (ix < i) COMPONENT_REFs and CONSTRUCTOR elements in
lto_fixup_types (f2); lto_fixup_types and special-case the field-decl
lto_streamer_cache_insert_at (cache, f1, ix); operand handling. */
} if (ix < i)
} lto_fixup_types (f2);
lto_streamer_cache_insert_at (cache, f1, ix);
}
/* If we found a tree that is equal to oldt replace it in the /* If we found a tree that is equal to oldt replace it in the
cache, so that further users (in the various LTO sections) cache, so that further users (in the various LTO sections)
@ -675,6 +638,22 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
lto_streamer_cache_insert_at (cache, t, i); lto_streamer_cache_insert_at (cache, t, i);
} }
} }
/* Finally compute the canonical type of t. From this point
there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
and its type-based alias problems. This step requires the
TYPE_POINTER_TO lists being present, so make sure it is done
last. */
for (i = len; i-- > from;)
{
tree t = VEC_index (tree, cache->nodes, i);
if (!t
|| !TYPE_P (t))
continue;
if (!TYPE_CANONICAL (t))
TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
}
} }
/* Read all the symbols from buffer DATA, using descriptors in DECL_DATA. /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.