In C++ code the clobber gets in the way of phiprop. E.g. ``` if (lr_bitpos.2401_412 < rr_bitpos.2402_413) goto <bb 198>; [INV] else goto <bb 197>; [INV]
<bb 197> : <bb 198> : MEM[(struct poly_int *)&D.192544] ={v} {CLOBBER(bob)}; _1060 = MEM[(const long int &)iftmp.2400_515]; ``` The above comes from fold-const.cc. The clobber in the above case is the clobber from the start of the constructor but other clobbers can also get in the way, see gcc.dg/tree-ssa/phiprop-2.c for an example. This shows up in a lot of C++ code where std::min/max (or even ?: like in the fold-const.cc case) is used with in connection of constructors. So optimizing this early in phiprop can improve code generation and compile time speed. g++.dg/tree-ssa/phiprop-2.C contains the reduced testcase from fold-const.cc. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/116823 gcc/ChangeLog: * tree-ssa-phiprop.cc (phiprop_insert_phi): Get the use_vuse before the looping of the phi arguments, also skip over clobbers to get the use_vuse. (propagate_with_phi): Skip over clobbers for the vuse. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/phiprop-2.c: New test. * g++.dg/tree-ssa/phiprop-1.C: New test. * g++.dg/tree-ssa/phiprop-2.C: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/testsuite/g++.dg/tree-ssa/phiprop-1.C | 23 +++++++++++++++++++ gcc/testsuite/g++.dg/tree-ssa/phiprop-2.C | 25 +++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c | 27 +++++++++++++++++++++++ gcc/tree-ssa-phiprop.cc | 25 ++++++++++++++++++++- 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/phiprop-1.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/phiprop-2.C create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c diff --git a/gcc/testsuite/g++.dg/tree-ssa/phiprop-1.C b/gcc/testsuite/g++.dg/tree-ssa/phiprop-1.C new file mode 100644 index 00000000000..e3388d1d157 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/phiprop-1.C @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiprop1-details -fdump-tree-release_ssa" } */ + +/* PR tree-optimization/116823 */ +/* The clobber on a should not get in the way of phiprop here even if + this is undefined code. */ +/* We should have MIN_EXPR early on then too. */ + +static inline +const int &c(const int &d, const int &e) { + if (d < e) + return d; + return e; +} + +int g(int i, struct f *ff) +{ + const int &a = c(i, 10); + return a; +} +/* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop1"} } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "release_ssa"} } */ + diff --git a/gcc/testsuite/g++.dg/tree-ssa/phiprop-2.C b/gcc/testsuite/g++.dg/tree-ssa/phiprop-2.C new file mode 100644 index 00000000000..1a0d6ed92ee --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/phiprop-2.C @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiprop1-details -fdump-tree-release_ssa" } */ + +/* PR tree-optimization/116823 */ +/* The clobber on the temp s2 should not get in the way of phiprop here. */ +/* We should have MAX_EXPR early on then too. */ +/* This is derived from fold-const.cc; s2 is similar to poly_int. */ + +struct s2 +{ + int i; + s2(const int &a) : i (a) {} +}; + + +int h(s2 b); + +int g(int l, int r) +{ + return h(l > r ? l : r); +} + +/* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop1"} } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "release_ssa"} } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c new file mode 100644 index 00000000000..546031e63d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiprop1-details -fdump-tree-release_ssa" } */ + +/* PR tree-optimization/116823 */ +/* The clobber on b should not get in the way of phiprop here. */ +/* We should have MIN_EXPR early on. */ + +void f(int *); + +int g(int i) +{ + const int t = 10; + const int *a; + { + int b; + f(&b); + if (t < i) + a = &t; + else + a = &i; + } + return *a; +} + +/* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop1"} } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "release_ssa"} } */ + diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc index 2a1cdae46d2..f04990e8cb4 100644 --- a/gcc/tree-ssa-phiprop.cc +++ b/gcc/tree-ssa-phiprop.cc @@ -159,6 +159,20 @@ phiprop_insert_phi (basic_block bb, gphi *phi, gimple *use_stmt, } gphi *vphi = get_virtual_phi (bb); + tree use_vuse = gimple_vuse (use_stmt); + gimple *def_stmt = SSA_NAME_DEF_STMT (use_vuse); + /* Skip over clobbers in the same bb as the use + as they don't interfer with loads. */ + while (!SSA_NAME_IS_DEFAULT_DEF (use_vuse) + && gimple_clobber_p (def_stmt) + && gimple_bb (def_stmt) == bb) + { + use_vuse = gimple_vuse (def_stmt); + def_stmt = SSA_NAME_DEF_STMT (use_vuse); + } + /* If there is a vphi, then the def statement of the + vuse has to be a phi. */ + gcc_assert (!vphi || is_a<gphi *>(def_stmt)); /* Add PHI arguments for each edge inserting loads of the addressable operands. */ @@ -204,7 +218,7 @@ phiprop_insert_phi (basic_block bb, gphi *phi, gimple *use_stmt, if (vphi) vuse = PHI_ARG_DEF_FROM_EDGE (vphi, e); else - vuse = gimple_vuse (use_stmt); + vuse = use_vuse; } else /* For the aggregate copy case updating virtual operands @@ -377,6 +391,15 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn, def is an edge-inserted one we know it dominates us. */ vuse = gimple_vuse (use_stmt); def_stmt = SSA_NAME_DEF_STMT (vuse); + /* Skip over clobbers in the same bb as the use + as they don't interfer with loads. */ + while (!SSA_NAME_IS_DEFAULT_DEF (vuse) + && gimple_clobber_p (def_stmt) + && gimple_bb (def_stmt) == bb) + { + vuse = gimple_vuse (def_stmt); + def_stmt = SSA_NAME_DEF_STMT (vuse); + } if (!SSA_NAME_IS_DEFAULT_DEF (vuse) && (gimple_bb (def_stmt) == bb || (gimple_bb (def_stmt) -- 2.43.0