diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7274aa4e7a6..f15a8a882bb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-03-28 Richard Biener + + PR ipa/80205 + * tree-inline.c (copy_phis_for_bb): Do not create PHI node + without arguments, generate default definition of a SSA name. + 2017-03-28 Richard Biener PR middle-end/80222 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fe42af1b3bb..b3a54711f24 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-03-28 Martin Liska + + PR ipa/80205 + * g++.dg/ipa/pr80205.C: New test. + 2017-03-28 Senthil Kumar Selvaraj * gcc.c-torture/execute/pr79121.c:Use __{U}INT32_TYPE__ for targets diff --git a/gcc/testsuite/g++.dg/ipa/pr80205.C b/gcc/testsuite/g++.dg/ipa/pr80205.C new file mode 100644 index 00000000000..460bdcb02ca --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr80205.C @@ -0,0 +1,34 @@ +// PR ipa/80205 +// { dg-options "-fnon-call-exceptions --param early-inlining-insns=100 -O2" } + +class a +{ +public: + virtual ~a (); +}; +class b +{ +public: + template b (c); + ~b () { delete d; } + void + operator= (b e) + { + b (e).f (*this); + } + void + f (b &e) + { + a g; + d = e.d; + e.d = &g; + } + a *d; +}; +void +h () +{ + b i = int(); + void j (); + i = j; +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 6b6d489f6ca..09e80e6a5bc 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2344,50 +2344,60 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id) if (!virtual_operand_p (res)) { walk_tree (&new_res, copy_tree_body_r, id, NULL); - new_phi = create_phi_node (new_res, new_bb); - FOR_EACH_EDGE (new_edge, ei, new_bb->preds) + if (EDGE_COUNT (new_bb->preds) == 0) { - edge old_edge = find_edge ((basic_block) new_edge->src->aux, bb); - tree arg; - tree new_arg; - edge_iterator ei2; - location_t locus; - - /* When doing partial cloning, we allow PHIs on the entry block - as long as all the arguments are the same. Find any input - edge to see argument to copy. */ - if (!old_edge) - FOR_EACH_EDGE (old_edge, ei2, bb->preds) - if (!old_edge->src->aux) - break; - - arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge); - new_arg = arg; - walk_tree (&new_arg, copy_tree_body_r, id, NULL); - gcc_assert (new_arg); - /* With return slot optimization we can end up with - non-gimple (foo *)&this->m, fix that here. */ - if (TREE_CODE (new_arg) != SSA_NAME - && TREE_CODE (new_arg) != FUNCTION_DECL - && !is_gimple_val (new_arg)) + /* Technically we'd want a SSA_DEFAULT_DEF here... */ + SSA_NAME_DEF_STMT (new_res) = gimple_build_nop (); + } + else + { + new_phi = create_phi_node (new_res, new_bb); + FOR_EACH_EDGE (new_edge, ei, new_bb->preds) { - gimple_seq stmts = NULL; - new_arg = force_gimple_operand (new_arg, &stmts, true, NULL); - gsi_insert_seq_on_edge (new_edge, stmts); - inserted = true; - } - locus = gimple_phi_arg_location_from_edge (phi, old_edge); - if (LOCATION_BLOCK (locus)) - { - tree *n; - n = id->decl_map->get (LOCATION_BLOCK (locus)); - gcc_assert (n); - locus = set_block (locus, *n); - } - else - locus = LOCATION_LOCUS (locus); + edge old_edge = find_edge ((basic_block) new_edge->src->aux, + bb); + tree arg; + tree new_arg; + edge_iterator ei2; + location_t locus; - add_phi_arg (new_phi, new_arg, new_edge, locus); + /* When doing partial cloning, we allow PHIs on the entry + block as long as all the arguments are the same. + Find any input edge to see argument to copy. */ + if (!old_edge) + FOR_EACH_EDGE (old_edge, ei2, bb->preds) + if (!old_edge->src->aux) + break; + + arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge); + new_arg = arg; + walk_tree (&new_arg, copy_tree_body_r, id, NULL); + gcc_assert (new_arg); + /* With return slot optimization we can end up with + non-gimple (foo *)&this->m, fix that here. */ + if (TREE_CODE (new_arg) != SSA_NAME + && TREE_CODE (new_arg) != FUNCTION_DECL + && !is_gimple_val (new_arg)) + { + gimple_seq stmts = NULL; + new_arg = force_gimple_operand (new_arg, &stmts, true, + NULL); + gsi_insert_seq_on_edge (new_edge, stmts); + inserted = true; + } + locus = gimple_phi_arg_location_from_edge (phi, old_edge); + if (LOCATION_BLOCK (locus)) + { + tree *n; + n = id->decl_map->get (LOCATION_BLOCK (locus)); + gcc_assert (n); + locus = set_block (locus, *n); + } + else + locus = LOCATION_LOCUS (locus); + + add_phi_arg (new_phi, new_arg, new_edge, locus); + } } } }