On Tue, Sep 2, 2025 at 5:26 AM Richard Biener <[email protected]> wrote: > > On Sun, Aug 31, 2025 at 4:11 PM Andrew Pinski > <[email protected]> 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).
I was thinking about moving some of fab into optimize_widening_mul (which in itself is already misnamed) like the atomic builtins simplifications and the stdarg ones. > > So, unless memcmp_eq is unhandled elsewhere and thus we need to > do it late (-> ISEL), I'd rather do it in forwprop. memcmp_eq is pretty much not handled anywhere in the gimple. Now I think most of the places which do handle memcmp can/should handle memcmp_eq in a similar way. Now this is really an isel like what is done for popcount but that is done in optimize_widening_mul. Since both are similar in nature they should be in isel really since they explain how these 2 are used to expand and don't need anything more than that. I will file a few bugs about moving this stuff around and trying to remove some extra passes but I don't think I will get to them until next year. Thanks, Andrew Pinski > > 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 <[email protected]> > > --- > > 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 > >
