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>
---
 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