* ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Sep 2013 16:54:34 +0000 (16:54 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Sep 2013 16:54:34 +0000 (16:54 +0000)
for ipa-devirt.
* ipa-utils.h (possible_polymorphic_call_target_p): New function.
* ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant
of external calls
* gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h
(gimple_fold_call): Dump inconsistent devirtualizations; add
sanity check for type based devirtualizations.
* ipa-prop.c: Include ipa-utils.h
(ipa_intraprocedural_devirtualization): Add sanity check.
(try_make_edge_direct_virtual_call): Likewise.

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

gcc/ChangeLog
gcc/gimple-fold.c
gcc/ipa-cp.c
gcc/ipa-devirt.c
gcc/ipa-prop.c
gcc/ipa-utils.h

index a77d7c7..b38c84b 100644 (file)
@@ -1,3 +1,17 @@
+2013-09-23  Jan Hubicka  <jh@suse.cz>
+
+       * ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check
+       for ipa-devirt.
+       * ipa-utils.h (possible_polymorphic_call_target_p): New function.
+       * ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant
+       of external calls
+       * gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h
+       (gimple_fold_call): Dump inconsistent devirtualizations; add
+       sanity check for type based devirtualizations.
+       * ipa-prop.c: Include ipa-utils.h
+       (ipa_intraprocedural_devirtualization): Add sanity check.
+       (try_make_edge_direct_virtual_call): Likewise.
+
 2013-09-23  Eric Botcazou  <ebotcazou@adacore.com>
 
        * tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
index 51713e6..c77d00b 100644 (file)
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "target.h"
 #include "gimple-fold.h"
+#include "ipa-utils.h"
+#include "gimple-pretty-print.h"
 
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -1116,6 +1118,19 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
     {
       if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
        {
+          if (dump_file && virtual_method_call_p (callee)
+             && !possible_polymorphic_call_target_p
+                   (callee, cgraph_get_node (gimple_call_addr_fndecl
+                                                 (OBJ_TYPE_REF_EXPR (callee)))))
+           {
+             fprintf (dump_file,
+                      "Type inheritnace inconsistent devirtualization of ");
+             print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+             fprintf (dump_file, " to ");
+             print_generic_expr (dump_file, callee, TDF_SLIM);
+             fprintf (dump_file, "\n");
+           }
+
          gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
          changed = true;
        }
@@ -1131,6 +1146,11 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
              tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
              if (fndecl)
                {
+#ifdef ENABLE_CHECKING
+                 gcc_assert (possible_polymorphic_call_target_p
+                                (callee, cgraph_get_node (fndecl)));
+
+#endif
                  gimple_call_set_fndecl (stmt, fndecl);
                  changed = true;
                }
index 56b27b2..86f5501 100644 (file)
@@ -1484,6 +1484,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
   HOST_WIDE_INT token, anc_offset;
   tree otr_type;
   tree t;
+  tree target;
 
   if (param_index == -1
       || known_vals.length () <= (unsigned int) param_index)
@@ -1552,7 +1553,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
       binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
       if (!binfo)
        return NULL_TREE;
-      return gimple_get_virt_method_for_binfo (token, binfo);
+      target = gimple_get_virt_method_for_binfo (token, binfo);
     }
   else
     {
@@ -1561,8 +1562,15 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
       binfo = get_binfo_at_offset (t, anc_offset, otr_type);
       if (!binfo)
        return NULL_TREE;
-      return gimple_get_virt_method_for_binfo (token, binfo);
+      target = gimple_get_virt_method_for_binfo (token, binfo);
     }
+#ifdef ENABLE_CHECKING
+  if (target)
+    gcc_assert (possible_polymorphic_call_target_p
+                (ie, cgraph_get_node (target)));
+#endif
+
+  return target;
 }
 
 
index 85bc5b0..c610e7b 100644 (file)
@@ -905,13 +905,19 @@ possible_polymorphic_call_target_p (tree otr_type,
 {
   vec <cgraph_node *> targets;
   unsigned int i;
+  bool final;
 
   if (!odr_hash.is_created ())
     return true;
-  targets = possible_polymorphic_call_targets (otr_type, otr_token);
+  targets = possible_polymorphic_call_targets (otr_type, otr_token, &final);
   for (i = 0; i < targets.length (); i++)
     if (n == targets[i])
       return true;
+
+  /* At a moment we allow middle end to dig out new external declarations
+     as a targets of polymorphic calls.  */
+  if (!final && !n->symbol.definition)
+    return true;
   return false;
 }
 
index c09ec2f..2fbc9d4 100644 (file)
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "data-streamer.h"
 #include "tree-streamer.h"
 #include "params.h"
+#include "ipa-utils.h"
 
 /* Intermediate information about a parameter that is only useful during the
    run of ipa_analyze_node and is not kept afterwards.  */
@@ -2196,6 +2197,11 @@ ipa_intraprocedural_devirtualization (gimple call)
   token = OBJ_TYPE_REF_TOKEN (otr);
   fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
                                             binfo);
+#ifdef ENABLE_CHECKING
+  if (fndecl)
+    gcc_assert (possible_polymorphic_call_target_p
+                 (otr, cgraph_get_node (fndecl)));
+#endif
   return fndecl;
 }
 
@@ -2651,7 +2657,13 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
     return NULL;
 
   if (target)
-    return ipa_make_edge_direct_to_target (ie, target);
+    {
+#ifdef ENABLE_CHECKING
+      gcc_assert (possible_polymorphic_call_target_p
+        (ie, cgraph_get_node (target)));
+#endif
+      return ipa_make_edge_direct_to_target (ie, target);
+    }
   else
     return NULL;
 }
index d6f390d..27949e1 100644 (file)
@@ -108,6 +108,19 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
   return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
                                             e->indirect_info->otr_token, n);
 }
+
+/* Return true if N can be possibly target of a polymorphic call of
+   OBJ_TYPE_REF expression CALL.  */
+
+inline bool
+possible_polymorphic_call_target_p (tree call,
+                                   struct cgraph_node *n)
+{
+  return possible_polymorphic_call_target_p (obj_type_ref_class (call),
+                                            tree_low_cst
+                                               (OBJ_TYPE_REF_TOKEN (call), 1),
+                                            n);
+}
 #endif  /* GCC_IPA_UTILS_H  */