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. > + 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,8 @@ 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); > + free (order_idx); > } > 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); > + }); > +}