From 5e3552617012e976ec766da0590796e62ff8075e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 22 Dec 2017 09:50:30 +0100 Subject: [PATCH] backport: re PR ipa/82801 (Internal compiler error with Eigen and __attribute__((always_inline, flatten))) Backported from mainline 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. * g++.dg/ipa/pr82801.C: New test. From-SVN: r255968 --- gcc/ChangeLog | 13 ++++++ gcc/ipa-inline.c | 68 ++++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/g++.dg/ipa/pr82801.C | 20 +++++++++ 4 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/pr82801.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 480fa32ec0e..30344b18819 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2017-12-22 Jakub Jelinek + + Backported from mainline + 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. + 2017-12-21 Uros Bizjak PR target/83467 diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 4843f8a2f8e..0dfdd551577 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -2358,6 +2358,19 @@ dump_inline_stats (void) (int) reason[i][2], (int) reason[i][1], 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. */ @@ -2367,7 +2380,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; @@ -2408,26 +2421,56 @@ ipa_inline (void) if (dump_file) fprintf (dump_file, "\nFlattening functions:\n"); - /* 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--) + /* 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 > 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 (); @@ -2439,7 +2482,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 0545b869ee7..9cf9bfce76c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2017-12-22 Jakub Jelinek + + Backported from mainline + 2017-12-19 Jakub Jelinek + + PR ipa/82801 + PR ipa/83346 + * g++.dg/ipa/pr82801.C: New test. + 2017-12-21 Uros Bizjak PR target/83467 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; +}