On 17 Nov 13:32, Richard Biener wrote: > On Mon, Nov 10, 2014 at 4:48 PM, Ilya Enkovich <enkovich....@gmail.com> wrote: > > Hi, > > > > Here is a fix for PR63766. Currently all functions are transformed into > > SSA before local optimizations and it allows function to be inlined and > > removed before it goes through local optimzations. But this requires > > removal of these functions from working queue. > > > > Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? > > > > Thanks, > > Ilya > > -- > > gcc/ > > > > 2014-11-10 Ilya Enkovich <ilya.enkov...@intel.com> > > > > * passes.c (remove_cgraph_node_from_order): New. > > (do_per_function_toporder): Register cgraph removal > > hook. > > > > gcc/testsuite/ > > > > 2014-11-10 Ilya Enkovich <ilya.enkov...@intel.com> > > > > * g++.dg/pr63766.C: New. > > > > > > diff --git a/gcc/passes.c b/gcc/passes.c > > index 5e91a79..b6a0b0c 100644 > > --- a/gcc/passes.c > > +++ b/gcc/passes.c > > @@ -1609,6 +1609,24 @@ do_per_function (void (*callback) (function *, void > > *data), void *data) > > static int nnodes; > > static GTY ((length ("nnodes"))) cgraph_node **order; > > > > +/* Hook called when NODE is removed and therefore should be > > + excluded from order vector. DATA is an array of integers. > > + DATA[0] holds max index it may be accessed by. For cgraph > > + node DATA[node->uid + 1] holds index of this node in order > > + vector. */ > > +static void > > +remove_cgraph_node_from_order (cgraph_node *node, void *data) > > +{ > > + int *order_idx = (int *)data; > > + > > + if (node->uid >= order_idx[0]) > > + return; > > + > > + int idx = order_idx[node->uid + 1]; > > + if (idx >= 0 && idx < nnodes && order[idx] == node) > > + order[idx] = NULL; > > +} > > + > > /* If we are in IPA mode (i.e., current_function_decl is NULL), call > > function CALLBACK for every function in the call graph. Otherwise, > > call CALLBACK on the current function. > > @@ -1622,13 +1640,29 @@ do_per_function_toporder (void (*callback) > > (function *, void *data), void *data) > > callback (cfun, data); > > else > > { > > + cgraph_node_hook_list *hook; > > + int *order_idx; > > gcc_assert (!order); > > order = ggc_vec_alloc<cgraph_node *> (symtab->cgraph_count); > > + > > + order_idx = (int *)xmalloc (sizeof(int) * (symtab->cgraph_max_uid + > > 1)); > > XALLOCAVEC (int, symtab->graph_max_uid + 1) > > Ok with that change. > > Thanks, > Richard. >
Below is the committed version. Thanks, Ilya -- diff --git a/gcc/passes.c b/gcc/passes.c index c818d8a..f6f3b9d 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1609,6 +1609,24 @@ do_per_function (void (*callback) (function *, void *data), void *data) static int nnodes; static GTY ((length ("nnodes"))) cgraph_node **order; +/* Hook called when NODE is removed and therefore should be + excluded from order vector. DATA is an array of integers. + DATA[0] holds max index it may be accessed by. For cgraph + node DATA[node->uid + 1] holds index of this node in order + vector. */ +static void +remove_cgraph_node_from_order (cgraph_node *node, void *data) +{ + int *order_idx = (int *)data; + + if (node->uid >= order_idx[0]) + return; + + int idx = order_idx[node->uid + 1]; + if (idx >= 0 && idx < nnodes && order[idx] == node) + order[idx] = NULL; +} + /* If we are in IPA mode (i.e., current_function_decl is NULL), call function CALLBACK for every function in the call graph. Otherwise, call CALLBACK on the current function. @@ -1622,13 +1640,29 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data) callback (cfun, data); else { + cgraph_node_hook_list *hook; + int *order_idx; gcc_assert (!order); order = ggc_vec_alloc<cgraph_node *> (symtab->cgraph_count); + + order_idx = XALLOCAVEC (int, symtab->cgraph_max_uid + 1); + memset (order_idx + 1, -1, sizeof (int) * symtab->cgraph_max_uid); + order_idx[0] = symtab->cgraph_max_uid; + nnodes = ipa_reverse_postorder (order); for (i = nnodes - 1; i >= 0; i--) - order[i]->process = 1; + { + order[i]->process = 1; + order_idx[order[i]->uid + 1] = i; + } + hook = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order, + order_idx); for (i = nnodes - 1; i >= 0; i--) { + /* Function could be inlined and removed as unreachable. */ + if (!order[i]) + continue; + struct cgraph_node *node = order[i]; /* Allow possibly removed nodes to be garbage collected. */ @@ -1637,6 +1671,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data) if (node->has_gimple_body_p ()) callback (DECL_STRUCT_FUNCTION (node->decl), data); } + symtab->remove_cgraph_removal_hook (hook); } ggc_free (order); order = NULL; diff --git a/gcc/testsuite/g++.dg/pr63766.C b/gcc/testsuite/g++.dg/pr63766.C new file mode 100644 index 0000000..1414fbe --- /dev/null +++ b/gcc/testsuite/g++.dg/pr63766.C @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c++11 -O2" } */ + +class A +{ + public: + void + getValueType () + { + } + void getTypeClass (); +}; +template <typename ImplClass> class B +{ + public: + void + Visit (A *p1) + { + p1->getTypeClass (); + static_cast<ImplClass *> (0)->VisitAtomicType (0); + } +}; +class C : B<C> +{ + template <typename Fn> + void + dumpChild (Fn p1) + { + p1 (); + } + + public: + void dumpTypeAsChild (int); + void + VisitAtomicType (A *p1) + { + p1->getValueType (); + dumpTypeAsChild (0); + } +}; +void +C::dumpTypeAsChild (int) +{ + dumpChild ([=] + { + Visit (0); + }); +}