This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto] Fix gimple_types_compatible_p


I've been meaning to revise this for a while.  The quirky version
we had before was causing SRA to get confused because CCP was
folding a structure reference the wrong way (thinking that struct
Bar and struct Baz were compatible in this test case).

The change to free_lang_data_in_type is needed to remove
TYPE_DECLs from unions.  Otherwise, gimple_types_compatible_p was
getting into infinite recursion cycles.

Tested on x86_64 and i686.


Diego.


	* gimple.c (gimple_types_compatible_p): Call itself
	recursively when comparing fields of aggregates.
	Handle unions.
	Honor TYPE_CANONICAL and pointer equality.

	* tree.c (free_lang_data_in_type): Remove non-FIELD_DECLs
	from UNION_TYPE and QUAL_UNION_TYPE.

testsuite/ChangeLog.lto

	* gcc.dg/lto/20090219_0.c: Add -fPIC.
	* g++.dg/lto/20090221_0.C: New.


Index: tree.c
===================================================================
--- tree.c	(revision 144372)
+++ tree.c	(working copy)
@@ -3825,9 +3825,11 @@ free_lang_data_in_type (tree type)
 	}
     }
 
-  /* Remove members that are not actually FIELD_DECLs
-     from the field list of a record.  These occur in C++.  */
-  if (TREE_CODE (type) == RECORD_TYPE)
+  /* Remove members that are not actually FIELD_DECLs from the field
+     list of an aggregate.  These occur in C++.  */
+  if (TREE_CODE (type) == RECORD_TYPE
+      || TREE_CODE (type) == UNION_TYPE
+      || TREE_CODE (type) == QUAL_UNION_TYPE)
     {
       tree prev, member;
 
Index: gimple.c
===================================================================
--- gimple.c	(revision 144329)
+++ gimple.c	(working copy)
@@ -3193,30 +3193,47 @@ gimple_call_copy_skip_args (gimple stmt,
 }
 
 
-/* Return 1 if TYPE1 and TYPE2 are structurally compatible and/or they
-   have the same main variant.  */
+/* Return 1 if TYPE1 and TYPE2 are structurally compatible.  */
 
 int
 gimple_types_compatible_p (tree type1, tree type2)
 {
+  /* Types are trivially compatible with themselves.  */
+  if (type1 == type2)
+    return 1;
+
+  /* Only types with the same code can be compatible.  */
+  if (TREE_CODE (type1) != TREE_CODE (type2))
+    return 0;
+
+  /* If the main variants or their canonical type are the same, then
+     they are compatible.  */
+  if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)
+      || TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
+    return 1;
+
+  /* In the case of aggregates, check structural equality.  Note that
+     at this point, TYPE1 and TYPE2 are guaranteed to have the same
+     code already.  */
   if (TREE_CODE (type1) == RECORD_TYPE
-      && TREE_CODE (type2) == RECORD_TYPE)
+      || TREE_CODE (type1) == UNION_TYPE
+      || TREE_CODE (type1) == QUAL_UNION_TYPE)
     {
-      /* Check structural equality.  */
       tree f1, f2;
 
       for (f1 = TYPE_FIELDS (type1), f2 = TYPE_FIELDS (type2);
 	   f1 && f2;
 	   f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-	{
-	  if (TREE_CODE (f1) != TREE_CODE (f2)
-	      || DECL_NAME (f1) != DECL_NAME (f2))
-	    break;
-	}
+	if (!gimple_types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+	  return 0;
 
-      return f1 && f2 ? 0 : 1;
+      /* If one aggregate is bigger than the other, then they are not
+	 compatible.  */
+      return f1 || f2 ? 0 : 1;
     }
 
-  return TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2);
+  /* In any other case, the two types are not compatible.  */
+  return 0;
 }
+
 #include "gt-gimple.h"
Index: testsuite/gcc.dg/lto/20090219_0.c
===================================================================
--- testsuite/gcc.dg/lto/20090219_0.c	(revision 144329)
+++ testsuite/gcc.dg/lto/20090219_0.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do link } */
-/* { dg-options "{-O3 -fwhopr -shared}" } */
+/* { dg-options "{-O3 -fwhopr -fPIC -shared}" } */
 
 struct Foo { int f1, f2, f3, f4, f5; };
 
Index: testsuite/g++.dg/lto/20090221_0.C
===================================================================
--- testsuite/g++.dg/lto/20090221_0.C	(revision 0)
+++ testsuite/g++.dg/lto/20090221_0.C	(revision 0)
@@ -0,0 +1,53 @@
+// { dg-do compile }
+extern void some_function (const char *);
+extern bool some_other_function ();
+
+struct Foo
+{
+ long long a;
+ int b;
+};
+
+bool Foo_eq(Foo x, Foo y)
+{
+ return x.a == y.a && x.b == y.b;
+}
+
+struct Bar
+{
+ Foo a;
+ int b;
+};
+
+struct Baz
+{
+ Bar a;
+ Baz(Bar &a):a(a) { }
+};
+
+struct Zonk
+{
+ Baz baz;
+
+ Bar func_1(const Bar & bar) {
+   if (Foo_eq(bar.a, baz.a.a) && bar.b == baz.a.b || some_other_function ())
+     return bar;
+ }
+
+ void func_2(const Baz & baz) {
+   func_1(baz.a);
+   some_function(__PRETTY_FUNCTION__);
+ }
+};
+
+void func() {
+ Bar bar;
+ Zonk *rep;
+ rep->func_1(bar);
+ rep->func_2(Baz(bar));
+}
+
+void foo ()
+{
+  func();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]