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]

[PATCH] Handle copy between non-identical, but structurally equal RECORD_TYPEs in SRA (PR c++/35144)


Hi!

The pointer to member function RECORD_TYPEs C++ FE creates have the same
fields and for useless_type_conversion_p are considered compatible (so it is
valid GIMPLE to copy one to the other, yet they have different
TYPE_MAIN_VARIANTs and different FIELD_DECLs.

SRA currently uses FIELD_DECLs to look up the elements, which will not work.
The following patch adjusts generate_element_copy to try harder, if
DST's FIELD_DECL wasn't found in SRC, it will try to locate a SRC FIELD_DECL
with the same field offset, size and compatible type.

Unfortunately, the pointer to member function RECORD_TYPEs sometimes have
pointers to different METHOD_TYPEs, and useless_type_conversion_p doesn't
consider those to be equivalent, so the extra POINTER_TYPE_P checks
in generate_element_copy and additional hunk in sra_build_assignment
are there to convert the pointers.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2008-02-12  Jakub Jelinek  <jakub@redhat.com>

	PR c++/35144
	* tree-sra.c (sra_build_assignment): fold_convert SRC if copying
	non-compatible pointers.
	(generate_element_copy): If SRC and DST are RECORD_TYPEs with
	different FIELD_DECLs, try harder by comparing field offsets, sizes
	and types.

	* g++.dg/tree-ssa/pr35144.C: New test.

--- gcc/tree-sra.c.jj	2008-02-11 14:48:12.000000000 +0100
+++ gcc/tree-sra.c	2008-02-12 14:07:29.000000000 +0100
@@ -1,7 +1,7 @@
 /* Scalar Replacement of Aggregates (SRA) converts some structure
    references into scalar references, exposing them to the scalar
    optimizers.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
      Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -2270,7 +2270,13 @@ sra_build_assignment (tree dst, tree src
      Since such accesses under different types require compatibility
      anyway, there's little point in making tests and/or adding
      conversions to ensure the types of src and dst are the same.
-     So we just assume type differences at this point are ok.  */
+     So we just assume type differences at this point are ok.
+     The only exception we make here are pointer types, which can be different
+     in e.g. structurally equal, but non-identical RECORD_TYPEs.  */
+  if (POINTER_TYPE_P (TREE_TYPE (dst))
+      && !useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (src)))
+    src = fold_convert (TREE_TYPE (dst), src);
+
   return build_gimple_modify_stmt (dst, src);
 }
 
@@ -2600,7 +2606,33 @@ generate_element_copy (struct sra_elt *d
 
 	  continue;
 	}
-      gcc_assert (sc);
+
+      /* If DST and SRC are structs with the same elements, but do not have
+	 the same TYPE_MAIN_VARIANT, then lookup of DST FIELD_DECL in SRC
+	 will fail.  Try harder by finding the corresponding FIELD_DECL
+	 in SRC.  */
+      if (!sc)
+	{
+	  tree f;
+
+	  gcc_assert (useless_type_conversion_p (dst->type, src->type));
+	  gcc_assert (TREE_CODE (dc->element) == FIELD_DECL);
+	  for (f = TYPE_FIELDS (src->type); f ; f = TREE_CHAIN (f))
+	    if (simple_cst_equal (DECL_FIELD_OFFSET (f),
+				  DECL_FIELD_OFFSET (dc->element)) > 0
+		&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (f),
+				     DECL_FIELD_BIT_OFFSET (dc->element)) > 0
+		&& simple_cst_equal (DECL_SIZE (f),
+				     DECL_SIZE (dc->element)) > 0
+		&& (useless_type_conversion_p (TREE_TYPE (dc->element),
+					       TREE_TYPE (f))
+		    || (POINTER_TYPE_P (TREE_TYPE (dc->element))
+			&& POINTER_TYPE_P (TREE_TYPE (f)))))
+	      break;
+	  gcc_assert (f != NULL_TREE);
+	  sc = lookup_element (src, f, NULL, NO_INSERT);
+	}
+
       generate_element_copy (dc, sc, list_p);
     }
 
--- gcc/testsuite/g++.dg/tree-ssa/pr35144.C.jj	2008-02-12 14:12:02.000000000 +0100
+++ gcc/testsuite/g++.dg/tree-ssa/pr35144.C	2008-02-12 14:12:32.000000000 +0100
@@ -0,0 +1,30 @@
+// PR c++/35144
+// { dg-do compile }
+// { dg-options "-O2" }
+
+struct A
+{
+  int baz ();
+};
+
+typedef int (A::*P) ();
+
+struct B
+{
+  B ();
+  int foo (P x, int y = 0);
+};
+
+struct C
+{
+  typedef int (B::*Q) (P, int);
+  void bar (Q x) { c = x; }
+  Q c;
+};
+
+extern C c;
+
+B::B ()
+{
+ c.bar ((C::Q) &B::foo);
+}

	Jakub


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