> 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?
OK, Honza > > 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" } } */