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]

Fix devirtualization with LTO


Hi,
while fixing Firefox issues I also noticed that type simplification
completely disabled type based devirtualization on LTO path. Problem
is that method pointers now point to simplified type and 
obj_type_ref_class is not ready for that.

I also moved testcases where it makes sense to lto so this does not
happen again. This is not trivial task since one needs to work out why
testcases behaves differently when they do, so I will follow up on this
and convert more.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

	* tree.c: (obj_type_ref_class): Move to...
	* ipa-devirt.c (obj_type_ref_class): Move to here; lookup main
	odr type.
	(get_odr_type): Compensate for type simplification.

	* g++.dg/ipa/devirt-30.C: Add dg-do.
	* g++.dg/lto/devirt-1_0.C: New testcase.
	* g++.dg/lto/devirt-2_0.C: New testcase.
	* g++.dg/lto/devirt-3_0.C: New testcase.
	* g++.dg/lto/devirt-4_0.C: New testcase.
	* g++.dg/lto/devirt-5_0.C: New testcase.
	* g++.dg/lto/devirt-6_0.C: New testcase.
	* g++.dg/lto/devirt-13_0.C: New testcase.
	* g++.dg/lto/devirt-14_0.C: New testcase.
	* g++.dg/lto/devirt-19_0.C: New testcase.
	* g++.dg/lto/devirt-22_0.C: New testcase.
	* g++.dg/lto/devirt-23_0.C: New testcase.
	* g++.dg/lto/devirt-30_0.C: New testcase.
	* g++.dg/lto/devirt-34_0.C: New testcase.
	
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 267337)
+++ ipa-devirt.c	(working copy)
@@ -1985,6 +1985,30 @@ add_type_duplicate (odr_type val, tree t
   return build_bases;
 }
 
+/* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
+
+tree
+obj_type_ref_class (const_tree ref)
+{
+  gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
+  ref = TREE_TYPE (ref);
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  ref = TREE_TYPE (ref);
+  /* We look for type THIS points to.  ObjC also builds
+     OBJ_TYPE_REF with non-method calls, Their first parameter
+     ID however also corresponds to class type. */
+  gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
+		       || TREE_CODE (ref) == FUNCTION_TYPE);
+  ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  tree ret = TREE_TYPE (ref);
+  if (!in_lto_p)
+    ret = TYPE_CANONICAL (ret);
+  else
+    ret = get_odr_type (ret)->type;
+  return ret;
+}
+
 /* Get ODR type hash entry for TYPE.  If INSERT is true, create
    possibly new entry.  */
 
@@ -2000,6 +2024,8 @@ get_odr_type (tree type, bool insert)
   int base_id = -1;
 
   type = TYPE_MAIN_VARIANT (type);
+  if (!in_lto_p)
+    type = TYPE_CANONICAL (type);
 
   gcc_checking_assert (can_be_name_hashed_p (type)
 		       || can_be_vtable_hashed_p (type));
Index: testsuite/g++.dg/ipa/devirt-30.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-30.C	(revision 267337)
+++ testsuite/g++.dg/ipa/devirt-30.C	(working copy)
@@ -1,4 +1,5 @@
 // PR c++/58678
+// { dg-do compile }
 // { dg-options "-O3 -fdump-ipa-devirt" }
 
 // We shouldn't speculatively devirtualize to ~B because B is an abstract
Index: testsuite/g++.dg/lto/devirt-13_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-13_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-13_0.C	(working copy)
@@ -0,0 +1,5 @@
+/* { dg-lto-do run } */
+/* Call to foo should be devirtualized because there are no derived types of A.  */
+/* { dg-lto-options "-O2 -flto -fdump-tree-ssa"  } */
+#include "../ipa/devirt-13.C"
+/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "ssa"} } */
Index: testsuite/g++.dg/lto/devirt-14_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-14_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-14_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options "-O2 -fdump-tree-ssa"  } */
+#include "../ipa/devirt-14.C"
+/* { dg-final { scan-tree-dump-not "A.*foo" "ssa"} } */
Index: testsuite/g++.dg/lto/devirt-19_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-19_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-19_0.C	(working copy)
@@ -0,0 +1,5 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { "-O2 -fdump-ipa-cp -Wno-return-type -flto -r -nostdlib" } } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
+#include "../ipa/devirt-19.C"
+/* { dg-final { scan-wpa-ipa-dump-times "Discovered a virtual call to a known target" 1 "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-1_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-1_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-1_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized -flto" } } */
+#include "../ipa/devirt-1.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to a known target.*foo"  "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-22_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-22_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-22_0.C	(working copy)
@@ -0,0 +1,5 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-ipa-sra -fdump-ipa-cp -flto -r -nostdlib" } } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
+#include "../ipa/devirt-22.C"
+/* { dg-final { scan-wpa-ipa-dump-times "Discovered a virtual call to a known target" 2 "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-23_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-23_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-23_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-ipa-sra -flto -fno-devirtualize-speculatively" } } */
+#include "../ipa/devirt-23.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to" "cp" { xfail *-*-* } } } */
Index: testsuite/g++.dg/lto/devirt-2_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-2_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-2_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized -flto" } } */
+#include "../ipa/devirt-2.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to a known target.*foo"  "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-30_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-30_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-30_0.C	(working copy)
@@ -0,0 +1,5 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { "-O3 -fdump-ipa-devirt -flto -r -nostdlib" } } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
+#include "../ipa/devirt-30.C"
+// { dg-final { scan-wpa-ipa-dump-not "Speculatively devirtualizing" "devirt" } }
Index: testsuite/g++.dg/lto/devirt-34_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-34_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-34_0.C	(working copy)
@@ -0,0 +1,6 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { "-O2 -fdump-ipa-devirt -flto -r -nostdlib" } } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
+#include "../ipa/devirt-34.C"
+/* { dg-final { scan-wpa-ipa-dump "Speculative targets"  "devirt"  } } */
+/* { dg-final { scan-wpa-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
Index: testsuite/g++.dg/lto/devirt-3_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-3_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-3_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized -flto" } } */
+#include "../ipa/devirt-3.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to a known target.*foo"  "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-4_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-4_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-4_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized -flto" } } */
+#include "../ipa/devirt-4.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to a known target.*foo"  "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-5_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-5_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-5_0.C	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized -flto" } } */
+#include "../ipa/devirt-5.C"
+/* { dg-final { scan-wpa-ipa-dump "Discovered a virtual call to a known target.*foo"  "cp"  } } */
Index: testsuite/g++.dg/lto/devirt-6_0.C
===================================================================
--- testsuite/g++.dg/lto/devirt-6_0.C	(nonexistent)
+++ testsuite/g++.dg/lto/devirt-6_0.C	(working copy)
@@ -0,0 +1,3 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { "-O3 -flto" } } */
+#include "../ipa/devirt-6.C"
Index: tree.c
===================================================================
--- tree.c	(revision 267337)
+++ tree.c	(working copy)
@@ -12838,25 +12838,6 @@ virtual_method_call_p (const_tree target
   return true;
 }
 
-/* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
-
-tree
-obj_type_ref_class (const_tree ref)
-{
-  gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
-  ref = TREE_TYPE (ref);
-  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
-  ref = TREE_TYPE (ref);
-  /* We look for type THIS points to.  ObjC also builds
-     OBJ_TYPE_REF with non-method calls, Their first parameter
-     ID however also corresponds to class type. */
-  gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
-		       || TREE_CODE (ref) == FUNCTION_TYPE);
-  ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
-  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
-  return TREE_TYPE (ref);
-}
-
 /* Lookup sub-BINFO of BINFO of TYPE at offset POS.  */
 
 static tree


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