Hello, this patch does some search-cost optimization for comp_type_attributes target hook. By recent patch about diagnostic of attributes affecting type indentity, it is possible to avoid some searching for such kind of type checks.
In general it would be possible to remove this target-hook completely, but by doing so we would need to introduce an new hook which returns the current default calling-convention. To avoid this the check just avoids call of comp_type_attributes target hook for cases where all type identity affecting attributes are compatible. If the don't match the target hook gets called to handle target's default calling convention proper. ChangeLog gcc/ 2011-03-11 Kai Tietz * c-typeck.c (comptypes_internal): Replace target hook call of comp_type_attributes by version in tree.c file. * gimple.c (gimple_types_compatible_p_1): Likewise. * tree-ssa.c (useless_type_conversion_p): Likewise. * tree.c (build_type_attribute_qual_variant): Likewise. (comp_type_attributes): New function. * tree.h (comp_type_attributes): New prototype. ChangeLog cp/ 2011-03-11 Kai Tietz * decl.c (decls_match): Replace target hook call of comp_type_attributes by version in tree.c file. * search.c (check_final_overrider): Likewise. * typeck.c (structural_comptypes): Likewise. Tested for x86_64-pc-linux-gnu, and for x86_64-w64-mingw32. Ok for apply? Regards, Kai
Index: gcc/gcc/c-typeck.c =================================================================== --- gcc.orig/gcc/c-typeck.c 2011-01-27 08:57:07.000000000 +0100 +++ gcc/gcc/c-typeck.c 2011-03-21 11:05:45.345143000 +0100 @@ -1079,7 +1079,7 @@ comptypes_internal (const_tree type1, co return 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ - if (!(attrval = targetm.comp_type_attributes (t1, t2))) + if (!(attrval = comp_type_attributes (t1, t2))) return 0; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ Index: gcc/gcc/cp/decl.c =================================================================== --- gcc.orig/gcc/cp/decl.c 2011-03-17 18:55:30.000000000 +0100 +++ gcc/gcc/cp/decl.c 2011-03-21 11:12:00.528285200 +0100 @@ -1012,8 +1012,8 @@ decls_match (tree newdecl, tree olddecl) types_match = compparms (p1, p2) && (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE - || targetm.comp_type_attributes (TREE_TYPE (newdecl), - TREE_TYPE (olddecl)) != 0); + || comp_type_attributes (TREE_TYPE (newdecl), + TREE_TYPE (olddecl)) != 0); } else types_match = 0; Index: gcc/gcc/cp/search.c =================================================================== --- gcc.orig/gcc/cp/search.c 2011-03-06 12:15:05.000000000 +0100 +++ gcc/gcc/cp/search.c 2011-03-21 11:12:36.760386100 +0100 @@ -1897,7 +1897,7 @@ check_final_overrider (tree overrider, t } /* Check for conflicting type attributes. */ - if (!targetm.comp_type_attributes (over_type, base_type)) + if (!comp_type_attributes (over_type, base_type)) { error ("conflicting type attributes specified for %q+#D", overrider); error (" overriding %q+#D", basefn); Index: gcc/gcc/cp/typeck.c =================================================================== --- gcc.orig/gcc/cp/typeck.c 2011-03-17 18:55:30.000000000 +0100 +++ gcc/gcc/cp/typeck.c 2011-03-21 11:13:12.125876900 +0100 @@ -1338,7 +1338,7 @@ structural_comptypes (tree t1, tree t2, /* If we get here, we know that from a target independent POV the types are the same. Make sure the target attributes are also the same. */ - return targetm.comp_type_attributes (t1, t2); + return comp_type_attributes (t1, t2); } /* Return true if T1 and T2 are related as allowed by STRICT. STRICT Index: gcc/gcc/gimple.c =================================================================== --- gcc.orig/gcc/gimple.c 2010-12-02 20:10:55.000000000 +0100 +++ gcc/gcc/gimple.c 2011-03-21 11:06:27.447989400 +0100 @@ -3616,7 +3616,7 @@ gimple_types_compatible_p_1 (tree t1, tr state, sccstack, sccstate, sccstate_obstack)) goto different_types; - if (!targetm.comp_type_attributes (t1, t2)) + if (!comp_type_attributes (t1, t2)) goto different_types; if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) Index: gcc/gcc/tree-ssa.c =================================================================== --- gcc.orig/gcc/tree-ssa.c 2011-03-17 18:55:31.000000000 +0100 +++ gcc/gcc/tree-ssa.c 2011-03-21 11:07:24.362216600 +0100 @@ -1438,7 +1438,7 @@ useless_type_conversion_p (tree outer_ty /* Defer to the target if necessary. */ if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type)) - return targetm.comp_type_attributes (outer_type, inner_type) != 0; + return comp_type_attributes (outer_type, inner_type) != 0; return true; } Index: gcc/gcc/tree.c =================================================================== --- gcc.orig/gcc/tree.c 2011-03-17 18:54:25.000000000 +0100 +++ gcc/gcc/tree.c 2011-03-21 11:04:26.742161700 +0100 @@ -4283,7 +4283,7 @@ build_type_attribute_qual_variant (tree its canonical type, we will need to use structural equality checks for this type. */ if (TYPE_STRUCTURAL_EQUALITY_P (ttype) - || !targetm.comp_type_attributes (ntype, ttype)) + || !comp_type_attributes (ntype, ttype)) SET_TYPE_STRUCTURAL_EQUALITY (ntype); else if (TYPE_CANONICAL (ntype) == ntype) TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); @@ -4296,6 +4296,78 @@ build_type_attribute_qual_variant (tree return ttype; } +/* Return 0 if the attributes for two types are incompatible, 1 if they + are compatible, and 2 if they are nearly compatible (which causes a + warning to be generated). */ +int +comp_type_attributes (const_tree type1, const_tree type2) +{ + const_tree a1 = TYPE_ATTRIBUTES (type1); + const_tree a2 = TYPE_ATTRIBUTES (type2); + const_tree a; + + if (a1 == a2) + return 1; + for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + const_tree attr; + as = lookup_attribute_spec (TREE_PURPOSE (a)); + if (!as || as->affects_type_identity == false) + continue; + attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a)), + CONST_CAST_TREE (a2)); + if (!attr) + break; + + if (TREE_VALUE (a) != NULL_TREE + && TREE_CODE (TREE_VALUE (a)) == TREE_LIST + && TREE_VALUE (attr) != NULL + && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (a), + TREE_VALUE (attr)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (attr)) == 1) + break; + } + if (!a) + { + for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + const_tree attr; + as = lookup_attribute_spec (TREE_PURPOSE (a)); + if (!as || as->affects_type_identity == false) + continue; + attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a)), + CONST_CAST_TREE (a1)); + if (!attr) + break; + + if (TREE_VALUE (a) != NULL_TREE + && TREE_CODE (TREE_VALUE (a)) == TREE_LIST + && TREE_VALUE (attr) != NULL + && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST) + { + if (simple_cst_list_equal (TREE_VALUE (a), + TREE_VALUE (attr)) == 1) + break; + } + else if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (attr)) == 1) + break; + } + /* All types affecting identity are equal, so + there is no need to call target host for comparision. */ + if (!a) + return 1; + } + /* As some types might be compatible for target, we have to call + for attributes affecting type identity the target hook + to get final result. */ + return targetm.comp_type_attributes (type1, type2); +} /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. Index: gcc/gcc/tree.h =================================================================== --- gcc.orig/gcc/tree.h 2011-03-21 09:04:39.000000000 +0100 +++ gcc/gcc/tree.h 2011-03-21 09:50:06.218247100 +0100 @@ -4286,6 +4286,11 @@ extern tree build_type_attribute_variant extern tree build_decl_attribute_variant (tree, tree); extern tree build_type_attribute_qual_variant (tree, tree, int); +/* Return 0 if the attributes for two types are incompatible, 1 if they + are compatible, and 2 if they are nearly compatible (which causes a + warning to be generated). */ +extern int comp_type_attributes (const_tree, const_tree); + /* Structure describing an attribute and a function to handle it. */ struct attribute_spec {