public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-455] PR tree-optimization/83907: Improved memset handling in strlen pass.
@ 2022-05-13 21:21 Roger Sayle
  0 siblings, 0 replies; only message in thread
From: Roger Sayle @ 2022-05-13 21:21 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1fe04c497d5a16baee6af48a0b08ca99b75724e4

commit r13-455-g1fe04c497d5a16baee6af48a0b08ca99b75724e4
Author: Roger Sayle <roger@nextmovesoftware.com>
Date:   Fri May 13 22:20:16 2022 +0100

    PR tree-optimization/83907: Improved memset handling in strlen pass.
    
    This patch implements the missed optimization enhancement PR 83907,
    by handling memset with a constant byte value in tree-ssa's strlen
    optimization pass.  Effectively, this treats memset(dst,'x',3) as
    it would memcpy(dst,"xxx",3).
    
    This patch also includes a tweak to handle_store to address another
    missed optimization observed in the related test case pr83907-2.c.
    The consecutive byte stores to memory get coalesced into a vector
    write of a vector const, but unfortunately tree-ssa-strlen's
    handle_store didn't previously handle the (unusual) case where the
    stored "string" starts with a zero byte but also contains non-zero
    bytes.
    
    2022-05-13  Roger Sayle  <roger@nextmovesoftware.com>
    
    gcc/ChangeLog
            PR tree-optimization/83907
            * tree-ssa-strlen.cc (handle_builtin_memset): Record a strinfo
            for memset with an constant char value.
            (handle_store): Improved handling of stores with a first byte
            of zero, but not storing_all_zeros_p.
    
    gcc/testsuite/ChangeLog
            PR tree-optimization/83907
            * gcc.dg/tree-ssa/pr83907-1.c: New test case.
            * gcc.dg/tree-ssa/pr83907-2.c: New test case.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/pr83907-1.c | 13 +++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr83907-2.c | 14 +++++++++
 gcc/tree-ssa-strlen.cc                    | 48 +++++++++++++++++++++++++++----
 3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr83907-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr83907-1.c
new file mode 100644
index 00000000000..2a6f4f56903
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr83907-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+extern char str[];
+
+unsigned int foo()
+{
+  __builtin_memset(str,'x',5);
+  str[5] = 0;
+  return __builtin_strlen (str);
+}
+
+/* { dg-final { scan-tree-dump-not "strlen" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr83907-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr83907-2.c
new file mode 100644
index 00000000000..cc27504fe86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr83907-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+extern char str[];
+
+unsigned int foo()
+{
+  __builtin_memset(str,'x',5);
+  str[5] = 0;
+  str[6] = 'z';
+  return __builtin_strlen (str);
+}
+
+/* { dg-final { scan-tree-dump-not "strlen" "optimized" } } */
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index bb7fe0853ef..1d4c0f78fbf 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -3805,9 +3805,44 @@ strlen_pass::handle_builtin_memset (bool *zero_write)
 {
   gimple *memset_stmt = gsi_stmt (m_gsi);
   tree ptr = gimple_call_arg (memset_stmt, 0);
+  tree memset_val = gimple_call_arg (memset_stmt, 1);
+  tree memset_size = gimple_call_arg (memset_stmt, 2);
+
   /* Set to the non-constant offset added to PTR.  */
   wide_int offrng[2];
   int idx1 = get_stridx (ptr, memset_stmt, offrng, ptr_qry.rvals);
+  if (idx1 == 0
+      && TREE_CODE (memset_val) == INTEGER_CST
+      && ((TREE_CODE (memset_size) == INTEGER_CST
+	   && !integer_zerop (memset_size))
+	  || TREE_CODE (memset_size) == SSA_NAME))
+    {
+      unsigned HOST_WIDE_INT mask = (HOST_WIDE_INT_1U << CHAR_TYPE_SIZE) - 1;
+      bool full_string_p = (wi::to_wide (memset_val) & mask) == 0;
+
+      /* We only handle symbolic lengths when writing non-zero values.  */
+      if (full_string_p && TREE_CODE (memset_size) != INTEGER_CST)
+	return false;
+
+      idx1 = new_stridx (ptr);
+      if (idx1 == 0)
+	return false;
+      tree newlen;
+      if (full_string_p)
+	newlen = build_int_cst (size_type_node, 0);
+      else if (TREE_CODE (memset_size) == INTEGER_CST)
+	newlen = fold_convert (size_type_node, memset_size);
+      else
+	newlen = memset_size;
+
+      strinfo *dsi = new_strinfo (ptr, idx1, newlen, full_string_p);
+      set_strinfo (idx1, dsi);
+      find_equal_ptrs (ptr, idx1);
+      dsi->dont_invalidate = true;
+      dsi->writable = true;
+      return false;
+    }
+
   if (idx1 <= 0)
     return false;
   strinfo *si1 = get_strinfo (idx1);
@@ -3820,7 +3855,6 @@ strlen_pass::handle_builtin_memset (bool *zero_write)
   if (!valid_builtin_call (alloc_stmt))
     return false;
   tree alloc_size = gimple_call_arg (alloc_stmt, 0);
-  tree memset_size = gimple_call_arg (memset_stmt, 2);
 
   /* Check for overflow.  */
   maybe_warn_overflow (memset_stmt, false, memset_size, NULL, false, true);
@@ -3836,7 +3870,7 @@ strlen_pass::handle_builtin_memset (bool *zero_write)
     return false;
 
   /* Bail when the call writes a non-zero value.  */
-  if (!integer_zerop (gimple_call_arg (memset_stmt, 1)))
+  if (!integer_zerop (memset_val))
     return false;
 
   /* Let the caller know the memset call cleared the destination.  */
@@ -5089,8 +5123,9 @@ strlen_pass::handle_store (bool *zero_write)
 	  return false;
 	}
 
-      if (storing_all_zeros_p
-	  || storing_nonzero_p
+      if (storing_nonzero_p
+	  || storing_all_zeros_p
+	  || (full_string_p && lenrange[1] == 0)
 	  || (offset != 0 && store_before_nul[1] > 0))
 	{
 	  /* When STORING_NONZERO_P, we know that the string will start
@@ -5100,8 +5135,9 @@ strlen_pass::handle_store (bool *zero_write)
 	     of leading non-zero characters and set si->NONZERO_CHARS to
 	     the result instead.
 
-	     When STORING_ALL_ZEROS_P, we know that the string is now
-	     OFFSET characters long.
+	     When STORING_ALL_ZEROS_P, or the first byte written is zero,
+	     i.e. FULL_STRING_P && LENRANGE[1] == 0, we know that the
+	     string is now OFFSET characters long.
 
 	     Otherwise, we're storing an unknown value at offset OFFSET,
 	     so need to clip the nonzero_chars to OFFSET.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-13 21:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-13 21:21 [gcc r13-455] PR tree-optimization/83907: Improved memset handling in strlen pass Roger Sayle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).