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]

Re: Fix devirtualization with LTO


Hi Jan

On 22/12/18 8:08 PM, Jan Hubicka wrote:
> 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.
> 	
I am seeing the following failures on aarch64-none-elf, 
aarch64-none-linux-gnu, aarch64_be-none-elf, arm-none-eabi, 
arm-none-linux-gnueabihf:

UNRESOLVED: g++-dg-lto-devirt-13-01.exe scan-tree-dump-times ssa 
"OBJ_TYPE_REF" 0
UNRESOLVED: g++-dg-lto-devirt-13-11.exe scan-tree-dump-times ssa 
"OBJ_TYPE_REF" 0
UNRESOLVED: g++-dg-lto-devirt-13-21.exe scan-tree-dump-times ssa 
"OBJ_TYPE_REF" 0
UNRESOLVED: g++-dg-lto-devirt-14-01.exe scan-tree-dump-not ssa "A.*foo"
UNRESOLVED: g++-dg-lto-devirt-14-11.exe scan-tree-dump-not ssa "A.*foo"
UNRESOLVED: g++-dg-lto-devirt-23-01.exe scan-wpa-ipa-dump cp "Discovered 
a virtual call to"

With an error like:

g++-dg-lto-devirt-14-11.exe: dump file does not exist

In my brief attempt, I can see that the scan-dump* routines are 
computing the wrong base name. I get the following if I edit

diff --git a/gcc/testsuite/lib/scandump.exp 
b/gcc/testsuite/lib/scandump.exp
index 3d42692..5961623 100644
--- a/gcc/testsuite/lib/scandump.exp
+++ b/gcc/testsuite/lib/scandump.exp
@@ -160,7 +160,7 @@ proc scan-dump-not { args } {
      set dumpbase [dump-base $src [lindex $args 3]]
      set output_file "[glob -nocomplain $dumpbase.[lindex $args 2]]"
      if { $output_file == "" } {
-       verbose -log "$testcase: dump file does not exist"
+       verbose -log "$testcase: dump file does not exist $dumpbase"
         unresolved "$testname"
         return
      }

g++-dg-lto-devirt-14-11.exe: dump file does not exist 
g++-dg-lto-devirt-14-11.exe

UNRESOLVED: g++-dg-lto-devirt-14-11.exe scan-tree-dump-not ssa "A.*foo

Thanks

Sudi

> 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]