public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch middle-end c c++]: Optimize cost of comp_type_attributes
@ 2011-03-21 17:37 Kai Tietz
  2011-03-24  9:44 ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-21 17:37 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 1391 bytes --]

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

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 7295 bytes --]

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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-21 17:37 [patch middle-end c c++]: Optimize cost of comp_type_attributes Kai Tietz
@ 2011-03-24  9:44 ` Jason Merrill
  2011-03-24 10:30   ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-03-24  9:44 UTC (permalink / raw)
  To: Kai Tietz; +Cc: GCC Patches

On 03/21/2011 06:36 PM, Kai Tietz wrote:
> +      attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a)),
> +			       CONST_CAST_TREE (a2));

I might use as->name for the name, and change lookup_attribute to take a 
const_tree rather than use CONST_CAST_TREE.

> +  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;
> +	}

Once we've walked the first list, we don't need to compare the values of 
common attributes again; for each attribute in the second list either it 
does appear in the first list and we've already established that they 
match, or it doesn't appear in the first list and we're done.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24  9:44 ` Jason Merrill
@ 2011-03-24 10:30   ` Kai Tietz
  2011-03-24 10:56     ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-24 10:30 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2084 bytes --]

2011/3/24 Jason Merrill <jason@redhat.com>:
> On 03/21/2011 06:36 PM, Kai Tietz wrote:
>>
>> +      attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a)),
>> +                              CONST_CAST_TREE (a2));
>
> I might use as->name for the name, and change lookup_attribute to take a
> const_tree rather than use CONST_CAST_TREE.

I changed patch to use as->name here instead.  The CONST_CAST_TREE
part - as we discussed on irc - is necessary, as lookup_attribute
returns as result a non-const tree.

>> +  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;
>> +       }
>
> Once we've walked the first list, we don't need to compare the values of
> common attributes again; for each attribute in the second list either it
> does appear in the first list and we've already established that they match,
> or it doesn't appear in the first list and we're done.

Yes

Updated patch attached. Ok for apply to trunk?

Regards,
Kai



-- 
|  (\_/) This is Bunny. Copy and paste
| (='.'=) Bunny into your signature to help
| (")_(") him gain world domination

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 6904 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-24 08:23:42.441173500 +0100
+++ gcc/gcc/c-typeck.c	2011-03-24 09:24:53.445892300 +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-24 08:23:42.443173500 +0100
+++ gcc/gcc/cp/decl.c	2011-03-24 09:24:53.573408500 +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-24 08:23:42.444173500 +0100
+++ gcc/gcc/cp/search.c	2011-03-24 09:24:53.645417600 +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-24 08:23:42.495173500 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-24 09:24:53.697424200 +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	2011-03-24 08:23:42.496173500 +0100
+++ gcc/gcc/gimple.c	2011-03-24 09:24:53.793936500 +0100
@@ -3615,7 +3615,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-24 08:23:42.498173500 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-24 09:24:53.831441200 +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-24 08:23:42.499173500 +0100
+++ gcc/gcc/tree.c	2011-03-24 11:25:57.696835000 +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,68 @@ 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 (as->name, 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;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as did this
+	     already in first loop.  */
+	}
+      /* 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-24 08:23:42.619173500 +0100
+++ gcc/gcc/tree.h	2011-03-24 09:24:54.041968000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 10:30   ` Kai Tietz
@ 2011-03-24 10:56     ` Kai Tietz
  2011-03-24 12:00       ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-24 10:56 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 103 bytes --]

Sorry, but I found some commenting issues and reworked them a bit.
Attached is the updated patch.

Kai

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 6906 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-24 08:23:42.441173500 +0100
+++ gcc/gcc/c-typeck.c	2011-03-24 09:24:53.445892300 +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-24 08:23:42.443173500 +0100
+++ gcc/gcc/cp/decl.c	2011-03-24 09:24:53.573408500 +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-24 08:23:42.444173500 +0100
+++ gcc/gcc/cp/search.c	2011-03-24 09:24:53.645417600 +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-24 08:23:42.495173500 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-24 09:24:53.697424200 +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	2011-03-24 08:23:42.496173500 +0100
+++ gcc/gcc/gimple.c	2011-03-24 09:24:53.793936500 +0100
@@ -3615,7 +3615,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-24 08:23:42.498173500 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-24 09:24:53.831441200 +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-24 08:23:42.499173500 +0100
+++ gcc/gcc/tree.c	2011-03-24 11:54:43.225949400 +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,67 @@ 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 (as->name, 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;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as we did this
+	     already in first loop.  */
+	}
+      /* All types - affecting identity - are equal, so
+         there is no need to call target hook for comparison.  */
+      if (!a)
+        return 1;
+    }
+  /* As some type combinations - like default calling-convention - might
+     be compatible, we have to call the target hook to get the 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-24 08:23:42.619173500 +0100
+++ gcc/gcc/tree.h	2011-03-24 09:24:54.041968000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 10:56     ` Kai Tietz
@ 2011-03-24 12:00       ` Jason Merrill
  2011-03-24 17:06         ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-03-24 12:00 UTC (permalink / raw)
  To: Kai Tietz; +Cc: GCC Patches

On 03/24/2011 11:56 AM, Kai Tietz wrote:
> +      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)

How about splitting this out into a separate function that can compare 
either list or expression arguments?  That would also be useful for 
merge_attributes and attribute_list_contained.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 12:00       ` Jason Merrill
@ 2011-03-24 17:06         ` Kai Tietz
  2011-03-24 17:11           ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-24 17:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 1187 bytes --]

2011/3/24 Jason Merrill <jason@redhat.com>:
> How about splitting this out into a separate function that can compare
> either list or expression arguments?  That would also be useful for
> merge_attributes and attribute_list_contained.
>
> Jason
>

Ok, here is the patch

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.
       (attribute_equal): New static helper function.
       (comp_type_attributes): New function.
       (merge_attributes): Use attribute_equal for comparison.
       (attribute_list_contained): Likewise.
       * 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.

Regards,
Kai

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 8805 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-24 08:23:42.441173500 +0100
+++ gcc/gcc/c-typeck.c	2011-03-24 09:24:53.445892300 +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-24 08:23:42.443173500 +0100
+++ gcc/gcc/cp/decl.c	2011-03-24 09:24:53.573408500 +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-24 08:23:42.444173500 +0100
+++ gcc/gcc/cp/search.c	2011-03-24 09:24:53.645417600 +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-24 08:23:42.495173500 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-24 09:24:53.697424200 +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	2011-03-24 08:23:42.496173500 +0100
+++ gcc/gcc/gimple.c	2011-03-24 09:24:53.793936500 +0100
@@ -3615,7 +3615,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-24 08:23:42.498173500 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-24 09:24:53.831441200 +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-24 08:23:42.499173500 +0100
+++ gcc/gcc/tree.c	2011-03-24 18:00:04.398084700 +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,74 @@ build_type_attribute_qual_variant (tree
   return ttype;
 }
 
+/* Compare two attributes for identity.  Return true if the attributes
+   are known to be equal; otherwise return false.  */
+
+static bool
+attribute_equal (const_tree attr1, const_tree attr2)
+{
+  if (attr1 == attr2)
+    return true;
+
+  if (TREE_VALUE (attr1) != NULL_TREE
+      && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
+      && TREE_VALUE (attr2) != NULL
+      && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
+    return (simple_cst_list_equal (TREE_VALUE (attr1),
+				   TREE_VALUE (attr2)) == 1);
+
+  return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
+}
+
+/* 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 (as->name, CONST_CAST_TREE (a2));
+      if (!attr || !attribute_equal (a, attr))
+        break;
+    }
+  if (!a)
+    {
+      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
+	{
+	  const struct attribute_spec *as;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as we did this
+	     already in first loop.  */
+	}
+      /* All types - affecting identity - are equal, so
+         there is no need to call target hook for comparison.  */
+      if (!a)
+        return 1;
+    }
+  /* As some type combinations - like default calling-convention - might
+     be compatible, we have to call the target hook to get the final result.  */
+  return targetm.comp_type_attributes (type1, type2);
+}
 
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
@@ -5296,23 +5364,10 @@ merge_attributes (tree a1, tree a2)
 	      tree a;
 	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 attributes);
-		   a != NULL_TREE;
+		   a != NULL_TREE && !attribute_equal (a, a2);
 		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 TREE_CHAIN (a)))
-		{
-		  if (TREE_VALUE (a) != NULL
-		      && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
-		      && TREE_VALUE (a2) != NULL
-		      && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
-		    {
-		      if (simple_cst_list_equal (TREE_VALUE (a),
-						 TREE_VALUE (a2)) == 1)
-			break;
-		    }
-		  else if (simple_cst_equal (TREE_VALUE (a),
-					     TREE_VALUE (a2)) == 1)
-		    break;
-		}
+		;
 	      if (a == NULL_TREE)
 		{
 		  a1 = copy_node (a2);
@@ -6250,24 +6305,12 @@ attribute_list_contained (const_tree l1,
 	 const_tree.  */
       for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    CONST_CAST_TREE(l1));
-	   attr != NULL_TREE;
+	   attr != NULL_TREE && !attribute_equal (t2, attr);
 	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    TREE_CHAIN (attr)))
-	{
-	  if (TREE_VALUE (t2) != NULL
-	      && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
-	      && TREE_VALUE (attr) != NULL
-	      && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
-	    {
-	      if (simple_cst_list_equal (TREE_VALUE (t2),
-					 TREE_VALUE (attr)) == 1)
-		break;
-	    }
-	  else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
-	    break;
-	}
+	;
 
-      if (attr == 0)
+      if (attr == NULL_TREE)
 	return 0;
     }
 
Index: gcc/gcc/tree.h
===================================================================
--- gcc.orig/gcc/tree.h	2011-03-24 08:23:42.619173500 +0100
+++ gcc/gcc/tree.h	2011-03-24 09:24:54.041968000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 17:06         ` Kai Tietz
@ 2011-03-24 17:11           ` Jason Merrill
  2011-03-24 17:41             ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-03-24 17:11 UTC (permalink / raw)
  To: Kai Tietz; +Cc: GCC Patches

On 03/24/2011 06:06 PM, Kai Tietz wrote:
> +/* Compare two attributes for identity.  Return true if the attributes
> +   are known to be equal; otherwise return false.  */
> +
> +static bool
> +attribute_equal (const_tree attr1, const_tree attr2)
> +{
> +  if (attr1 == attr2)
> +    return true;
> +

Shouldn't this compare the TREE_VALUEs?

This function is also assuming that the TREE_PURPOSEs name the same 
attribute.  I had figured that we would pull out the TREE_VALUE in the 
caller, but doing it in here is fine too as long as the function is 
documented as making that assumption.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 17:11           ` Jason Merrill
@ 2011-03-24 17:41             ` Kai Tietz
  2011-03-24 19:44               ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-24 17:41 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 775 bytes --]

2011/3/24 Jason Merrill <jason@redhat.com>:
> On 03/24/2011 06:06 PM, Kai Tietz wrote:
>>
>> +/* Compare two attributes for identity.  Return true if the attributes
>> +   are known to be equal; otherwise return false.  */
>> +
>> +static bool
>> +attribute_equal (const_tree attr1, const_tree attr2)
>> +{
>> +  if (attr1 == attr2)
>> +    return true;
>> +
>
> Shouldn't this compare the TREE_VALUEs?
>
> This function is also assuming that the TREE_PURPOSEs name the same
> attribute.  I had figured that we would pull out the TREE_VALUE in the
> caller, but doing it in here is fine too as long as the function is
> documented as making that assumption.
>
> Jason
>

I added an note to the documentation of the helper function. Ok by this?

Kai

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 8893 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-24 08:23:42.441173500 +0100
+++ gcc/gcc/c-typeck.c	2011-03-24 09:24:53.445892300 +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-24 08:23:42.443173500 +0100
+++ gcc/gcc/cp/decl.c	2011-03-24 09:24:53.573408500 +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-24 08:23:42.444173500 +0100
+++ gcc/gcc/cp/search.c	2011-03-24 09:24:53.645417600 +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-24 08:23:42.495173500 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-24 09:24:53.697424200 +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	2011-03-24 08:23:42.496173500 +0100
+++ gcc/gcc/gimple.c	2011-03-24 09:24:53.793936500 +0100
@@ -3615,7 +3615,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-24 08:23:42.498173500 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-24 09:24:53.831441200 +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-24 08:23:42.499173500 +0100
+++ gcc/gcc/tree.c	2011-03-24 18:39:38.461052400 +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,77 @@ build_type_attribute_qual_variant (tree
   return ttype;
 }
 
+/* Compare two attributes for identity.  Return true if the attributes
+   are known to be equal; otherwise return false.
+   NOTE: This function is assuming that the TREE_PURPOSEs name the same
+   attribute.
+*/
+
+static bool
+attribute_equal (const_tree attr1, const_tree attr2)
+{
+  if (attr1 == attr2)
+    return true;
+
+  if (TREE_VALUE (attr1) != NULL_TREE
+      && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
+      && TREE_VALUE (attr2) != NULL
+      && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
+    return (simple_cst_list_equal (TREE_VALUE (attr1),
+				   TREE_VALUE (attr2)) == 1);
+
+  return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
+}
+
+/* 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 (as->name, CONST_CAST_TREE (a2));
+      if (!attr || !attribute_equal (a, attr))
+        break;
+    }
+  if (!a)
+    {
+      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
+	{
+	  const struct attribute_spec *as;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as we did this
+	     already in first loop.  */
+	}
+      /* All types - affecting identity - are equal, so
+         there is no need to call target hook for comparison.  */
+      if (!a)
+        return 1;
+    }
+  /* As some type combinations - like default calling-convention - might
+     be compatible, we have to call the target hook to get the final result.  */
+  return targetm.comp_type_attributes (type1, type2);
+}
 
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
@@ -5296,23 +5367,10 @@ merge_attributes (tree a1, tree a2)
 	      tree a;
 	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 attributes);
-		   a != NULL_TREE;
+		   a != NULL_TREE && !attribute_equal (a, a2);
 		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 TREE_CHAIN (a)))
-		{
-		  if (TREE_VALUE (a) != NULL
-		      && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
-		      && TREE_VALUE (a2) != NULL
-		      && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
-		    {
-		      if (simple_cst_list_equal (TREE_VALUE (a),
-						 TREE_VALUE (a2)) == 1)
-			break;
-		    }
-		  else if (simple_cst_equal (TREE_VALUE (a),
-					     TREE_VALUE (a2)) == 1)
-		    break;
-		}
+		;
 	      if (a == NULL_TREE)
 		{
 		  a1 = copy_node (a2);
@@ -6250,24 +6308,12 @@ attribute_list_contained (const_tree l1,
 	 const_tree.  */
       for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    CONST_CAST_TREE(l1));
-	   attr != NULL_TREE;
+	   attr != NULL_TREE && !attribute_equal (t2, attr);
 	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    TREE_CHAIN (attr)))
-	{
-	  if (TREE_VALUE (t2) != NULL
-	      && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
-	      && TREE_VALUE (attr) != NULL
-	      && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
-	    {
-	      if (simple_cst_list_equal (TREE_VALUE (t2),
-					 TREE_VALUE (attr)) == 1)
-		break;
-	    }
-	  else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
-	    break;
-	}
+	;
 
-      if (attr == 0)
+      if (attr == NULL_TREE)
 	return 0;
     }
 
Index: gcc/gcc/tree.h
===================================================================
--- gcc.orig/gcc/tree.h	2011-03-24 08:23:42.619173500 +0100
+++ gcc/gcc/tree.h	2011-03-24 09:24:54.041968000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 17:41             ` Kai Tietz
@ 2011-03-24 19:44               ` Kai Tietz
  2011-03-25  9:34                 ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-24 19:44 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 1074 bytes --]

2011/3/24 Kai Tietz <ktietz70@googlemail.com>:
> 2011/3/24 Jason Merrill <jason@redhat.com>:
>> On 03/24/2011 06:06 PM, Kai Tietz wrote:
>>>
>>> +/* Compare two attributes for identity.  Return true if the attributes
>>> +   are known to be equal; otherwise return false.  */
>>> +
>>> +static bool
>>> +attribute_equal (const_tree attr1, const_tree attr2)
>>> +{
>>> +  if (attr1 == attr2)
>>> +    return true;
>>> +
>>
>> Shouldn't this compare the TREE_VALUEs?
>>
>> This function is also assuming that the TREE_PURPOSEs name the same
>> attribute.  I had figured that we would pull out the TREE_VALUE in the
>> caller, but doing it in here is fine too as long as the function is
>> documented as making that assumption.
>>
>> Jason
>>
>
> I added an note to the documentation of the helper function. Ok by this?
>
> Kai
>

I thought a bit about it and renamed function's name to
attribute_value_equal and adjusted helper functions comment to point
out that just value identity is checked by it.  Previous variant was a
bit weak.

Kai

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 8847 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-24 08:23:42.441173500 +0100
+++ gcc/gcc/c-typeck.c	2011-03-24 09:24:53.445892300 +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-24 08:23:42.443173500 +0100
+++ gcc/gcc/cp/decl.c	2011-03-24 09:24:53.573408500 +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-24 08:23:42.444173500 +0100
+++ gcc/gcc/cp/search.c	2011-03-24 09:24:53.645417600 +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-24 08:23:42.495173500 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-24 09:24:53.697424200 +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	2011-03-24 08:23:42.496173500 +0100
+++ gcc/gcc/gimple.c	2011-03-24 09:24:53.793936500 +0100
@@ -3615,7 +3615,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-24 08:23:42.498173500 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-24 09:24:53.831441200 +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-24 08:23:42.499173500 +0100
+++ gcc/gcc/tree.c	2011-03-24 20:42:37.699096700 +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,75 @@ build_type_attribute_qual_variant (tree
   return ttype;
 }
 
+/* Compare two attributes for their value identity.  Return true if the attribute
+   values are known to be equal; otherwise return false.
+*/
+
+static bool
+attribute_value_equal (const_tree attr1, const_tree attr2)
+{
+  if (attr1 == attr2)
+    return true;
+
+  if (TREE_VALUE (attr1) != NULL_TREE
+      && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
+      && TREE_VALUE (attr2) != NULL
+      && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
+    return (simple_cst_list_equal (TREE_VALUE (attr1),
+				   TREE_VALUE (attr2)) == 1);
+
+  return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
+}
+
+/* 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 (as->name, CONST_CAST_TREE (a2));
+      if (!attr || !attribute_value_equal (a, attr))
+        break;
+    }
+  if (!a)
+    {
+      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
+	{
+	  const struct attribute_spec *as;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as we did this
+	     already in first loop.  */
+	}
+      /* All types - affecting identity - are equal, so
+         there is no need to call target hook for comparison.  */
+      if (!a)
+        return 1;
+    }
+  /* As some type combinations - like default calling-convention - might
+     be compatible, we have to call the target hook to get the final result.  */
+  return targetm.comp_type_attributes (type1, type2);
+}
 
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
@@ -5296,23 +5365,10 @@ merge_attributes (tree a1, tree a2)
 	      tree a;
 	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 attributes);
-		   a != NULL_TREE;
+		   a != NULL_TREE && !attribute_value_equal (a, a2);
 		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 TREE_CHAIN (a)))
-		{
-		  if (TREE_VALUE (a) != NULL
-		      && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
-		      && TREE_VALUE (a2) != NULL
-		      && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
-		    {
-		      if (simple_cst_list_equal (TREE_VALUE (a),
-						 TREE_VALUE (a2)) == 1)
-			break;
-		    }
-		  else if (simple_cst_equal (TREE_VALUE (a),
-					     TREE_VALUE (a2)) == 1)
-		    break;
-		}
+		;
 	      if (a == NULL_TREE)
 		{
 		  a1 = copy_node (a2);
@@ -6250,24 +6306,12 @@ attribute_list_contained (const_tree l1,
 	 const_tree.  */
       for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    CONST_CAST_TREE(l1));
-	   attr != NULL_TREE;
+	   attr != NULL_TREE && !attribute_value_equal (t2, attr);
 	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    TREE_CHAIN (attr)))
-	{
-	  if (TREE_VALUE (t2) != NULL
-	      && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
-	      && TREE_VALUE (attr) != NULL
-	      && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
-	    {
-	      if (simple_cst_list_equal (TREE_VALUE (t2),
-					 TREE_VALUE (attr)) == 1)
-		break;
-	    }
-	  else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
-	    break;
-	}
+	;
 
-      if (attr == 0)
+      if (attr == NULL_TREE)
 	return 0;
     }
 
Index: gcc/gcc/tree.h
===================================================================
--- gcc.orig/gcc/tree.h	2011-03-24 08:23:42.619173500 +0100
+++ gcc/gcc/tree.h	2011-03-24 09:24:54.041968000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-24 19:44               ` Kai Tietz
@ 2011-03-25  9:34                 ` Jason Merrill
  2011-03-25  9:52                   ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-03-25  9:34 UTC (permalink / raw)
  To: Kai Tietz; +Cc: GCC Patches

On 03/24/2011 08:44 PM, Kai Tietz wrote:
> +static bool
> +attribute_value_equal (const_tree attr1, const_tree attr2)
> +{
> +  if (attr1 == attr2)
> +    return true;

I still think this test should be comparing TREE_VALUEs.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-25  9:34                 ` Jason Merrill
@ 2011-03-25  9:52                   ` Kai Tietz
  2011-03-25 10:06                     ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Kai Tietz @ 2011-03-25  9:52 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 438 bytes --]

2011/3/25 Jason Merrill <jason@redhat.com>:
> On 03/24/2011 08:44 PM, Kai Tietz wrote:
>>
>> +static bool
>> +attribute_value_equal (const_tree attr1, const_tree attr2)
>> +{
>> +  if (attr1 == attr2)
>> +    return true;
>
> I still think this test should be comparing TREE_VALUEs.
>
> Jason
>

Ok, it makes sense to check here for value indentity instead of
identity of list-node. Thanks. Updated patch attached.

Kai

[-- Attachment #2: comp_type_attributes.txt --]
[-- Type: text/plain, Size: 8873 bytes --]

Index: gcc/gcc/c-typeck.c
===================================================================
--- gcc.orig/gcc/c-typeck.c	2011-03-25 09:27:47.101196700 +0100
+++ gcc/gcc/c-typeck.c	2011-03-25 09:35:35.038738400 +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-25 09:27:47.102196700 +0100
+++ gcc/gcc/cp/decl.c	2011-03-25 09:35:35.090745000 +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-25 09:27:47.103196700 +0100
+++ gcc/gcc/cp/search.c	2011-03-25 09:35:35.145752000 +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-25 09:27:47.110196700 +0100
+++ gcc/gcc/cp/typeck.c	2011-03-25 09:35:35.164754400 +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	2011-03-25 09:27:47.112196700 +0100
+++ gcc/gcc/gimple.c	2011-03-25 09:35:35.206259700 +0100
@@ -3615,7 +3615,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-25 09:27:47.113196700 +0100
+++ gcc/gcc/tree-ssa.c	2011-03-25 09:35:35.231762900 +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-25 09:31:02.378615000 +0100
+++ gcc/gcc/tree.c	2011-03-25 10:48:15.141401100 +0100
@@ -4287,7 +4287,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);
@@ -4300,6 +4300,75 @@ build_type_attribute_qual_variant (tree
   return ttype;
 }
 
+/* Compare two attributes for their value identity.  Return true if the
+   attribute values are known to be equal; otherwise return false.
+*/
+
+static bool
+attribute_value_equal (const_tree attr1, const_tree attr2)
+{
+  if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
+    return true;
+
+  if (TREE_VALUE (attr1) != NULL_TREE
+      && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
+      && TREE_VALUE (attr2) != NULL
+      && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
+    return (simple_cst_list_equal (TREE_VALUE (attr1),
+				   TREE_VALUE (attr2)) == 1);
+
+  return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
+}
+
+/* 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 (as->name, CONST_CAST_TREE (a2));
+      if (!attr || !attribute_value_equal (a, attr))
+        break;
+    }
+  if (!a)
+    {
+      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
+	{
+	  const struct attribute_spec *as;
+
+	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  if (!as || as->affects_type_identity == false)
+	    continue;
+
+	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
+	    break;
+	  /* We don't need to compare trees again, as we did this
+	     already in first loop.  */
+	}
+      /* All types - affecting identity - are equal, so
+         there is no need to call target hook for comparison.  */
+      if (!a)
+        return 1;
+    }
+  /* As some type combinations - like default calling-convention - might
+     be compatible, we have to call the target hook to get the final result.  */
+  return targetm.comp_type_attributes (type1, type2);
+}
 
 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    is ATTRIBUTE.
@@ -5300,23 +5369,10 @@ merge_attributes (tree a1, tree a2)
 	      tree a;
 	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 attributes);
-		   a != NULL_TREE;
+		   a != NULL_TREE && !attribute_value_equal (a, a2);
 		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 TREE_CHAIN (a)))
-		{
-		  if (TREE_VALUE (a) != NULL
-		      && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
-		      && TREE_VALUE (a2) != NULL
-		      && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
-		    {
-		      if (simple_cst_list_equal (TREE_VALUE (a),
-						 TREE_VALUE (a2)) == 1)
-			break;
-		    }
-		  else if (simple_cst_equal (TREE_VALUE (a),
-					     TREE_VALUE (a2)) == 1)
-		    break;
-		}
+		;
 	      if (a == NULL_TREE)
 		{
 		  a1 = copy_node (a2);
@@ -6254,24 +6310,12 @@ attribute_list_contained (const_tree l1,
 	 const_tree.  */
       for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    CONST_CAST_TREE(l1));
-	   attr != NULL_TREE;
+	   attr != NULL_TREE && !attribute_value_equal (t2, attr);
 	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    TREE_CHAIN (attr)))
-	{
-	  if (TREE_VALUE (t2) != NULL
-	      && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
-	      && TREE_VALUE (attr) != NULL
-	      && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
-	    {
-	      if (simple_cst_list_equal (TREE_VALUE (t2),
-					 TREE_VALUE (attr)) == 1)
-		break;
-	    }
-	  else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
-	    break;
-	}
+	;
 
-      if (attr == 0)
+      if (attr == NULL_TREE)
 	return 0;
     }
 
Index: gcc/gcc/tree.h
===================================================================
--- gcc.orig/gcc/tree.h	2011-03-25 09:31:02.416119700 +0100
+++ gcc/gcc/tree.h	2011-03-25 09:35:35.295271000 +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
 {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-25  9:52                   ` Kai Tietz
@ 2011-03-25 10:06                     ` Jason Merrill
  2011-03-25 10:28                       ` Kai Tietz
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2011-03-25 10:06 UTC (permalink / raw)
  To: Kai Tietz; +Cc: GCC Patches

OK.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch middle-end c c++]: Optimize cost of comp_type_attributes
  2011-03-25 10:06                     ` Jason Merrill
@ 2011-03-25 10:28                       ` Kai Tietz
  0 siblings, 0 replies; 13+ messages in thread
From: Kai Tietz @ 2011-03-25 10:28 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

2011/3/25 Jason Merrill <jason@redhat.com>:
> OK.
>
> Jason
>

Committed at revision 171445.

Thanks,
Kai

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-03-25 10:28 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-21 17:37 [patch middle-end c c++]: Optimize cost of comp_type_attributes Kai Tietz
2011-03-24  9:44 ` Jason Merrill
2011-03-24 10:30   ` Kai Tietz
2011-03-24 10:56     ` Kai Tietz
2011-03-24 12:00       ` Jason Merrill
2011-03-24 17:06         ` Kai Tietz
2011-03-24 17:11           ` Jason Merrill
2011-03-24 17:41             ` Kai Tietz
2011-03-24 19:44               ` Kai Tietz
2011-03-25  9:34                 ` Jason Merrill
2011-03-25  9:52                   ` Kai Tietz
2011-03-25 10:06                     ` Jason Merrill
2011-03-25 10:28                       ` Kai Tietz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).