Hi, On Wed, Jun 18, 2014 at 06:12:34PM +0200, Bernhard Reutner-Fischer wrote: > On 18 June 2014 10:24:16 Martin Jambor <mjam...@suse.cz> wrote: > > >@@ -3002,10 +3014,8 @@ try_make_edge_direct_virtual_call (struct > >cgraph_edge *ie, > > > > if (target) > > { > >-#ifdef ENABLE_CHECKING > >- gcc_assert (possible_polymorphic_call_target_p > >- (ie, cgraph_get_node (target))); > >-#endif > >+ if (!possible_polymorphic_call_target_p (ie, cgraph_get_node > >(target))) > >+ return ipa_make_edge_direct_to_target (ie, target); > > return ipa_make_edge_direct_to_target (ie, target); > > } > > The above looks odd. You return the same thing both conditionally > and unconditionally? >
You are obviously right, apparently I was too tired to attempt to work that night. Thanks, for spotting it. The following patch has this corrected and it also passes bootstrap and testing on x86_64-linux on both the trunk and the 4.9 branch. OK for both? Thanks, Martin 2014-06-19 Martin Jambor <mjam...@suse.cz> PR ipa/61540 * ipa-prop.c (impossible_devirt_target): New function. (try_make_edge_direct_virtual_call): Use it, also instead of asserting. testsuite/ * g++.dg/ipa/pr61540.C: New test. diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index b67deed..d9dca52 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2912,6 +2912,29 @@ try_make_edge_direct_simple_call (struct cgraph_edge *ie, return cs; } +/* Return the target to be used in cases of impossible devirtualization. IE + and target (the latter can be NULL) are dumped when dumping is enabled. */ + +static tree +impossible_devirt_target (struct cgraph_edge *ie, tree target) +{ + if (dump_file) + { + if (target) + fprintf (dump_file, + "Type inconsident devirtualization: %s/%i->%s\n", + ie->caller->name (), ie->caller->order, + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target))); + else + fprintf (dump_file, + "No devirtualization target in %s/%i\n", + ie->caller->name (), ie->caller->order); + } + tree new_target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + cgraph_get_create_node (new_target); + return new_target; +} + /* Try to find a destination for indirect edge IE that corresponds to a virtual call based on a formal parameter which is described by jump function JFUNC and if it can be determined, make it direct and return the direct edge. @@ -2946,15 +2969,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) || !possible_polymorphic_call_target_p (ie, cgraph_get_node (target))) - { - if (dump_file) - fprintf (dump_file, - "Type inconsident devirtualization: %s/%i->%s\n", - ie->caller->name (), ie->caller->order, - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target))); - target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); - cgraph_get_create_node (target); - } + target = impossible_devirt_target (ie, target); return ipa_make_edge_direct_to_target (ie, target); } } @@ -2984,10 +2999,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, if (targets.length () == 1) target = targets[0]->decl; else - { - target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); - cgraph_get_create_node (target); - } + target = impossible_devirt_target (ie, NULL_TREE); } else { @@ -3002,10 +3014,8 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, if (target) { -#ifdef ENABLE_CHECKING - gcc_assert (possible_polymorphic_call_target_p - (ie, cgraph_get_node (target))); -#endif + if (!possible_polymorphic_call_target_p (ie, cgraph_get_node (target))) + target = impossible_devirt_target (ie, target); return ipa_make_edge_direct_to_target (ie, target); } else diff --git a/gcc/testsuite/g++.dg/ipa/pr61540.C b/gcc/testsuite/g++.dg/ipa/pr61540.C new file mode 100644 index 0000000..d298964 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr61540.C @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp" } */ + +struct data { + data(int) {} +}; + +struct top { + virtual int topf() {} +}; + +struct intermediate: top { + int topf() /* override */ { return 0; } +}; + +struct child1: top { + void childf() + { + data d(topf()); + } +}; + +struct child2: intermediate {}; + +void test(top& t) +{ + child1& c = static_cast<child1&>(t); + c.childf(); + child2 d; + test(d); +} + +int main (int argc, char **argv) +{ + child1 c; + test (c); + return 0; +} + +/* { dg-final { scan-ipa-dump "Type inconsident devirtualization" "cp" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */