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
>