https://gcc.gnu.org/g:c33d8c55a79f08e4a14b4bc601b270268d3c4c89
commit r15-4539-gc33d8c55a79f08e4a14b4bc601b270268d3c4c89 Author: Richard Biener <rguent...@suse.de> Date: Mon Oct 21 14:01:23 2024 +0200 tree-optimization/117123 - missed PHI equivalence in VN Value-numbering can use its set of equivalences to prove that a PHI node with args <a_1, 5, 10> is equal to a_1 iff on the edges with the constants a_1 == 5 and a_1 == 10 hold. This breaks down when the order of PHI args is <5, 10, a_1> as then we drop to VARYING early. The following mitigates this by shuffling a copy of the edge vector to always process a SSA name argument first. Which should also handle the special-case of a two argument <5, a_1> we already had. PR tree-optimization/117123 * tree-ssa-sccvn.cc (visit_phi): First process a non-constant argument edge to handle more equivalences. Remove the two-arg special case. * g++.dg/tree-ssa/pr117123.C: New testcase. Diff: --- gcc/testsuite/g++.dg/tree-ssa/pr117123.C | 52 ++++++++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.cc | 50 +++++++++++++++--------------- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr117123.C b/gcc/testsuite/g++.dg/tree-ssa/pr117123.C new file mode 100644 index 000000000000..2aa2810de952 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr117123.C @@ -0,0 +1,52 @@ +// { dg-do compile } +// { dg-options "-Os -fdump-tree-optimized" } + +struct Potato { + int size; + bool isMashed; +}; + +int dont_be_here(); + +int patatino(int a) { + if (a > 5 && a % 2 == 0 && a != 10) { + return a * 2; + } else { + Potato spud; + spud.size = a; + spud.isMashed = false; + + for (int i = 0; i < 10; i++) { + if (i > 10 && i < 5 && a == -1) { + for (int j = 0; j < 5; j++) { + spud.size += j; + } + } + } + + for (int k = 0; k < 10 && a == -100 && spud.size > 1000; k++) { + for (int l = 0; l < 5; l++) { + spud.size += l * k; + } + } + + for (int m = 0; m < 10 && a == -1000 && spud.size < -1000; m++) { + dont_be_here(); + } + + if (a > 10000 && spud.size < -10000) { + spud.size *= 2; + } + + for (int n = 0; n < 10 && a == -2000 && spud.size > 2000; n++) { + for (int o = 0; o < 5; o++) { + spud.size -= o * n; + } + } + + return spud.size; + } +} + +// { dg-final { scan-tree-dump-not "dont_be_here" "optimized" } } +// { dg-final { scan-tree-dump-times "if " 3 "optimized" } } diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index abf7d38d15cb..84a0c3796950 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -5948,8 +5948,7 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p) tree sameval_base = NULL_TREE; poly_int64 soff, doff; unsigned n_executable = 0; - edge_iterator ei; - edge e, sameval_e = NULL; + edge sameval_e = NULL; /* TODO: We could check for this in initialization, and replace this with a gcc_assert. */ @@ -5962,10 +5961,32 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p) if (!inserted) gimple_set_plf (phi, GF_PLF_1, false); + basic_block bb = gimple_bb (phi); + + /* For the equivalence handling below make sure to first process an + edge with a non-constant. */ + auto_vec<edge, 2> preds; + preds.reserve_exact (EDGE_COUNT (bb->preds)); + bool seen_nonconstant = false; + for (unsigned i = 0; i < EDGE_COUNT (bb->preds); ++i) + { + edge e = EDGE_PRED (bb, i); + preds.quick_push (e); + if (!seen_nonconstant) + { + tree def = PHI_ARG_DEF_FROM_EDGE (phi, e); + if (TREE_CODE (def) == SSA_NAME) + { + seen_nonconstant = true; + if (i != 0) + std::swap (preds[0], preds[i]); + } + } + } + /* See if all non-TOP arguments have the same value. TOP is equivalent to everything, so we can ignore it. */ - basic_block bb = gimple_bb (phi); - FOR_EACH_EDGE (e, ei, bb->preds) + for (edge e : preds) if (e->flags & EDGE_EXECUTABLE) { tree def = PHI_ARG_DEF_FROM_EDGE (phi, e); @@ -6065,27 +6086,6 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p) } continue; } - /* If on all previous edges the value was equal to def - we can change sameval to def. */ - if (EDGE_COUNT (bb->preds) == 2 - && (val = vn_nary_op_get_predicated_value - (vnresult, EDGE_PRED (bb, 0))) - && integer_truep (val) - && !(e->flags & EDGE_DFS_BACK)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Predication says "); - print_generic_expr (dump_file, def, TDF_NONE); - fprintf (dump_file, " and "); - print_generic_expr (dump_file, sameval, TDF_NONE); - fprintf (dump_file, " are equal on edge %d -> %d\n", - EDGE_PRED (bb, 0)->src->index, - EDGE_PRED (bb, 0)->dest->index); - } - sameval = def; - continue; - } } } sameval = NULL_TREE;