Hi!

If TREE_BINFO has BV_VCALL_INDEX set, this needs to be dynamically
adjusted, but none of the callers are prepared to handle that.
Thus, this patch makes devirtualization give up in those cases.

Bootstrapped/regtested on x86_64-linux and i686-linux, trunk and 4.6.
On the trunk the testcase ICEs before and after the patch in some new callgraph
checking (added today or so, Honza?), on the branch it works just fine.

Ok for trunk/4.6?

2011-04-18  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/48661
        * gimple-fold.c (gimple_get_virt_method_for_binfo): Return NULL
        if TREE_TYPE (v) is non-NULL.

        * gimple-fold.c (gimple_get_virt_method_for_binfo): Renamed from
        gimple_get_virt_mehtod_for_binfo.
        * gimple.h (gimple_get_virt_method_for_binfo): Likewise.
        * ipa-cp.c (ipcp_process_devirtualization_opportunities): Adjust
        callers.
        * ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.

        * g++.dg/torture/pr48661.C: New test.

--- gcc/gimple-fold.c.jj        2011-03-14 14:12:15.000000000 +0100
+++ gcc/gimple-fold.c   2011-04-18 18:35:22.000000000 +0200
@@ -1374,7 +1374,7 @@ gimple_fold_builtin (gimple stmt)
    is a thunk (other than a this adjustment which is dealt with by DELTA). */
 
 tree
-gimple_get_virt_mehtod_for_binfo (HOST_WIDE_INT token, tree known_binfo,
+gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo,
                                  tree *delta, bool refuse_thunks)
 {
   HOST_WIDE_INT i;
@@ -1393,6 +1393,10 @@ gimple_get_virt_mehtod_for_binfo (HOST_W
       v = TREE_CHAIN (v);
     }
 
+  /* If BV_VCALL_INDEX is non-NULL, give up.  */
+  if (TREE_TYPE (v))
+    return NULL_TREE;
+
   fndecl = TREE_VALUE (v);
   node = cgraph_get_node_or_alias (fndecl);
   if (refuse_thunks
--- gcc/gimple.h.jj     2011-03-14 14:12:15.000000000 +0100
+++ gcc/gimple.h        2011-04-18 18:35:40.000000000 +0200
@@ -892,7 +892,7 @@ unsigned get_gimple_rhs_num_ops (enum tr
 gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
 const char *gimple_decl_printable_name (tree, int);
 bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace);
-tree gimple_get_virt_mehtod_for_binfo (HOST_WIDE_INT, tree, tree *, bool);
+tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree, tree *, bool);
 void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
 /* Returns true iff T is a valid GIMPLE statement.  */
 extern bool is_gimple_stmt (tree);
--- gcc/ipa-cp.c.jj     2011-04-13 12:39:28.000000000 +0200
+++ gcc/ipa-cp.c        2011-04-18 18:36:11.000000000 +0200
@@ -1242,7 +1242,7 @@ ipcp_process_devirtualization_opportunit
        {
          tree binfo = VEC_index (tree, info->params[param_index].types, j);
          tree d;
-         tree t = gimple_get_virt_mehtod_for_binfo (token, binfo, &d, true);
+         tree t = gimple_get_virt_method_for_binfo (token, binfo, &d, true);
 
          if (!t)
            {
--- gcc/ipa-prop.c.jj   2011-04-13 12:39:28.000000000 +0200
+++ gcc/ipa-prop.c      2011-04-18 18:36:30.000000000 +0200
@@ -1730,7 +1730,7 @@ try_make_edge_direct_virtual_call (struc
   type = ie->indirect_info->otr_type;
   binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type);
   if (binfo)
-    target = gimple_get_virt_mehtod_for_binfo (token, binfo, &delta, true);
+    target = gimple_get_virt_method_for_binfo (token, binfo, &delta, true);
   else
     return NULL;
 
--- gcc/testsuite/g++.dg/torture/pr48661.C.jj   2011-04-18 18:50:49.000000000 
+0200
+++ gcc/testsuite/g++.dg/torture/pr48661.C      2011-04-18 18:50:11.000000000 
+0200
@@ -0,0 +1,77 @@
+// PR middle-end/48661
+// { dg-do run }
+
+extern "C" void abort ();
+
+__attribute__((noinline))
+double
+foo (double x, double y)
+{
+  asm volatile ("" : : : "memory");
+  return x + y;
+}
+
+__attribute__((noinline, noclone))
+void
+bar (int x)
+{
+  if (x != 123)
+    abort ();
+}
+
+struct A
+{
+  double a1, a2;
+};
+
+struct B 
+{
+  virtual int m () const = 0 ;
+};
+
+struct C
+{
+  virtual ~C () {}
+};
+
+struct D : virtual public B, public C
+{ 
+  explicit D (const A &x) : d(123) { foo (x.a2, x.a1); }
+  int m () const { return d; }
+  int d;
+}; 
+
+struct E
+{
+  E () : d(0) {}
+  virtual void n (const B &x) { d = x.m (); x.m (); x.m (); }
+  int d;
+};
+
+void
+test ()
+{
+  A a;
+  a.a1 = 0;
+  a.a2 = 1;
+  E p;
+  D q (a);
+  const B &b = q;
+  bar (b.m ());
+  p.n (b);
+  bar (p.d);
+}
+
+void
+baz ()
+{
+  A a;
+  D p2 (a);
+}
+
+int
+main ()
+{
+  test ();
+  return 0;
+}

        Jakub

Reply via email to