On Sun, Aug 31, 2025 at 4:11 PM Andrew Pinski
<andrew.pin...@oss.qualcomm.com> wrote:
>
> This is a small cleanup by moving the optimization of memcmp to
> memcmp_eq to fab from strlen pass. Since the copy of the other
> part of the memcmp strlen optimization to forwprop, this was the
> only thing left that strlen can do memcmp.
>
> Note this move will cause memcmp_eq to be used for -Os too.
>
> It also removes the optimization from strlen since both are now
> handled elsewhere.
>
> Bootstrapped and tested on x86_64-linux-gnu.

OK.

Note I don't like fab much, at least the parts that are not obviously
instruction selection.  Most of it should be part of forwprop or ISEL
or a pre-expand "cleanup" (removal of __builtin_assume_aligned and friends).

So, unless memcmp_eq is unhandled elsewhere and thus we need to
do it late (-> ISEL), I'd rather do it in forwprop.

Richard.

> gcc/ChangeLog:
>
>         * tree-ssa-ccp.cc (optimize_memcmp_eq): New function.
>         (pass_fold_builtins::execute): Call optimize_memcmp_eq
>         for memcmp.
>         * tree-ssa-strlen.cc (strlen_pass::handle_builtin_memcmp): Remove.
>         (strlen_pass::check_and_optimize_call): Don't call 
> handle_builtin_memcmp.
>
> Signed-off-by: Andrew Pinski <andrew.pin...@oss.qualcomm.com>
> ---
>  gcc/tree-ssa-ccp.cc    | 35 +++++++++++++++++++++++
>  gcc/tree-ssa-strlen.cc | 63 ------------------------------------------
>  2 files changed, 35 insertions(+), 63 deletions(-)
>
> diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
> index f33cc042e9f..f16b37f193e 100644
> --- a/gcc/tree-ssa-ccp.cc
> +++ b/gcc/tree-ssa-ccp.cc
> @@ -155,6 +155,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "ipa-prop.h"
>  #include "internal-fn.h"
>  #include "gimple-range.h"
> +#include "tree-ssa-strlen.h"
>
>  /* Possible lattice values.  */
>  typedef enum
> @@ -4221,6 +4222,36 @@ public:
>
>  }; // class pass_fold_builtins
>
> +/* Optimize memcmp STMT into memcmp_eq if it is only used with
> +   `== 0` or `!= 0`. */
> +
> +static void
> +optimize_memcmp_eq (gcall *stmt)
> +{
> +  /* Make sure memcmp arguments are the correct type.  */
> +  if (gimple_call_num_args (stmt) != 3)
> +    return;
> +  tree arg1 = gimple_call_arg (stmt, 0);
> +  tree arg2 = gimple_call_arg (stmt, 1);
> +  tree len = gimple_call_arg (stmt, 2);
> +
> +  if (!POINTER_TYPE_P (TREE_TYPE (arg1)))
> +    return;
> +  if (!POINTER_TYPE_P (TREE_TYPE (arg2)))
> +    return;
> +  if (!INTEGRAL_TYPE_P (TREE_TYPE (len)))
> +    return;
> +  /* The return value of the memcmp has to be used
> +     equality comparison to zero. */
> +  tree res = gimple_call_lhs (stmt);
> +
> +  if (!res || !use_in_zero_equality (res))
> +    return;
> +
> +  gimple_call_set_fndecl (stmt, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
> +  update_stmt (stmt);
> +}
> +
>  unsigned int
>  pass_fold_builtins::execute (function *fun)
>  {
> @@ -4285,6 +4316,10 @@ pass_fold_builtins::execute (function *fun)
>                   gsi_next (&i);
>                   continue;
>
> +               case BUILT_IN_MEMCMP:
> +                 optimize_memcmp_eq (as_a<gcall*>(stmt));
> +                 break;
> +
>                 case BUILT_IN_UNREACHABLE:
>                   if (optimize_unreachable (i))
>                     cfg_changed = true;
> diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
> index c4d64132e53..ade8c7dcadd 100644
> --- a/gcc/tree-ssa-strlen.cc
> +++ b/gcc/tree-ssa-strlen.cc
> @@ -3971,65 +3971,6 @@ use_in_zero_equality (tree res, bool exclusive)
>    return first_use;
>  }
>
> -/* Handle a call to memcmp.  We try to handle small comparisons by
> -   converting them to load and compare, and replacing the call to memcmp
> -   with a __builtin_memcmp_eq call where possible.
> -   return true when call is transformed, return false otherwise.  */
> -
> -bool
> -strlen_pass::handle_builtin_memcmp ()
> -{
> -  gcall *stmt = as_a <gcall *> (gsi_stmt (m_gsi));
> -  tree res = gimple_call_lhs (stmt);
> -
> -  if (!res || !use_in_zero_equality (res))
> -    return false;
> -
> -  tree arg1 = gimple_call_arg (stmt, 0);
> -  tree arg2 = gimple_call_arg (stmt, 1);
> -  tree len = gimple_call_arg (stmt, 2);
> -  unsigned HOST_WIDE_INT leni;
> -
> -  if (tree_fits_uhwi_p (len)
> -      && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
> -      && pow2p_hwi (leni))
> -    {
> -      leni *= CHAR_TYPE_SIZE;
> -      unsigned align1 = get_pointer_alignment (arg1);
> -      unsigned align2 = get_pointer_alignment (arg2);
> -      unsigned align = MIN (align1, align2);
> -      scalar_int_mode mode;
> -      if (int_mode_for_size (leni, 1).exists (&mode)
> -         && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
> -       {
> -         location_t loc = gimple_location (stmt);
> -         tree type, off;
> -         type = build_nonstandard_integer_type (leni, 1);
> -         gcc_assert (known_eq (GET_MODE_BITSIZE (TYPE_MODE (type)), leni));
> -         tree ptrtype = build_pointer_type_for_mode (char_type_node,
> -                                                     ptr_mode, true);
> -         off = build_int_cst (ptrtype, 0);
> -         arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
> -         arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
> -         tree tem1 = fold_const_aggregate_ref (arg1);
> -         if (tem1)
> -           arg1 = tem1;
> -         tree tem2 = fold_const_aggregate_ref (arg2);
> -         if (tem2)
> -           arg2 = tem2;
> -         res = fold_convert_loc (loc, TREE_TYPE (res),
> -                                 fold_build2_loc (loc, NE_EXPR,
> -                                                  boolean_type_node,
> -                                                  arg1, arg2));
> -         gimplify_and_update_call_from_tree (&m_gsi, res);
> -         return true;
> -       }
> -    }
> -
> -  gimple_call_set_fndecl (stmt, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
> -  return true;
> -}
> -
>  /* Given strinfo IDX for ARG, sets LENRNG[] to the range of lengths
>     of the string(s) referenced by ARG if it can be determined.
>     If the length cannot be determined, sets *SIZE to the size of
> @@ -5520,10 +5461,6 @@ strlen_pass::check_and_optimize_call (bool *zero_write)
>        if (handle_builtin_memset (zero_write))
>         return false;
>        break;
> -    case BUILT_IN_MEMCMP:
> -      if (handle_builtin_memcmp ())
> -       return false;
> -      break;
>      case BUILT_IN_STRCMP:
>      case BUILT_IN_STRNCMP:
>        if (handle_builtin_string_cmp ())
> --
> 2.43.0
>

Reply via email to