diff mbox

Fix PR ipa/65722

Message ID 20150412011115.GA73158@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka April 12, 2015, 1:11 a.m. UTC
Hi,
this is version of patch I comitted after testing at x86_64-linux firefox build
and bootstrapped/regtested ppc64-linux.

Honza

	Jan Hubicka  <hubicka@ucw.cz>
	Martin Liska  <mliska@suse.cz>

	PR ipa/65722
	* g++.dg/ipa/pr65722.C: New testcase.

	* ipa-icf.c (sem_item::compare_cgraph_references): function and
	variable can not match.
	(sem_item::update_hash_by_addr_refs): Fix handling of virtual tables.
	(sem_variable::equals_wpa): Fix checking of DECL_FINAL_P patch.
diff mbox

Patch

Index: testsuite/g++.dg/ipa/pr65722.C
===================================================================
--- testsuite/g++.dg/ipa/pr65722.C	(revision 0)
+++ testsuite/g++.dg/ipa/pr65722.C	(revision 0)
@@ -0,0 +1,21 @@ 
+// { dg-do compile }
+// { dg-options "-O -fipa-icf -fno-rtti" }
+
+struct A
+{
+  virtual void f ()
+  {
+    __builtin_abort ();
+  }
+  virtual void g ();
+};
+
+struct B : virtual A { };
+struct C : B, virtual A { };
+
+void foo()
+{
+  C c;
+  C *p = &c;
+  p->f ();
+}
Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 221977)
+++ ipa-icf.c	(working copy)
@@ -368,6 +368,10 @@  sem_item::compare_cgraph_references (
   if (n1 == n2)
     return true;
 
+  /* Never match variable and function.  */
+  if (is_a <varpool_node *> (n1) != is_a <varpool_node *> (n2))
+    return false;
+
   /* Merging two definitions with a reference to equivalent vtables, but
      belonging to a different type may result in ipa-polymorphic-call analysis
      giving a wrong answer about the dynamic type of instance.  */
@@ -587,9 +591,6 @@  void
 sem_item::update_hash_by_addr_refs (hash_map <symtab_node *,
 				    sem_item *> &m_symtab_node_map)
 {
-  if (is_a <varpool_node *> (node) && DECL_VIRTUAL_P (node->decl))
-    return;
-
   ipa_ref* ref;
   inchash::hash hstate (hash);
   for (unsigned i = 0; i < node->num_references (); i++)
@@ -1667,17 +1668,19 @@  sem_variable::equals_wpa (sem_item *item
 				      ref->address_matters_p ()))
 	return false;
 
-      /* DECL_FINAL_P flag on methods referred by virtual tables is used
-	 to decide on completeness possible_polymorphic_call_targets lists
-	 and therefore it must match.  */
-      if ((DECL_VIRTUAL_P (decl) || DECL_VIRTUAL_P (item->decl))
-	  && (DECL_VIRTUAL_P (ref->referred->decl)
-	      || DECL_VIRTUAL_P (ref2->referred->decl))
-	  && ((DECL_VIRTUAL_P (ref->referred->decl)
-	       != DECL_VIRTUAL_P (ref2->referred->decl))
-	      || (DECL_FINAL_P (ref->referred->decl)
-		  != DECL_FINAL_P (ref2->referred->decl))))
-        return return_false_with_msg ("virtual or final flag mismatch");
+      /* When matching virtual tables, be sure to also match information
+ 	 relevant for polymorphic call analysis.  */
+      if (DECL_VIRTUAL_P (decl) || DECL_VIRTUAL_P (item->decl))
+	{
+	  if (DECL_VIRTUAL_P (ref->referred->decl)
+	      != DECL_VIRTUAL_P (ref2->referred->decl))
+            return return_false_with_msg ("virtual flag mismatch");
+	  if (DECL_VIRTUAL_P (ref->referred->decl)
+	      && is_a <cgraph_node *> (ref->referred)
+	      && (DECL_FINAL_P (ref->referred->decl)
+		  != DECL_FINAL_P (ref2->referred->decl)))
+            return return_false_with_msg ("final flag mismatch");
+	}
     }
 
   return true;