On 17 Nov 13:32, Richard Biener wrote:
> On Mon, Nov 10, 2014 at 4:48 PM, Ilya Enkovich <[email protected]> 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 <[email protected]>
> >
> > * passes.c (remove_cgraph_node_from_order): New.
> > (do_per_function_toporder): Register cgraph removal
> > hook.
> >
> > gcc/testsuite/
> >
> > 2014-11-10 Ilya Enkovich <[email protected]>
> >
> > * 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);
+ });
+}