------- Comment #4 from jakub at gcc dot gnu dot org  2008-02-12 13:27 -------
Not doing SRA seems harder than just handling it, because the decision whether
SRA should be done and whether to use block copy is done on vars, which both
are scalarizable.
Testing following patch:
2008-02-12  Jakub Jelinek  <[EMAIL PROTECTED]>

        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 <[EMAIL PROTECTED]>

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

The special casing of pointers is admittedly ugly, but in this case, eventhough
the C++ FE says the two RECORD_TYPEs are type compatible, the pointers in them
actually are not (point to similar, but not identical, METHOD_TYPEs).
Also, the ptrmemfunc types are otherwise perfect candidate for scalarizing
which will allow further optimizations, so rejecting to SRA it would be a
pitty.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35144

Reply via email to