https://gcc.gnu.org/g:0a1d2ea57722c248777e1130de076e28c443ff8b
commit r15-7472-g0a1d2ea57722c248777e1130de076e28c443ff8b Author: Richard Biener <rguent...@suse.de> Date: Tue Feb 11 10:29:18 2025 +0100 tree-optimization/118817 - missed folding of PRE inserted code When PRE inserts code it is not fully folded with following SSA edges which can cause missed optimizations since the next fully folding pass is way ahead, after strlen which in the PRs case leads to diagnostics emitted on dead code. The following mitigates the missed expression canonicalization that happens during PHI translation where to be inserted expressions are calculated. It is largely refactoring and eliminating the single use of fully_constant_expression and otherwise leverages the work already done by vn_nary_simplify by updating the NARY with the simplified expression. PR tree-optimization/118817 * tree-ssa-pre.cc (fully_constant_expression): Fold into the single caller. (phi_translate_1): Refactor folded in fully_constant_expression. * tree-ssa-sccvn.cc (vn_nary_simplify): Update the NARY with the simplified expression. * g++.dg/lto/pr118817_0.C: New testcase. Diff: --- gcc/testsuite/g++.dg/lto/pr118817_0.C | 17 ++++++ gcc/tree-ssa-pre.cc | 111 ++++++++++++---------------------- gcc/tree-ssa-sccvn.cc | 13 +++- 3 files changed, 65 insertions(+), 76 deletions(-) diff --git a/gcc/testsuite/g++.dg/lto/pr118817_0.C b/gcc/testsuite/g++.dg/lto/pr118817_0.C new file mode 100644 index 000000000000..ae65f34504e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr118817_0.C @@ -0,0 +1,17 @@ +// { dg-lto-do link } +// { dg-lto-options { { -O3 -fPIC -flto -shared -std=c++20 -Wall } } } +// { dg-require-effective-target fpic } +// { dg-require-effective-target shared } + +#include <memory> +#include <vector> +#include <string> + +int func() +{ + auto strVec = std::make_unique<std::vector<std::string>>(); + strVec->emplace_back("One"); + strVec->emplace_back("Two"); + strVec->emplace_back("Three"); + return 0; +} diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc index 735893bb191e..ecf45d29e769 100644 --- a/gcc/tree-ssa-pre.cc +++ b/gcc/tree-ssa-pre.cc @@ -1185,41 +1185,6 @@ get_or_alloc_expr_for_constant (tree constant) return newexpr; } -/* Return the folded version of T if T, when folded, is a gimple - min_invariant or an SSA name. Otherwise, return T. */ - -static pre_expr -fully_constant_expression (pre_expr e) -{ - switch (e->kind) - { - case CONSTANT: - return e; - case NARY: - { - vn_nary_op_t nary = PRE_EXPR_NARY (e); - tree res = vn_nary_simplify (nary); - if (!res) - return e; - if (is_gimple_min_invariant (res)) - return get_or_alloc_expr_for_constant (res); - if (TREE_CODE (res) == SSA_NAME) - return get_or_alloc_expr_for_name (res); - return e; - } - case REFERENCE: - { - vn_reference_t ref = PRE_EXPR_REFERENCE (e); - tree folded; - if ((folded = fully_constant_vn_reference_p (ref))) - return get_or_alloc_expr_for_constant (folded); - return e; - } - default: - return e; - } -} - /* Translate the VUSE backwards through phi nodes in E->dest, so that it has the value it would have in E->src. Set *SAME_VALID to true in case the new vuse doesn't change the value id of the OPERANDS. */ @@ -1443,57 +1408,55 @@ phi_translate_1 (bitmap_set_t dest, } if (changed) { - pre_expr constant; unsigned int new_val_id; - PRE_EXPR_NARY (expr) = newnary; - constant = fully_constant_expression (expr); - PRE_EXPR_NARY (expr) = nary; - if (constant != expr) + /* Try to simplify the new NARY. */ + tree res = vn_nary_simplify (newnary); + if (res) { + if (is_gimple_min_invariant (res)) + return get_or_alloc_expr_for_constant (res); + /* For non-CONSTANTs we have to make sure we can eventually insert the expression. Which means we need to have a leader for it. */ - if (constant->kind != CONSTANT) + gcc_assert (TREE_CODE (res) == SSA_NAME); + + /* Do not allow simplifications to non-constants over + backedges as this will likely result in a loop PHI node + to be inserted and increased register pressure. + See PR77498 - this avoids doing predcoms work in + a less efficient way. */ + if (e->flags & EDGE_DFS_BACK) + ; + else { - /* Do not allow simplifications to non-constants over - backedges as this will likely result in a loop PHI node - to be inserted and increased register pressure. - See PR77498 - this avoids doing predcoms work in - a less efficient way. */ - if (e->flags & EDGE_DFS_BACK) - ; - else + unsigned value_id = VN_INFO (res)->value_id; + /* We want a leader in ANTIC_OUT or AVAIL_OUT here. + dest has what we computed into ANTIC_OUT sofar + so pick from that - since topological sorting + by sorted_array_from_bitmap_set isn't perfect + we may lose some cases here. */ + pre_expr constant = find_leader_in_sets (value_id, dest, + AVAIL_OUT (pred)); + if (constant) { - unsigned value_id = get_expr_value_id (constant); - /* We want a leader in ANTIC_OUT or AVAIL_OUT here. - dest has what we computed into ANTIC_OUT sofar - so pick from that - since topological sorting - by sorted_array_from_bitmap_set isn't perfect - we may lose some cases here. */ - constant = find_leader_in_sets (value_id, dest, - AVAIL_OUT (pred)); - if (constant) + if (dump_file && (dump_flags & TDF_DETAILS)) { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "simplifying "); - print_pre_expr (dump_file, expr); - fprintf (dump_file, " translated %d -> %d to ", - phiblock->index, pred->index); - PRE_EXPR_NARY (expr) = newnary; - print_pre_expr (dump_file, expr); - PRE_EXPR_NARY (expr) = nary; - fprintf (dump_file, " to "); - print_pre_expr (dump_file, constant); - fprintf (dump_file, "\n"); - } - return constant; + fprintf (dump_file, "simplifying "); + print_pre_expr (dump_file, expr); + fprintf (dump_file, " translated %d -> %d to ", + phiblock->index, pred->index); + PRE_EXPR_NARY (expr) = newnary; + print_pre_expr (dump_file, expr); + PRE_EXPR_NARY (expr) = nary; + fprintf (dump_file, " to "); + print_pre_expr (dump_file, constant); + fprintf (dump_file, "\n"); } + return constant; } } - else - return constant; } tree result = vn_nary_op_lookup_pieces (newnary->length, diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 6d0202ad4369..06f6b0ccd724 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -2598,7 +2598,8 @@ vn_nary_build_or_lookup (gimple_match_op *res_op) } /* Try to simplify the expression RCODE OPS... of type TYPE and return - its value if present. */ + its value if present. Update NARY with a simplified expression if + it fits. */ tree vn_nary_simplify (vn_nary_op_t nary) @@ -2608,7 +2609,15 @@ vn_nary_simplify (vn_nary_op_t nary) gimple_match_op op (gimple_match_cond::UNCOND, nary->opcode, nary->type, nary->length); memcpy (op.ops, nary->op, sizeof (tree) * nary->length); - return vn_nary_build_or_lookup_1 (&op, false, true); + tree res = vn_nary_build_or_lookup_1 (&op, false, true); + if (op.code.is_tree_code () && op.num_ops <= nary->length) + { + nary->opcode = (tree_code) op.code; + nary->length = op.num_ops; + for (unsigned i = 0; i < op.num_ops; ++i) + nary->op[i] = op.ops[i]; + } + return res; } /* Elimination engine. */