From d6ea70a0dcf7ca69321c6fa7c583bc9a2ca3dfd0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 19 Dec 2017 08:41:30 +0100 Subject: [PATCH] re PR ipa/82801 (Internal compiler error with Eigen and __attribute__((always_inline, flatten))) PR ipa/82801 PR ipa/83346 * ipa-inline.c (flatten_remove_node_hook): New function. (ipa_inline): Keep only nodes with flatten attribute at the end of the array in the order from ipa_reverse_postorder, only walk that portion of array for flattening, if there is more than one such node, temporarily register a removal hook and ignore removed nodes. * g++.dg/ipa/pr82801.C: New test. From-SVN: r255805 --- gcc/ChangeLog | 8 ++++ gcc/ipa-inline.c | 64 +++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/ipa/pr82801.C | 20 ++++++++++ 4 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/pr82801.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f8b773d6b8..9d7875e3918 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2017-12-19 Jakub Jelinek + PR ipa/82801 + PR ipa/83346 + * ipa-inline.c (flatten_remove_node_hook): New function. + (ipa_inline): Keep only nodes with flatten attribute at the end of + the array in the order from ipa_reverse_postorder, only walk that + portion of array for flattening, if there is more than one such + node, temporarily register a removal hook and ignore removed nodes. + PR tree-optimization/80631 * tree-vect-loop.c (vect_create_epilog_for_reduction): Compare induc_code against MAX_EXPR or MIN_EXPR instead of reduc_fn against diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 7846e93d119..4af47b4d055 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -2338,6 +2338,19 @@ dump_inline_stats (void) (int) reason[i][1], reason_freq[i].to_double (), reason[i][0]); } +/* Called when node is removed. */ + +static void +flatten_remove_node_hook (struct cgraph_node *node, void *data) +{ + if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) == NULL) + return; + + hash_set *removed + = (hash_set *) data; + removed->add (node); +} + /* Decide on the inlining. We do so in the topological order to avoid expenses on updating data structures. */ @@ -2347,7 +2360,7 @@ ipa_inline (void) struct cgraph_node *node; int nnodes; struct cgraph_node **order; - int i; + int i, j; int cold; bool remove_functions = false; @@ -2380,26 +2393,56 @@ ipa_inline (void) if (dump_file) fprintf (dump_file, "\nFlattening functions:\n"); + /* First shrink order array, so that it only contains nodes with + flatten attribute. */ + for (i = nnodes - 1, j = i; i >= 0; i--) + { + node = order[i]; + if (lookup_attribute ("flatten", + DECL_ATTRIBUTES (node->decl)) != NULL) + order[j--] = order[i]; + } + + /* After the above loop, order[j + 1] ... order[nnodes - 1] contain + nodes with flatten attribute. If there is more than one such + node, we need to register a node removal hook, as flatten_function + could remove other nodes with flatten attribute. See PR82801. */ + struct cgraph_node_hook_list *node_removal_hook_holder = NULL; + hash_set *flatten_removed_nodes = NULL; + if (j < nnodes - 2) + { + flatten_removed_nodes = new hash_set; + node_removal_hook_holder + = symtab->add_cgraph_removal_hook (&flatten_remove_node_hook, + flatten_removed_nodes); + } + /* In the first pass handle functions to be flattened. Do this with a priority so none of our later choices will make this impossible. */ - for (i = nnodes - 1; i >= 0; i--) + for (i = nnodes - 1; i > j; i--) { node = order[i]; + if (flatten_removed_nodes + && flatten_removed_nodes->contains (node)) + continue; /* Handle nodes to be flattened. Ideally when processing callees we stop inlining at the entry of cycles, possibly cloning that entry point and try to flatten itself turning it into a self-recursive function. */ - if (lookup_attribute ("flatten", - DECL_ATTRIBUTES (node->decl)) != NULL) - { - if (dump_file) - fprintf (dump_file, - "Flattening %s\n", node->name ()); - flatten_function (node, false); - } + if (dump_file) + fprintf (dump_file, "Flattening %s\n", node->name ()); + flatten_function (node, false); + } + + if (j < nnodes - 2) + { + symtab->remove_cgraph_removal_hook (node_removal_hook_holder); + delete flatten_removed_nodes; } + free (order); + if (dump_file) dump_overall_stats (); @@ -2411,7 +2454,6 @@ ipa_inline (void) inline functions and virtual functions so we really know what is called once. */ symtab->remove_unreachable_nodes (dump_file); - free (order); /* Inline functions with a property that after inlining into all callers the code size will shrink because the out-of-line copy is eliminated. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eb2eba70d66..5c375c1b8b6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-12-19 Jakub Jelinek + + PR ipa/82801 + PR ipa/83346 + * g++.dg/ipa/pr82801.C: New test. + 2017-12-18 Martin Sebor PR middle-end/83373 diff --git a/gcc/testsuite/g++.dg/ipa/pr82801.C b/gcc/testsuite/g++.dg/ipa/pr82801.C new file mode 100644 index 00000000000..d0c2756e47a --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr82801.C @@ -0,0 +1,20 @@ +// PR ipa/82801 +// { dg-do compile } +// { dg-options "-O2 -Wno-attributes" } + +template +struct A { A () {} }; +struct B { double foo () const; }; + +__attribute__((always_inline, flatten)) +double B::foo () const +{ + A<1> v; + return 0.0; +} + +int +main () +{ + return 0; +} -- 2.30.2