]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* ipa-cp.c (ipa_get_indirect_edge_target_1): Do direct
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Feb 2014 03:42:37 +0000 (03:42 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Feb 2014 03:42:37 +0000 (03:42 +0000)
lookup via vtable pointer; check for type consistency
and turn inconsitent facts into UNREACHABLE.
* ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.
* gimple-fold.c (gimple_get_virt_method_for_vtable):
Do not ICE on type inconsistent querries; return UNREACHABLE
instead.

* g++.dg/ipa/devirt-25.C: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207447 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple-fold.c
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/devirt-25.C [new file with mode: 0644]

index 1c76b13844db6290c6c06fd02cacd67f01a894ab..4baab8e13bdabae3c76a731e471ed19a4b730fc6 100644 (file)
@@ -1,3 +1,13 @@
+2014-02-03  Jan Hubicka  <jh@suse.cz>
+
+       * ipa-cp.c (ipa_get_indirect_edge_target_1): Do direct
+       lookup via vtable pointer; check for type consistency
+       and turn inconsitent facts into UNREACHABLE.
+       * ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.
+       * gimple-fold.c (gimple_get_virt_method_for_vtable): 
+       Do not ICE on type inconsistent querries; return UNREACHABLE
+       instead.
+
 2014-02-03  Richard Henderson  <rth@twiddle.net>
 
        PR tree-opt/59924
index faea68e457bed60131f50ce810ad54e71df82cce..848c1f64e4810ab93c22e0baa6b83e1a7818508d 100644 (file)
@@ -3247,12 +3247,14 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
   tree vtable = v, init, fn;
   unsigned HOST_WIDE_INT size;
 
+  /* First of all double check we have virtual table.  */
   if (TREE_CODE (v) != VAR_DECL
       || !DECL_VIRTUAL_P (v))
     return NULL_TREE;
+
   init = ctor_for_folding (v);
 
-  /* The virtual tables should always be born with constructors.
+  /* The virtual tables should always be born with constructors
      and we always should assume that they are avaialble for
      folding.  At the moment we do not stream them in all cases,
      but it should never happen that ctor seem unreachable.  */
@@ -3266,21 +3268,31 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
   size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))));
   offset *= BITS_PER_UNIT;
   offset += token * size;
+
+  /* Do not pass from_decl here, we want to know even about values we can
+     not use and will check can_refer_decl_in_current_unit_p ourselves.  */
   fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), init,
-                           offset, size, v);
-  if (!fn || integer_zerop (fn))
-    return NULL_TREE;
-  gcc_assert (TREE_CODE (fn) == ADDR_EXPR
-             || TREE_CODE (fn) == FDESC_EXPR);
-  fn = TREE_OPERAND (fn, 0);
-  gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
-
-  /* When cgraph node is missing and function is not public, we cannot
-     devirtualize.  This can happen in WHOPR when the actual method
-     ends up in other partition, because we found devirtualization
-     possibility too late.  */
-  if (!can_refer_decl_in_current_unit_p (fn, vtable))
-    return NULL_TREE;
+                           offset, size, NULL);
+
+  /* For type inconsistent program we may end up looking up virtual method
+     in virtual table that does not contain TOKEN entries.  We may overrun
+     the virtual table and pick up a constant or RTTI info pointer.
+     In any case the call is undefined.  */
+  if (!fn
+      || (TREE_CODE (fn) != ADDR_EXPR && TREE_CODE (fn) != FDESC_EXPR)
+      || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+    fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+  else
+    {
+      fn = TREE_OPERAND (fn, 0);
+
+      /* When cgraph node is missing and function is not public, we cannot
+        devirtualize.  This can happen in WHOPR when the actual method
+        ends up in other partition, because we found devirtualization
+        possibility too late.  */
+      if (!can_refer_decl_in_current_unit_p (fn, vtable))
+       return NULL_TREE;
+    }
 
   /* Make sure we create a cgraph node for functions we'll reference.
      They can be non-existent if the reference comes from an entry
index 18a5a03a5e178cc7e77739aa8bdc45bf65baef07..e2101769e126bd09b35e5a436256ae7b93e72451 100644 (file)
@@ -1564,9 +1564,31 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
                                       true);
     }
 
-  /* If we found the virtual table pointer, lookup the binfo.  */
+  /* If we found the virtual table pointer, lookup the target.  */
   if (t)
-    t = vtable_pointer_value_to_binfo (t);
+    {
+      tree vtable;
+      unsigned HOST_WIDE_INT offset;
+      if (vtable_pointer_value_to_vtable (t, &vtable, &offset))
+       {
+         target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
+                                                     vtable, offset);
+         if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
+              && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
+             || !possible_polymorphic_call_target_p
+                  (ie, cgraph_get_node (target)))
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Type inconsident devirtualization: %s/%i->%s\n",
+                        ie->caller->name (), ie->caller->order,
+                        IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
+             target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+             cgraph_get_create_node (target);
+           }
+         return target;
+       }
+    }
 
   /* Did we work out BINFO via type propagation?  */
   if (!t && known_binfos.length () > (unsigned int) param_index)
index 37ddbde462162bdd3d1ed1ba32930cad0c500829..39c01c51ef3e4cc769f56c94d3a9913b4279b7da 100644 (file)
@@ -2687,23 +2687,44 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
                                   struct ipa_jump_func *jfunc,
                                   struct ipa_node_params *new_root_info)
 {
-  tree binfo = NULL, target;
+  tree binfo, target;
 
   if (!flag_devirtualize)
     return NULL;
 
-  /* First try to do lookup binfo via known virtual table pointer value.  */
+  /* First try to do lookup via known virtual table pointer value.  */
   if (!ie->indirect_info->by_ref)
     {
+      tree vtable;
+      unsigned HOST_WIDE_INT offset;
       tree t = ipa_find_agg_cst_for_param (&jfunc->agg,
                                           ie->indirect_info->offset,
                                           true);
-      if (t)
-        binfo = vtable_pointer_value_to_binfo (t);
+      if (t && vtable_pointer_value_to_vtable (t, &vtable, &offset))
+       {
+         target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token,
+                                                     vtable, offset);
+         if (target)
+           {
+             if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE
+                  && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
+                 || !possible_polymorphic_call_target_p
+                      (ie, cgraph_get_node (target)))
+               {
+                 if (dump_file)
+                   fprintf (dump_file,
+                            "Type inconsident devirtualization: %s/%i->%s\n",
+                            ie->caller->name (), ie->caller->order,
+                            IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
+                 target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+                 cgraph_get_create_node (target);
+               }
+             return ipa_make_edge_direct_to_target (ie, target);
+           }
+       }
     }
 
-  if (!binfo)
-    binfo = ipa_value_from_jfunc (new_root_info, jfunc);
+  binfo = ipa_value_from_jfunc (new_root_info, jfunc);
 
   if (!binfo)
     return NULL;
index 9465477719f8e390a4a076291445ca962d5ab984..3a0c9447dccb07ff9c2a1ab94f3e43af964664bb 100644 (file)
@@ -1,3 +1,7 @@
+2014-02-03  Jan Hubicka  <jh@suse.cz>
+
+       * g++.dg/ipa/devirt-25.C: New testcase.
+
 2014-02-04  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/59924
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-25.C b/gcc/testsuite/g++.dg/ipa/devirt-25.C
new file mode 100644 (file)
index 0000000..7516479
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp"  } */
+
+class ert_RefCounter {
+ protected:
+  int refCounterE;
+  virtual ~ert_RefCounter() {}
+};
+
+class ebs_Object : virtual public ert_RefCounter {
+};
+
+class dpr_App : public ebs_Object {
+ public:
+  virtual void run();
+};
+
+class dpr_Job : public ebs_Object {};
+
+void dpr_run(ebs_Object& objectA) {
+  ((dpr_App&)objectA).run();
+  dpr_Job jobL;
+  dpr_run(jobL);
+}
+/* { dg-final { scan-ipa-dump "Type inconsident devirtualization" "cp"  } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */