Re: [PUSHED v4] phiopt: Add some TARGET_MEM_REF support to factoring of loads [PR100173]
Andrea Pinski <[email protected]> Tue, 4 Aug 2026 08:59:05 -0700
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CALvbMcB+HUxWcQnK1rwAZA9L6b=f4TuVGQsTDjU8y8WK0UXKcw@mail.gmail.com> |
On Tue, Aug 4, 2026 at 8:52=E2=80=AFAM Andrea Pinski <[email protected]> wrote: > > The testcase in factor_op_phi-load-target_mem-1.c at -O2 gets: > ``` > if (_4 > _6) > goto <bb 4>; [50.00%] > else > goto <bb 5>; [50.00%] > > <bb 4> [local count: 531502204]: > t_21 =3D MEM[(int *)c_19(D) + ivtmp.23_12 * 1]; > goto <bb 6>; [100.00%] > > <bb 5> [local count: 531502204]: > t_20 =3D MEM[(int *)c_19(D) + 8B + ivtmp.23_12 * 1]; > > <bb 6> [local count: 1063004408]: > # t_13 =3D PHI <t_21(4), t_20(5)> > # t1_14 =3D PHI <_4(4), _6(5)> > ``` > > But that MEM is a TARGET_MEM_REF which is not supported by > factor_out_conditional_load yet. This adds simple TARGET_MEM_REF > support by requiring the index/step and index2 to be all the same. > It even supports a mismatched TARGET_MEM_REF with a MEM_REF but > only if the TARGET_MEM_REF had an null index/step and index2. > > We now get a similar code generation for telecom/viterb00data_1 (EEMBC) > at -O2 as LLVM. > > Changes since v1: > * v2: Fix small issue checking of equality and nullptr of TARGET_MEM_REF > operands. > * v3: Fix operand_equal check. > * v4: Add safe_operand_equal. Also use TMR_* instead of TREE_OPERAND. > > Bootstrapped and tested on x86_64-linux-gnu. > Pushed as approved already. Note I have not pushed this yet as the current trunk bootstrap is broken (unrelated to this patch). > > PR tree-optmization/100173 > > gcc/ChangeLog: > > * fold-const.h (safe_operand_equal_p): New function. > * tree-ssa-phiopt.cc (factor_out_conditional_load): Add simple > support for TARGET_MEM_REF. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/factor_op_phi-load-target_mem-1.c: New test. > > Signed-off-by: Andrea Pinski <[email protected]> > --- > gcc/fold-const.h | 13 +++++++ > .../factor_op_phi-load-target_mem-1.c | 24 ++++++++++++ > gcc/tree-ssa-phiopt.cc | 38 +++++++++++++++++-- > 3 files changed, 72 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-load-targ= et_mem-1.c > > diff --git a/gcc/fold-const.h b/gcc/fold-const.h > index 25e1cbf911f..ab03bf0aa35 100644 > --- a/gcc/fold-const.h > +++ b/gcc/fold-const.h > @@ -301,4 +301,17 @@ private: > unsigned int flags); > }; > > +/* Like operand_equal_p but supports nullptrs which compare > + equals to each other but not to others. */ > + > +inline bool > +safe_operand_equal_p (const_tree op0, const_tree op1, unsigned int flags= =3D 0) > +{ > + if (op0 =3D=3D op1) > + return true; > + if (!op0 || !op1) > + return false; > + return operand_equal_p (op0, op1, flags); > +} > + > #endif // GCC_FOLD_CONST_H > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-load-target_mem-= 1.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-load-target_mem-1.c > new file mode 100644 > index 00000000000..2e2a9ad7834 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-load-target_mem-1.c > @@ -0,0 +1,24 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-phiopt4-details" } */ > +/* PR tree-optmization/100173 */ > +/* TARGET_MEM_REF was not being supported for load factoring. */ > + > +void f(int a, int *b, int *d, int *c) > +{ > + for(int i =3D 0; i < 1024; i++) > + { > + int t; > + int t1; > + if (b[i] > d[i]) { > + t1 =3D b[i]; > + t =3D c[i]; > + } > + else { > + t1 =3D d[i]; > + t =3D c[i+2]; > + } > + b[i] =3D t+t1; > + } > +} > + > +/* { dg-final { scan-tree-dump "changed to factor out load from COND_EXP= R" "phiopt4" } } */ > diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc > index d63a47cc615..e29289c59bb 100644 > --- a/gcc/tree-ssa-phiopt.cc > +++ b/gcc/tree-ssa-phiopt.cc > @@ -4174,12 +4174,39 @@ factor_out_conditional_load (edge e0, edge e1, ba= sic_block merge, gphi *phi, > > tree ref0 =3D gimple_assign_rhs1 (load0); > tree ref1 =3D gimple_assign_rhs1 (load1); > + tree index =3D nullptr; > + tree step =3D nullptr; > + tree index2 =3D nullptr; > > /* Both must be *P loads of a compatible value type. The > TBAA alias-ptr type carried by MEM_REF operand 1 need not match; it= is > merged the way get_alias_type_for_stmts does when the load is built= . */ > - if (TREE_CODE (ref0) !=3D MEM_REF || TREE_CODE (ref1) !=3D MEM_REF > - || !types_compatible_p (TREE_TYPE (ref0), TREE_TYPE (ref1))) > + if (TREE_CODE (ref0) !=3D MEM_REF) > + { > + if (TREE_CODE (ref0) !=3D TARGET_MEM_REF) > + return false; > + index =3D TMR_INDEX (ref0); > + step =3D TMR_STEP (ref0); > + index2 =3D TMR_INDEX2 (ref0); > + } > + if (TREE_CODE (ref1) =3D=3D MEM_REF) > + { > + if (index || step || index2) > + return false; > + } > + else > + { > + if (TREE_CODE (ref1) !=3D TARGET_MEM_REF) > + return false; > + if (!safe_operand_equal_p (index, TMR_INDEX (ref1))) > + return false; > + if (!safe_operand_equal_p (step, TMR_STEP (ref1))) > + return false; > + if (!safe_operand_equal_p (index2, TMR_INDEX2 (ref1))) > + return false; > + } > + > + if (!types_compatible_p (TREE_TYPE (ref0), TREE_TYPE (ref1))) > return false; > > /* The alignment of the two accesses need to be the same. */ > @@ -4303,7 +4330,12 @@ factor_out_conditional_load (edge e0, edge e1, bas= ic_block merge, gphi *phi, > > /* Build the combined load RES =3D *PTR, reusing the PHI result so any= range > info on it is preserved (as factor_out_conditional_operation does).= */ > - tree nref =3D build2 (MEM_REF, TREE_TYPE (ref0), newptr, newindex); > + tree nref; > + if (index || step || index2) > + nref =3D build5 (TARGET_MEM_REF, TREE_TYPE (ref0), newptr, > + newindex, index, step, index2); > + else > + nref =3D build2 (MEM_REF, TREE_TYPE (ref0), newptr, newindex); > MR_DEPENDENCE_CLIQUE (nref) =3D clique; > MR_DEPENDENCE_BASE (nref) =3D base; > tree res =3D gimple_phi_result (phi); > -- > 2.43.0 >