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]

Minor ipa-devirt improvement


Hi,
this patch prevents ipa-devirt to devirtualize to functions that are
not exported and have no address takem from virtual table; those are
obviously not going to be targets of virtual calls.

Honza

	* ipa-devirt.c (referenced_from_vtable_p): New predicate.
	(maybe_record_node, likely_target_p): Use it.
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 209391)
+++ ipa-devirt.c	(working copy)
@@ -598,6 +598,48 @@ build_type_inheritance_graph (void)
   timevar_pop (TV_IPA_INHERITANCE);
 }
 
+/* Return true if N has reference from live virtual table
+   (and thus can be a destination of polymorphic call). 
+   Be conservatively correct when callgraph is not built or
+   if the method may be referred externally.  */
+
+static bool
+referenced_from_vtable_p (struct cgraph_node *node)
+{
+  int i;
+  struct ipa_ref *ref;
+  bool found = false;
+
+  if (node->externally_visible
+      || node->used_from_other_partition)
+    return true;
+
+  /* Keep this test constant time.
+     It is unlikely this can happen except for the case where speculative
+     devirtualization introduced many speculative edges to this node. 
+     In this case the target is very likely alive anyway.  */
+  if (node->ref_list.referring.length () > 100)
+    return true;
+
+  /* We need references built.  */
+  if (cgraph_state <= CGRAPH_STATE_CONSTRUCTION)
+    return true;
+
+  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
+					      i, ref); i++)
+	
+    if ((ref->use == IPA_REF_ALIAS
+	 && referenced_from_vtable_p (cgraph (ref->referring)))
+	|| (ref->use == IPA_REF_ADDR
+	    && TREE_CODE (ref->referring->decl) == VAR_DECL
+	    && DECL_VIRTUAL_P (ref->referring->decl)))
+      {
+	found = true;
+	break;
+      }
+  return found;
+}
+
 /* If TARGET has associated node, record it in the NODES array.
    CAN_REFER specify if program can refer to the target directly.
    if TARGET is unknown (NULL) or it can not be inserted (for example because
@@ -634,11 +676,29 @@ maybe_record_node (vec <cgraph_node *> &
 
   target_node = cgraph_get_node (target);
 
-  if (target_node != NULL
-      && ((TREE_PUBLIC (target)
-	   || DECL_EXTERNAL (target))
-	  || target_node->definition)
-      && symtab_real_symbol_p (target_node))
+  /* Method can only be called by polymorphic call if any
+     of vtables refering to it are alive. 
+
+     While this holds for non-anonymous functions, too, there are
+     cases where we want to keep them in the list; for example
+     inline functions with -fno-weak are static, but we still
+     may devirtualize them when instance comes from other unit.
+     The same holds for LTO.
+
+     Currently we ignore these functions in speculative devirtualization.
+     ??? Maybe it would make sense to be more aggressive for LTO even
+     eslewhere.  */
+  if (!flag_ltrans
+      && type_in_anonymous_namespace_p (DECL_CONTEXT (target))
+      && (!target_node
+          || !referenced_from_vtable_p (target_node)))
+    ;
+  /* See if TARGET is useful function we can deal with.  */
+  else if (target_node != NULL
+	   && (TREE_PUBLIC (target)
+	       || DECL_EXTERNAL (target)
+	       || target_node->definition)
+	   && symtab_real_symbol_p (target_node))
     {
       gcc_assert (!target_node->global.inlined_to);
       gcc_assert (symtab_real_symbol_p (target_node));
@@ -1725,6 +1785,12 @@ likely_target_p (struct cgraph_node *n)
     return false;
   if (n->frequency < NODE_FREQUENCY_NORMAL)
     return false;
+  /* If there are no virtual tables refering the target alive,
+     the only way the target can be called is an instance comming from other
+     compilation unit; speculative devirtualization is build around an
+     assumption that won't happen.  */
+  if (!referenced_from_vtable_p (n))
+    return false;
   return true;
 }
 


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