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