https://gcc.gnu.org/g:201cd2d3bef8e935eb9af04a516b9d224b5b8470
commit r16-1285-g201cd2d3bef8e935eb9af04a516b9d224b5b8470 Author: Andrew Pinski <quic_apin...@quicinc.com> Date: Fri Jun 6 11:34:48 2025 -0700 phi-opt: Do limited form of cselim from phiopt [PR120533] So currently cselim is limited to targets which have conditional move and also happens later in the pipeline. This adds the limited form of cselim; where there is only one store in the two sides and no loads after the store. This fixes phiprop-2.c for gcn target and now can match the MIN in phiopt1 so it moves the matching of MIN to phiopt1. The other testcases already disable cselim so they need to disable phiopt too. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/120533 gcc/ChangeLog: * tree-ssa-phiopt.cc (cond_if_else_store_replacement_limited): New function. (pass_phiopt::execute): Call cond_if_else_store_replacement_limited for diamand case. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr35286.c: Add -fno-ssa-phiopt. * gcc.dg/tree-ssa/split-path-6.c: Likewise. * gcc.dg/tree-ssa/split-path-7.c: Likewise. * gcc.dg/tree-ssa/phiprop-2.c: Move the check for MIN_EXPR to phiopt1. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> Diff: --- gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c | 5 ++- gcc/testsuite/gcc.dg/tree-ssa/pr35286.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c | 2 +- gcc/tree-ssa-phiopt.cc | 49 ++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c index 7181787db5eb..ae0d181a43ac 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -fdump-tree-phiopt2 -fdump-tree-phiprop1-details" } */ +/* { dg-options "-O1 -fdump-tree-phiopt1 -fdump-tree-phiprop1-details" } */ /* PR tree-optimization/116824 */ @@ -24,5 +24,4 @@ int g(int i, int *tt) /* Check that phiprop1 can do the insert of the loads. */ /* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop1"} } */ -/* Should be able to get MIN_EXPR in phiopt2 after cselim and phiprop. */ -/* { dg-final { scan-tree-dump-times "MIN_EXPR " 1 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR " 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c b/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c index 4429cc857bf6..b4f8c7ce4fce 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-code-hoisting -fno-tree-cselim -fdump-tree-pre-stats" } */ +/* { dg-options "-O2 -fno-code-hoisting -fno-tree-cselim -fno-ssa-phiopt -fdump-tree-pre-stats" } */ int g2; struct A { int a; int b; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c index 71e6362b10c8..e2b0a9571f0d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fdump-tree-split-paths-details -fno-finite-loops -fno-tree-dominator-opts -fno-tree-vrp -w" } */ +/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fno-ssa-phiopt -fdump-tree-split-paths-details -fno-finite-loops -fno-tree-dominator-opts -fno-tree-vrp -w" } */ struct __sFILE { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c index 252fe06c666a..35634ab3bd86 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fno-tree-sink -fdump-tree-split-paths-details -w" } */ +/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fno-ssa-phiopt -fno-tree-sink -fdump-tree-split-paths-details -w" } */ struct _reent diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 1e770cb0e805..c4e05966924f 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -3739,6 +3739,50 @@ single_trailing_store_in_bb (basic_block bb, tree vdef, gphi *vphi) return store; } +/* Limited Conditional store replacement. We already know + that the recognized pattern looks like so: + + split: + if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) + THEN_BB: + ... + ONLY_STORE = Y; + ... + goto JOIN_BB; + ELSE_BB: + ... + ONLY_STORE = Z; + ... + fallthrough (edge E0) + JOIN_BB: + some more + + Handles only the case with single store in THEN_BB and ELSE_BB. That is + cheap enough due to in phiopt and not worry about heurstics. Moving the store + out might provide an opportunity for a phiopt to happen. */ + +static bool +cond_if_else_store_replacement_limited (basic_block then_bb, basic_block else_bb, + basic_block join_bb) +{ + gphi *vphi = get_virtual_phi (join_bb); + if (!vphi) + return false; + + tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb)); + gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef, vphi); + if (!then_assign) + return false; + + tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb)); + gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef, vphi); + if (!else_assign) + return false; + + return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, + then_assign, else_assign, vphi); +} + /* Conditional store replacement. We already know that the recognized pattern looks like so: @@ -4460,6 +4504,11 @@ pass_phiopt::execute (function *) && !predictable_edge_p (EDGE_SUCC (bb, 0)) && !predictable_edge_p (EDGE_SUCC (bb, 1))) hoist_adjacent_loads (bb, bb1, bb2, bb3); + + /* Try to see if there are only one store in each side of the if + and try to remove that. */ + if (EDGE_COUNT (bb3->preds) == 2) + cond_if_else_store_replacement_limited (bb1, bb2, bb3); } gimple_stmt_iterator gsi;