From: hubicka Date: Sat, 18 Sep 2010 23:13:17 +0000 (+0000) Subject: PR tree-optimization/45453 X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;ds=sidebyside;h=d050bafd156a2ec8ce1382590158b853acf1c6ee;p=pf3gnuchains%2Fgcc-fork.git PR tree-optimization/45453 * cgraphunit.c (cgraph_finalize_function): Consider comdat & external virtual functions are reachable. * ipa-inline.c (cgraph_clone_inlined_nodes): Likewise. * ipa.c (cgraph_remove_unreachable_nodes): Likewise. * ipa-prop.c (ipa_modify_formal_parameters): Clear DECL_VIRTUAL_P when modifying function. * g++.dg/tree-ssa/pr45453.C: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164405 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f6508998fc4..125840938a9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2010-09-18 Jan Hubicka + PR tree-optimization/45453 + * cgraphunit.c (cgraph_finalize_function): Consider comdat & external + virtual functions are reachable. + * ipa-inline.c (cgraph_clone_inlined_nodes): Likewise. + * ipa.c (cgraph_remove_unreachable_nodes): Likewise. + * ipa-prop.c (ipa_modify_formal_parameters): Clear DECL_VIRTUAL_P + when modifying function. + +2010-09-18 Jan Hubicka + PR tree-optimization/45605 * cgraphunit.c (cgraph_analyze_functions): Allocate bitmap obstack. * gimple-fold.c (static_object_in_other_unit_p): New function. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f296fe05604..e390ec61706 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -363,7 +363,13 @@ cgraph_finalize_function (tree decl, bool nested) there. */ if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) || DECL_STATIC_CONSTRUCTOR (decl) - || DECL_STATIC_DESTRUCTOR (decl)) + || DECL_STATIC_DESTRUCTOR (decl) + /* COMDAT virtual functions may be referenced by vtable from + other compilatoin unit. Still we want to devirtualize calls + to those so we need to analyze them. + FIXME: We should introduce may edges for this purpose and update + their handling in unreachable function removal and inliner too. */ + || (DECL_VIRTUAL_P (decl) && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl)))) cgraph_mark_reachable_node (node); /* If we've not yet emitted decl, tell the debug info about it. */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 964d03ba21a..21e0b647973 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -251,6 +251,12 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, In that case just go ahead and re-use it. */ if (!e->callee->callers->next_caller && cgraph_can_remove_if_no_direct_calls_p (e->callee) + /* Inlining might enable more devirtualizing, so we want to remove + those only after all devirtualizable virtual calls are processed. + Lacking may edges in callgraph we just preserve them post + inlining. */ + && (!DECL_VIRTUAL_P (e->callee->decl) + || (!DECL_COMDAT (e->callee->decl) && !DECL_EXTERNAL (e->callee->decl))) /* Don't reuse if more than one function shares a comdat group. If the other function(s) are needed, we need to emit even this function out of line. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index ec45d7c5271..e1d821e3988 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2120,6 +2120,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, } TREE_TYPE (fndecl) = new_type; + DECL_VIRTUAL_P (fndecl) = 0; if (otypes) VEC_free (tree, heap, otypes); VEC_free (tree, heap, oparms); diff --git a/gcc/ipa.c b/gcc/ipa.c index 8c0ca86d59d..e4835c1e03f 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -238,7 +238,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) #endif varpool_reset_queue (); for (node = cgraph_nodes; node; node = node->next) - if (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node) + if ((!cgraph_can_remove_if_no_direct_calls_and_refs_p (node) + /* Keep around virtual functions for possible devirtualization. */ + || (!before_inlining_p + && !node->global.inlined_to + && DECL_VIRTUAL_P (node->decl) + && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))) && ((!DECL_EXTERNAL (node->decl)) || before_inlining_p)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56d0fbd5006..805e4b89357 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-09-18 Jan Hubicka + + PR tree-optimization/45453 + * g++.dg/tree-ssa/pr45453.C: New testcase. + 2010-09-18 Jason Merrill * g++.dg/cpp0x/initlist44.C: New. diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45453.C b/gcc/testsuite/g++.dg/tree-ssa/pr45453.C new file mode 100644 index 00000000000..78c6460f727 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr45453.C @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +struct S +{ + S(); + virtual inline void foo () + { + foo(); + } +}; + +void +B () +{ + S().foo (); +} +/* We should inline foo and devirtualize call to foo in the inlined version. */ +// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 1 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } }