[v2,2/2] strlen: call handle_builtin_strlen() from fold_strstr_to_strncmp()

Message ID 20230904205814.222166-2-someguy@effective-light.com
State Accepted
Headers
Series [v2,1/2] strlen: fold strstr() even if the length isn't previously known [PR96601] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Hamza Mahfooz Sept. 4, 2023, 8:58 p.m. UTC
  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 <someguy@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(-)
  

Patch

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 ();