aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2025-02-11 10:29:18 +0100
committerRichard Biener <rguenth@gcc.gnu.org>2025-02-11 12:42:04 +0100
commit0a1d2ea57722c248777e1130de076e28c443ff8b (patch)
tree45cfc6d6a626375014681b95b1a464327fb29605 /gcc
parent1bfab1dc79bef1f1120bda37556f2e372a2378f5 (diff)
downloadgcc-0a1d2ea57722c248777e1130de076e28c443ff8b.zip
gcc-0a1d2ea57722c248777e1130de076e28c443ff8b.tar.gz
gcc-0a1d2ea57722c248777e1130de076e28c443ff8b.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/lto/pr118817_0.C17
-rw-r--r--gcc/tree-ssa-pre.cc111
-rw-r--r--gcc/tree-ssa-sccvn.cc13
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 0000000..ae65f34
--- /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 735893b..ecf45d2 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 6d0202a..06f6b0c 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. */