diff mbox

Fix side case in ipa-devirt

Message ID 20140809220927.GA12548@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Aug. 9, 2014, 10:09 p.m. UTC
Hi,
tree-ssa-pre is checking that new dynamic type detection (get_dynamic_type) catch all cases as old.
Firefox has somewhat obscure case when new code runs into placement new paranoia earlier.
This patch fixes it and also fixes templates of last two testcases that had unresolved tests.
	* g++.dg/ipa/devirt-35.C: Fix template.
	* g++.dg/ipa/devirt-36.C: Likewise.
	* g++.dg/ipa/devirt-37.C: New testcase.
	* ipa-devirt.c (get_dynamic_type): Handle case when instance is in
	DECL correctly; do not give up on types in static storage.

Comments

Rainer Orth Aug. 11, 2014, 2:54 p.m. UTC | #1
Hi Jan,

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

it seems something is very wrong with this testcase: initially, all
scans FAILed because the dump file didn't exist.  But even with -O2
added to dg-options, the failures remain because either the wording is
different

FAIL: g++.dg/ipa/devirt-37.C  -std=gnu++98  scan-tree-dump fre2 "Determined dynamic type."

vs.

Determining dynamic type for call: OBJ_TYPE_REF(_4;(struct A)a_2(D)->0) (a_2(D));
        ^^^

or the strings are completely missing.

Please fix.

	Rainer
diff mbox

Patch

Index: testsuite/g++.dg/ipa/devirt-35.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-35.C	(revision 213757)
+++ testsuite/g++.dg/ipa/devirt-35.C	(working copy)
@@ -15,9 +15,9 @@  m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-ipa-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
 /* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
 /* { dg-final { cleanup-ipa-dump "devirt" } } */
-/* { dg-final { cleanup-tree-dump "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
 
Index: testsuite/g++.dg/ipa/devirt-37.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-37.C	(revision 0)
+++ testsuite/g++.dg/ipa/devirt-37.C	(revision 0)
@@ -0,0 +1,35 @@ 
+/* { dg-options "-fpermissive -fno-indirect-inlining -fno-devirtualize-speculatively -fdump-tree-fre2-details"  } */
+#include <stdlib.h>
+struct A {virtual void test() {abort ();}};
+struct B:A
+   {virtual void test() {}
+    B();
+    B(void (*test)(struct A *));};
+
+void extcall(void);
+
+inline void tt(struct A *a)
+{
+  a->test();
+}
+
+B::B (void (*test)(struct A *))
+{
+  struct B c;
+  struct A *a=this;
+  extcall();
+  test(a);
+}
+void
+t()
+{
+  struct B b(tt);
+}
+/* After inlining the call within constructor needs to be checked to not go into a basetype.
+   We should see the vtbl store and we should notice extcall as possibly clobbering the
+   type but ignore it because b is in static storage.  */
+/* { dg-final { scan-tree-dump "Determined dynamic type."  "fre2"  } } */
+/* { dg-final { scan-tree-dump "Checking vtbl store:"  "fre2"  } } */
+/* { dg-final { scan-tree-dump "Function call may change dynamic type:extcall"  "fre2"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual void"  "fre2"  } } */
+/* { dg-final { cleanup-tree-dump "fre2" } } */
Index: testsuite/g++.dg/ipa/devirt-36.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-36.C	(revision 213757)
+++ testsuite/g++.dg/ipa/devirt-36.C	(working copy)
@@ -17,9 +17,9 @@  m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-ipa-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
 /* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
 /* { dg-final { cleanup-ipa-dump "devirt" } } */
-/* { dg-final { cleanup-tree-dump "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
 
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 213757)
+++ ipa-devirt.c	(working copy)
@@ -2799,10 +2799,12 @@  get_dynamic_type (tree instance,
 		  /* Finally verify that what we found looks like read from OTR_OBJECT
 		     or from INSTANCE with offset OFFSET.  */
 		  if (base_ref
-		      && TREE_CODE (base_ref) == MEM_REF
-		      && ((offset2 == context->offset
-		           && TREE_OPERAND (base_ref, 0) == instance)
-			  || (!offset2 && TREE_OPERAND (base_ref, 0) == otr_object)))
+		      && ((TREE_CODE (base_ref) == MEM_REF
+		           && ((offset2 == context->offset
+		                && TREE_OPERAND (base_ref, 0) == instance)
+			       || (!offset2 && TREE_OPERAND (base_ref, 0) == otr_object)))
+			  || (DECL_P (instance) && base_ref == instance
+			      && offset2 == context->offset)))
 		    {
 		      stmt = SSA_NAME_DEF_STMT (ref);
 		      instance_ref = ref_exp;
@@ -2923,7 +2925,14 @@  get_dynamic_type (tree instance,
       && !function_entry_reached
       && !tci.multiple_types_encountered)
     {
-      if (!tci.speculative)
+      if (!tci.speculative
+	  /* Again in instances located in static storage we are interested only
+	     in constructor stores.  */
+	  || (context->outer_type
+	      && !tci.seen_unanalyzed_store
+	      && context->offset == tci.offset
+	      && types_same_for_odr (tci.known_current_type,
+				     context->outer_type)))
 	{
 	  context->outer_type = tci.known_current_type;
 	  context->offset = tci.known_current_offset;