https://gcc.gnu.org/g:97e77f567c2b21799010fe34e9a05f078abd5b55

commit r16-3532-g97e77f567c2b21799010fe34e9a05f078abd5b55
Author: Andrew Pinski <andrew.pin...@oss.qualcomm.com>
Date:   Sat Aug 30 18:52:09 2025 -0700

    Move the folding of memcmpy to memcmpy_eq to fold all builtins
    
    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.
    
    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>

Diff:
---
 gcc/tree-ssa-ccp.cc    | 35 +++++++++++++++++++++++++
 gcc/tree-ssa-strlen.cc | 71 --------------------------------------------------
 2 files changed, 35 insertions(+), 71 deletions(-)

diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index f33cc042e9fb..f16b37f193e2 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 3cef33bf5b07..ade8c7dcadd4 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -3971,73 +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);
-
-         /* Create unaligned types if needed. */
-         tree type1 = type, type2 = type;
-         if (TYPE_ALIGN (type1) > align1)
-           type1 = build_aligned_type (type1, align1);
-         if (TYPE_ALIGN (type2) > align2)
-           type2 = build_aligned_type (type2, align2);
-
-         arg1 = build2_loc (loc, MEM_REF, type1, arg1, off);
-         arg2 = build2_loc (loc, MEM_REF, type2, 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
@@ -5528,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 ())

Reply via email to