Currently, we are not saving the strlen() call we inserted for possible
future common subexpression elimination. Also, it's possible that we can
further fold that strlen() call. So, refactor handle_builtin_strlen()
so that it can be called from fold_strstr_to_strncmp().

gcc/ChangeLog:

        * tree-ssa-strlen.cc (strlen_pass::handle_builtin_strlen):
        Remove from class and mark as static.
        (handle_builtin_strlen): Add parameter
        "gimple_stmt_iterator gsi" and replace references of m_gsi
        with gsi.
        (fold_strstr_to_strncmp): Call handle_builtin_strlen().
        (strlen_pass::check_and_optimize_call): Add m_gsi to the
        handle_builtin_strlen() call.

gcc/testsuite/ChangeLog:

        * gcc.dg/strlenopt-30.c: Add a test.

Signed-off-by: Hamza Mahfooz <some...@effective-light.com>
---
v2: bump up the number of strncmp()s from 6 to 7 in strlenopt-30.c
---
 gcc/testsuite/gcc.dg/strlenopt-30.c |  9 ++++++++-
 gcc/tree-ssa-strlen.cc              | 23 ++++++++++++-----------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/strlenopt-30.c 
b/gcc/testsuite/gcc.dg/strlenopt-30.c
index 1ee814048c1..d89fe83ca98 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-30.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-30.c
@@ -44,6 +44,12 @@ _Bool f6(char *s, char *t)
   return __builtin_strstr (s, t) == s;
 }
 
+__attribute__((no_icf))
+_Bool f6plus(char *s, char *t)
+{
+  return __builtin_strstr (s, t) == s && __builtin_strlen(t) > 10;
+}
+
 /* Do not perform transform in this case, since
    t1 doesn't have single use.  */
 
@@ -57,4 +63,5 @@ _Bool f7(char *s)
   return (t1 == s);
 }
 
-/* { dg-final { scan-tree-dump-times "__builtin_strncmp" 6 "strlen1" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_strlen" 2 "strlen1" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_strncmp" 7 "strlen1" } } */
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index b0ebbb0db62..8ec6ddbc7c0 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -252,7 +252,6 @@ public:
   bool handle_assign (tree lhs, bool *zero_write);
   bool handle_store (bool *zero_write);
   void handle_pointer_plus ();
-  void handle_builtin_strlen ();
   void handle_builtin_strchr ();
   void handle_builtin_strcpy (built_in_function);
   void handle_integral_assign (bool *cleanup_eh);
@@ -2211,10 +2210,10 @@ strlen_pass::maybe_warn_overflow (gimple *stmt, bool 
call_lhs,
    the strlen call with the known value, otherwise remember that strlen
    of the argument is stored in the lhs SSA_NAME.  */
 
-void
-strlen_pass::handle_builtin_strlen ()
+static void
+handle_builtin_strlen (gimple_stmt_iterator gsi)
 {
-  gimple *stmt = gsi_stmt (m_gsi);
+  gimple *stmt = gsi_stmt (gsi);
   tree lhs = gimple_call_lhs (stmt);
 
   if (lhs == NULL_TREE)
@@ -2268,8 +2267,8 @@ strlen_pass::handle_builtin_strlen ()
          if (bound)
            rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
 
-         gimplify_and_update_call_from_tree (&m_gsi, rhs);
-         stmt = gsi_stmt (m_gsi);
+         gimplify_and_update_call_from_tree (&gsi, rhs);
+         stmt = gsi_stmt (gsi);
          update_stmt (stmt);
          if (dump_file && (dump_flags & TDF_DETAILS) != 0)
            {
@@ -2367,8 +2366,8 @@ strlen_pass::handle_builtin_strlen ()
              }
            if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
              ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
-           gimplify_and_update_call_from_tree (&m_gsi, ret);
-           stmt = gsi_stmt (m_gsi);
+           gimplify_and_update_call_from_tree (&gsi, ret);
+           stmt = gsi_stmt (gsi);
            update_stmt (stmt);
            if (dump_file && (dump_flags & TDF_DETAILS) != 0)
              {
@@ -5272,8 +5271,9 @@ fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple 
*stmt)
        {
          tree arg1 = gimple_call_arg (call_stmt, 1);
          tree arg1_len = NULL_TREE;
-         int idx = get_stridx (arg1, call_stmt);
          gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
+again:
+         int idx = get_stridx (arg1, call_stmt);
 
          if (idx)
            {
@@ -5296,7 +5296,8 @@ fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple 
*stmt)
              gimple_call_set_lhs (strlen_call, strlen_lhs);
              gimple_set_vuse (strlen_call, gimple_vuse (call_stmt));
              gsi_insert_before (&gsi, strlen_call, GSI_SAME_STMT);
-             arg1_len = strlen_lhs;
+             handle_builtin_strlen (gsi_for_stmt (strlen_call));
+             goto again;
            }
          else if (!is_gimple_val (arg1_len))
            {
@@ -5393,7 +5394,7 @@ strlen_pass::check_and_optimize_call (bool *zero_write)
     {
     case BUILT_IN_STRLEN:
     case BUILT_IN_STRNLEN:
-      handle_builtin_strlen ();
+      handle_builtin_strlen (m_gsi);
       break;
     case BUILT_IN_STRCHR:
       handle_builtin_strchr ();
-- 
2.42.0

Reply via email to