The following avoids picking up dead code left over from folding during FRE/PRE, effectively undoing propagations.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/107569 * tree-ssa-sccvn.cc (eliminate_dom_walker::eliminate_stmt): Do not push SSA names with zero uses as available leader. (process_bb): Likewise. * g++.dg/opt/pr107569.C: New testcase. --- gcc/testsuite/g++.dg/opt/pr107569.C | 29 +++++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.cc | 17 +++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr107569.C diff --git a/gcc/testsuite/g++.dg/opt/pr107569.C b/gcc/testsuite/g++.dg/opt/pr107569.C new file mode 100644 index 00000000000..e03941c7862 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr107569.C @@ -0,0 +1,29 @@ +// { dg-do compile } +// { dg-require-effective-target c++20 } +// { dg-options "-O2 -fdump-tree-evrp -fdump-tree-vrp1" } + +namespace std +{ + constexpr bool isfinite (float x) { return __builtin_isfinite (x); } + constexpr bool isfinite (double x) { return __builtin_isfinite (x); } + constexpr bool isfinite (long double x) { return __builtin_isfinite (x); } +} + +bool +foo (double x) +{ + if (!std::isfinite (x)) + __builtin_unreachable (); + + return std::isfinite (x); +} + +bool +bar (double x) +{ + [[assume (std::isfinite (x))]]; + return std::isfinite (x); +} + +/* { dg-final { scan-tree-dump "return 1;" "evrp" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 2 "vrp1" } } */ diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index d5b081a309f..6b8d38b270c 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -7197,10 +7197,14 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi) } /* Make new values available - for fully redundant LHS we - continue with the next stmt above and skip this. */ - def_operand_p defp; - FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF) - eliminate_push_avail (b, DEF_FROM_PTR (defp)); + continue with the next stmt above and skip this. + But avoid picking up dead defs. */ + tree def; + FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) + if (! has_zero_uses (def) + || (inserted_exprs + && bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (def)))) + eliminate_push_avail (b, def); } /* Perform elimination for the basic-block B during the domwalk. */ @@ -8046,9 +8050,10 @@ process_bb (rpo_elim &avail, basic_block bb, avail.eliminate_stmt (bb, &gsi); else /* If not eliminating, make all not already available defs - available. */ + available. But avoid picking up dead defs. */ FOR_EACH_SSA_TREE_OPERAND (op, gsi_stmt (gsi), i, SSA_OP_DEF) - if (! avail.eliminate_avail (bb, op)) + if (! has_zero_uses (op) + && ! avail.eliminate_avail (bb, op)) avail.eliminate_push_avail (bb, op); } -- 2.35.3