re PR c/18851 (IMA is slow and could be sped up)
2005-10-02 Andrew Pinski <pinskia@physics.uc.edu> PR c/18851 * c-typeck.c (tagged_tu_seen): Rename to ... (tagged_tu_seen_cache): this and add val field. (comptypes): Move functional to comptypes_internal and free tagged_tu_seen. (comptypes_internal): New function and call comptypes_internal instead of comptypes. Speed up by sibcalling tagged_types_tu_compatible_p. (alloc_tagged_tu_seen): New function (free_all_tagged_tu_seen_up_to): New function. (tagged_types_tu_compatible_p): Return the val of the seen two types. Add that the two types are the same to tagged_tu_seen_base if they are and call comptypes_internal instead of comptypes. <case UNION_TYPE>: Speed up common type where the fields are in the same order. (function_types_compatible_p): Call comptypes_internal instead of comptypes. (type_lists_compatible_p): Likewise. (all functions): s/tagged_tu_seen/tagged_tu_seen_cache/. From-SVN: r104873
This commit is contained in:
parent
aa58883c23
commit
f13c9b2c76
2 changed files with 186 additions and 53 deletions
|
@ -1,3 +1,26 @@
|
|||
2005-10-02 Andrew Pinski <pinskia@physics.uc.edu>
|
||||
|
||||
PR c/18851
|
||||
* c-typeck.c (tagged_tu_seen): Rename to ...
|
||||
(tagged_tu_seen_cache): this and add val field.
|
||||
(comptypes): Move functional to comptypes_internal
|
||||
and free tagged_tu_seen.
|
||||
(comptypes_internal): New function and call comptypes_internal
|
||||
instead of comptypes. Speed up by sibcalling
|
||||
tagged_types_tu_compatible_p.
|
||||
(alloc_tagged_tu_seen): New function
|
||||
(free_all_tagged_tu_seen_up_to): New function.
|
||||
(tagged_types_tu_compatible_p): Return the val of the seen two
|
||||
types.
|
||||
Add that the two types are the same to tagged_tu_seen_base
|
||||
if they are and call comptypes_internal instead of comptypes.
|
||||
<case UNION_TYPE>: Speed up common type where the fields are
|
||||
in the same order.
|
||||
(function_types_compatible_p): Call comptypes_internal instead of
|
||||
comptypes.
|
||||
(type_lists_compatible_p): Likewise.
|
||||
(all functions): s/tagged_tu_seen/tagged_tu_seen_cache/.
|
||||
|
||||
2005-10-02 Matthias Klose <doko@debian.org>
|
||||
|
||||
* doc/invoke.texi: Fix typo and speling error.
|
||||
|
|
216
gcc/c-typeck.c
216
gcc/c-typeck.c
|
@ -105,7 +105,21 @@ static void readonly_error (tree, enum lvalue_use);
|
|||
static int lvalue_or_else (tree, enum lvalue_use);
|
||||
static int lvalue_p (tree);
|
||||
static void record_maybe_used_decl (tree);
|
||||
|
||||
static int comptypes_internal (tree, tree);
|
||||
/* This is a cache to hold if two types are compatible or not. */
|
||||
|
||||
struct tagged_tu_seen_cache {
|
||||
const struct tagged_tu_seen_cache * next;
|
||||
tree t1;
|
||||
tree t2;
|
||||
/* The return value of tagged_types_tu_compatible_p if we had seen
|
||||
these two types already. */
|
||||
int val;
|
||||
};
|
||||
|
||||
static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
|
||||
static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
|
||||
|
||||
/* Do `exp = require_complete_type (exp);' to make sure exp
|
||||
does not have an incomplete type. (That includes void types.) */
|
||||
|
||||
|
@ -663,13 +677,29 @@ common_type (tree t1, tree t2)
|
|||
|
||||
return c_common_type (t1, t2);
|
||||
}
|
||||
|
||||
|
||||
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
|
||||
or various other operations. Return 2 if they are compatible
|
||||
but a warning may be needed if you use them together. */
|
||||
|
||||
int
|
||||
comptypes (tree type1, tree type2)
|
||||
{
|
||||
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
|
||||
int val;
|
||||
|
||||
val = comptypes_internal (type1, type2);
|
||||
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
|
||||
|
||||
return val;
|
||||
}
|
||||
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
|
||||
or various other operations. Return 2 if they are compatible
|
||||
but a warning may be needed if you use them together. This
|
||||
differs from comptypes, in that we don't free the seen types. */
|
||||
|
||||
static int
|
||||
comptypes_internal (tree type1, tree type2)
|
||||
{
|
||||
tree t1 = type1;
|
||||
tree t2 = type2;
|
||||
|
@ -737,7 +767,7 @@ comptypes (tree type1, tree type2)
|
|||
|| TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
|
||||
break;
|
||||
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
|
||||
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
|
||||
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)));
|
||||
break;
|
||||
|
||||
case FUNCTION_TYPE:
|
||||
|
@ -754,7 +784,7 @@ comptypes (tree type1, tree type2)
|
|||
|
||||
/* Target types must match incl. qualifiers. */
|
||||
if (TREE_TYPE (t1) != TREE_TYPE (t2)
|
||||
&& 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
|
||||
&& 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))))
|
||||
return 0;
|
||||
|
||||
/* Sizes must match unless one is missing or variable. */
|
||||
|
@ -787,12 +817,16 @@ comptypes (tree type1, tree type2)
|
|||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
if (val != 1 && !same_translation_unit_p (t1, t2))
|
||||
val = tagged_types_tu_compatible_p (t1, t2);
|
||||
{
|
||||
if (attrval != 2)
|
||||
return tagged_types_tu_compatible_p (t1, t2);
|
||||
val = tagged_types_tu_compatible_p (t1, t2);
|
||||
}
|
||||
break;
|
||||
|
||||
case VECTOR_TYPE:
|
||||
val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
|
||||
&& comptypes (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -861,21 +895,48 @@ same_translation_unit_p (tree t1, tree t2)
|
|||
return t1 == t2;
|
||||
}
|
||||
|
||||
/* The C standard says that two structures in different translation
|
||||
units are compatible with each other only if the types of their
|
||||
fields are compatible (among other things). So, consider two copies
|
||||
of this structure: */
|
||||
/* Allocate the seen two types, assuming that they are compatible. */
|
||||
|
||||
struct tagged_tu_seen {
|
||||
const struct tagged_tu_seen * next;
|
||||
tree t1;
|
||||
tree t2;
|
||||
};
|
||||
static struct tagged_tu_seen_cache *
|
||||
alloc_tagged_tu_seen_cache (tree t1, tree t2)
|
||||
{
|
||||
struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache));
|
||||
tu->next = tagged_tu_seen_base;
|
||||
tu->t1 = t1;
|
||||
tu->t2 = t2;
|
||||
|
||||
tagged_tu_seen_base = tu;
|
||||
|
||||
/* The C standard says that two structures in different translation
|
||||
units are compatible with each other only if the types of their
|
||||
fields are compatible (among other things). We assume that they
|
||||
are compatible until proven otherwise when building the cache.
|
||||
An example where this can occur is:
|
||||
struct a
|
||||
{
|
||||
struct a *next;
|
||||
};
|
||||
If we are comparing this against a similar struct in another TU,
|
||||
and did not assume they were compatiable, we end up with an infinite
|
||||
loop. */
|
||||
tu->val = 1;
|
||||
return tu;
|
||||
}
|
||||
|
||||
/* Can they be compatible with each other? We choose to break the
|
||||
recursion by allowing those types to be compatible. */
|
||||
/* Free the seen types until we get to TU_TIL. */
|
||||
|
||||
static const struct tagged_tu_seen * tagged_tu_seen_base;
|
||||
static void
|
||||
free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
|
||||
{
|
||||
const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
|
||||
while (tu != tu_til)
|
||||
{
|
||||
struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu;
|
||||
tu = tu1->next;
|
||||
free (tu1);
|
||||
}
|
||||
tagged_tu_seen_base = tu_til;
|
||||
}
|
||||
|
||||
/* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
|
||||
compatible. If the two types are not the same (which has been
|
||||
|
@ -917,73 +978,123 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
|
|||
return 1;
|
||||
|
||||
{
|
||||
const struct tagged_tu_seen * tts_i;
|
||||
const struct tagged_tu_seen_cache * tts_i;
|
||||
for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
|
||||
if (tts_i->t1 == t1 && tts_i->t2 == t2)
|
||||
return 1;
|
||||
return tts_i->val;
|
||||
}
|
||||
|
||||
switch (TREE_CODE (t1))
|
||||
{
|
||||
case ENUMERAL_TYPE:
|
||||
{
|
||||
|
||||
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
|
||||
/* Speed up the case where the type values are in the same order. */
|
||||
tree tv1 = TYPE_VALUES (t1);
|
||||
tree tv2 = TYPE_VALUES (t2);
|
||||
|
||||
if (tv1 == tv2)
|
||||
return 1;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
|
||||
{
|
||||
if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
|
||||
break;
|
||||
if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tv1 == NULL_TREE && tv2 == NULL_TREE)
|
||||
return 1;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (tv1 == NULL_TREE || tv2 == NULL_TREE)
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
|
||||
{
|
||||
s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
|
||||
if (s2 == NULL
|
||||
|| simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
case UNION_TYPE:
|
||||
{
|
||||
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
|
||||
if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Speed up the common case where the fields are in the same order. */
|
||||
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
|
||||
s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
|
||||
{
|
||||
int result;
|
||||
|
||||
|
||||
if (DECL_NAME (s1) == NULL
|
||||
|| DECL_NAME (s1) != DECL_NAME (s2))
|
||||
break;
|
||||
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
|
||||
if (result == 0)
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
if (result == 2)
|
||||
needs_warning = true;
|
||||
|
||||
if (TREE_CODE (s1) == FIELD_DECL
|
||||
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
|
||||
DECL_FIELD_BIT_OFFSET (s2)) != 1)
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!s1 && !s2)
|
||||
{
|
||||
tu->val = needs_warning ? 2 : 1;
|
||||
return tu->val;
|
||||
}
|
||||
|
||||
for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
|
||||
{
|
||||
bool ok = false;
|
||||
struct tagged_tu_seen tts;
|
||||
|
||||
tts.next = tagged_tu_seen_base;
|
||||
tts.t1 = t1;
|
||||
tts.t2 = t2;
|
||||
tagged_tu_seen_base = &tts;
|
||||
|
||||
if (DECL_NAME (s1) != NULL)
|
||||
for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
|
||||
if (DECL_NAME (s1) == DECL_NAME (s2))
|
||||
{
|
||||
int result;
|
||||
result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
|
||||
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
|
||||
if (result == 0)
|
||||
break;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
if (result == 2)
|
||||
needs_warning = true;
|
||||
|
||||
|
@ -995,21 +1106,19 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
|
|||
ok = true;
|
||||
break;
|
||||
}
|
||||
tagged_tu_seen_base = tts.next;
|
||||
if (!ok)
|
||||
return 0;
|
||||
{
|
||||
tu->val = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return needs_warning ? 2 : 1;
|
||||
tu->val = needs_warning ? 2 : 10;
|
||||
return tu->val;
|
||||
}
|
||||
|
||||
case RECORD_TYPE:
|
||||
{
|
||||
struct tagged_tu_seen tts;
|
||||
|
||||
tts.next = tagged_tu_seen_base;
|
||||
tts.t1 = t1;
|
||||
tts.t2 = t2;
|
||||
tagged_tu_seen_base = &tts;
|
||||
struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
|
||||
|
||||
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
|
||||
s1 && s2;
|
||||
|
@ -1019,7 +1128,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
|
|||
if (TREE_CODE (s1) != TREE_CODE (s2)
|
||||
|| DECL_NAME (s1) != DECL_NAME (s2))
|
||||
break;
|
||||
result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
|
||||
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
|
||||
if (result == 0)
|
||||
break;
|
||||
if (result == 2)
|
||||
|
@ -1030,10 +1139,11 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
|
|||
DECL_FIELD_BIT_OFFSET (s2)) != 1)
|
||||
break;
|
||||
}
|
||||
tagged_tu_seen_base = tts.next;
|
||||
if (s1 && s2)
|
||||
return 0;
|
||||
return needs_warning ? 2 : 1;
|
||||
tu->val = 0;
|
||||
else
|
||||
tu->val = needs_warning ? 2 : 1;
|
||||
return tu->val;
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -1070,7 +1180,7 @@ function_types_compatible_p (tree f1, tree f2)
|
|||
if (TYPE_VOLATILE (ret2))
|
||||
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
|
||||
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
|
||||
val = comptypes (ret1, ret2);
|
||||
val = comptypes_internal (ret1, ret2);
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -1151,7 +1261,7 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
else if (TREE_CODE (a1) == ERROR_MARK
|
||||
|| TREE_CODE (a2) == ERROR_MARK)
|
||||
;
|
||||
else if (!(newval = comptypes (mv1, mv2)))
|
||||
else if (!(newval = comptypes_internal (mv1, mv2)))
|
||||
{
|
||||
/* Allow wait (union {union wait *u; int *i} *)
|
||||
and wait (union wait *) to be compatible. */
|
||||
|
@ -1170,7 +1280,7 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
if (mv3 && mv3 != error_mark_node
|
||||
&& TREE_CODE (mv3) != ARRAY_TYPE)
|
||||
mv3 = TYPE_MAIN_VARIANT (mv3);
|
||||
if (comptypes (mv3, mv2))
|
||||
if (comptypes_internal (mv3, mv2))
|
||||
break;
|
||||
}
|
||||
if (memb == 0)
|
||||
|
@ -1191,7 +1301,7 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
if (mv3 && mv3 != error_mark_node
|
||||
&& TREE_CODE (mv3) != ARRAY_TYPE)
|
||||
mv3 = TYPE_MAIN_VARIANT (mv3);
|
||||
if (comptypes (mv3, mv1))
|
||||
if (comptypes_internal (mv3, mv1))
|
||||
break;
|
||||
}
|
||||
if (memb == 0)
|
||||
|
|
Loading…
Add table
Reference in a new issue