public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Andrew MacLeod <amacleod@redhat.com>, Jakub Jelinek <jakub@redhat.com>
Cc: Martin Sebor <msebor@redhat.com>,
	GCC patches <gcc-patches@gcc.gnu.org>,
	Jeff Law <jeffreyalaw@gmail.com>
Subject: Re: [PATCH] Convert strlen pass from evrp to ranger.
Date: Fri, 15 Oct 2021 12:39:46 +0200	[thread overview]
Message-ID: <d12640dc-3bb1-4d7d-ecd8-557beed01fe5@redhat.com> (raw)
In-Reply-To: <a6b5f759-8e4e-8bf6-01a9-fbb4bdfde8ad@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2202 bytes --]



On 10/15/21 2:47 AM, Andrew MacLeod wrote:
> On 10/14/21 6:07 PM, Martin Sebor via Gcc-patches wrote:
>> On 10/9/21 12:47 PM, Aldy Hernandez via Gcc-patches wrote:
>>> We seem to be passing a lot of context around in the strlen code.  I
>>> certainly don't want to contribute to more.
>>>
>>> Most of the handle_* functions are passing the gsi as well as either
>>> ptr_qry or rvals.  That looks a bit messy.  May I suggest putting all
>>> of that in the strlen pass object (well, the dom walker object, but we
>>> can rename it to be less dom centric)?
>>>
>>> Something like the attached (untested) patch could be the basis for
>>> further cleanups.
>>>
>>> Jakub, would this line of work interest you?
>>
>> You didn't ask me but since no one spoke up against it let me add
>> some encouragement: this is exactly what I was envisioning and in
>> line with other such modernization we have been doing elsewhere.
>> Could you please submit it for review?
>>
>> Martin
> 
> I'm willing to bet he didn't submit it for review because he doesn't 
> have time this release to polish and track it...  (I think the threader 
> has been quite consuming).  Rather, it was offered as a starting point 
> for someone else who might be interested in continuing to pursue this 
> work...  *everyone* is interested in cleanup work others do :-)

Exactly.  There's a lot of work that could be done in this area, and I'm 
trying to avoid the situation with the threaders where what started as 
refactoring ended up with me basically owning them ;-).

That being said, I there are enough cleanups that are useful on their 
own.  I've removed all the passing around of GSIs, as well as ptr_qry, 
with the exception of anything dealing with the sprintf pass, since it 
has a slightly different interface.

This is patch 0001, which I'm formally submitting for inclusion.  No 
functional changes with this patch.  OK for trunk?

Also, I am PINGing patch 0002, which is the strlen pass conversion to 
the ranger.  As mentioned, this is just a change from an evrp client to 
a ranger client.  The APIs are exactly the same, and besides, the evrp 
analyzer is deprecated and slated for removal.  OK for trunk?

Aldy

[-- Attachment #2: 0001-Convert-strlen-pass-from-evrp-to-ranger.patch --]
[-- Type: text/x-patch, Size: 24287 bytes --]

From 152bc3a1dad9a960b7c0c53c65d6690532d9da5a Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Fri, 8 Oct 2021 15:54:23 +0200
Subject: [PATCH] Convert strlen pass from evrp to ranger.

The following patch converts the strlen pass from evrp to ranger,
leaving DOM as the last remaining user.

No additional cleanups have been done.  For example, the strlen pass
still has uses of VR_ANTI_RANGE, and the sprintf still passes around
pairs of integers instead of using a proper range.  Fixing this
could further improve these passes.

Basically the entire patch is just adjusting the calls to range_of_expr
to include context.  The previous context of si->stmt was mostly
empty, so not really useful ;-).

With ranger we are now able to remove the range calculation from
before_dom_children entirely.  Just working with the ranger on-demand
catches all the strlen and sprintf testcases with the exception of
builtin-sprintf-warn-22.c which is due to a limitation of the sprintf
code.  I have XFAILed the test and documented what the problem is.

On a positive note, these changes found two possible sprintf overflow
bugs in the C++ and Fortran front-ends which I have fixed below.

Tested on x86-64 Linux.

gcc/ChangeLog:

	* tree-ssa-strlen.c (compare_nonzero_chars): Pass statement
	context to ranger.
	(get_addr_stridx): Same.
	(get_stridx): Same.
	(get_range_strlen_dynamic): Same.
	(handle_builtin_strlen): Same.
	(handle_builtin_strchr): Same.
	(handle_builtin_strcpy): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat):
	(handle_builtin_memcpy): Same.
	(handle_builtin_strcat): Same.
	(handle_alloc_call): Same.
	(handle_builtin_memset): Same.
	(handle_builtin_string_cmp): Same.
	(handle_pointer_plus): Same.
	(count_nonzero_bytes_addr): Same.
	(count_nonzero_bytes): Same.
	(handle_store): Same.
	(fold_strstr_to_strncmp): Same.
	(handle_integral_assign): Same.
	(check_and_optimize_stmt): Same.
	(class strlen_dom_walker): Replace evrp with ranger.
	(strlen_dom_walker::before_dom_children): Remove evrp.
	(strlen_dom_walker::after_dom_children): Remove evrp.
	* gimple-ssa-warn-access.cc (maybe_check_access_sizes):
	Restrict sprintf output.

gcc/cp/ChangeLog:

	* ptree.c (cxx_print_xnode): Add more space to pfx array.

gcc/fortran/ChangeLog:

	* misc.c (gfc_dummy_typename): Make sure ts->kind is
	non-negative.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/builtin-sprintf-warn-22.c: XFAIL.
---
 gcc/cp/ptree.c                                |   2 +-
 gcc/fortran/misc.c                            |   2 +-
 gcc/gimple-ssa-warn-access.cc                 |   2 +-
 .../gcc.dg/tree-ssa/builtin-sprintf-warn-22.c |  13 +-
 gcc/tree-ssa-strlen.c                         | 145 ++++++++++--------
 5 files changed, 92 insertions(+), 72 deletions(-)

diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 1dcd764af01..ca7884db39b 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -292,7 +292,7 @@ cxx_print_xnode (FILE *file, tree node, int indent)
 	for (unsigned ix = 0; ix != len; ix++)
 	  {
 	    binding_cluster *cluster = &BINDING_VECTOR_CLUSTER (node, ix);
-	    char pfx[24];
+	    char pfx[32];
 	    for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
 	      if (cluster->indices[jx].span)
 		{
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index 3d449ae17fe..c1520307c90 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -284,7 +284,7 @@ gfc_dummy_typename (gfc_typespec *ts)
 	{
 	  if (ts->kind == gfc_default_character_kind)
 	    sprintf(buffer, "CHARACTER(*)");
-	  else if (ts->kind < 10)
+	  else if (ts->kind >= 0 && ts->kind < 10)
 	    sprintf(buffer, "CHARACTER(*,%d)", ts->kind);
 	  else
 	    sprintf(buffer, "CHARACTER(*,?)");
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 00c3ea0f505..850c1d2ded2 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2913,7 +2913,7 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
 	      char *s1 = print_generic_expr_to_str (sizrng[1]);
 	      gcc_checking_assert (strlen (s0) + strlen (s1)
 				   < sizeof sizstr - 4);
-	      sprintf (sizstr, "[%s, %s]", s0, s1);
+	      sprintf (sizstr, "[%.37s, %.37s]", s0, s1);
 	      free (s1);
 	    }
 	  free (s0);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c
index 685a4fd8c89..82eb5851c59 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c
@@ -18,7 +18,18 @@ void g (char *s1, char *s2)
   if (n + d + 1 >= 1025)
     return;
 
-  sprintf (b, "%s.%s", s1, s2);     // { dg-bogus "\\\[-Wformat-overflow" }
+  /* Ranger can find ranges here:
+     [1] n_6: size_t [0, 1023]
+     [2] d_8: size_t [0, 1023]
+
+     Whereas evrp can't really:
+     [1] n_6: size_t [0, 9223372036854775805]
+     [2] d_8: size_t [0, 9223372036854775805]
+
+     This is causing the sprintf warning pass to issue a false
+     positive here.  */
+
+  sprintf (b, "%s.%s", s1, s2);     // { dg-bogus "\\\[-Wformat-overflow" "" { xfail *-*-* } }
 
   f (b);
 }
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 7c568a42d49..df0c2d5ee7a 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 #include "vr-values.h"
-#include "gimple-ssa-evrp-analyze.h"
+#include "gimple-range.h"
 #include "tree-ssa.h"
 
 /* A vector indexed by SSA_NAME_VERSION.  0 means unknown, positive value
@@ -256,7 +256,8 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
    Uses RVALS to determine length range.  */
 
 static int
-compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off,
+compare_nonzero_chars (strinfo *si, gimple *stmt,
+		       unsigned HOST_WIDE_INT off,
 		       range_query *rvals)
 {
   if (!si->nonzero_chars)
@@ -269,7 +270,7 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off,
     return -1;
 
   value_range vr;
-  if (!rvals->range_of_expr (vr, si->nonzero_chars, si->stmt))
+  if (!rvals->range_of_expr (vr, si->nonzero_chars, stmt))
     return -1;
   value_range_kind rng = vr.kind ();
   if (rng != VR_RANGE)
@@ -324,7 +325,8 @@ get_next_strinfo (strinfo *si)
    information.  */
 
 static int
-get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out,
+get_addr_stridx (tree exp, gimple *stmt,
+		 tree ptr, unsigned HOST_WIDE_INT *offset_out,
 		 range_query *rvals = NULL)
 {
   HOST_WIDE_INT off;
@@ -363,7 +365,7 @@ get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out,
       unsigned HOST_WIDE_INT rel_off
 	= (unsigned HOST_WIDE_INT) off - last->offset;
       strinfo *si = get_strinfo (last->idx);
-      if (si && compare_nonzero_chars (si, rel_off, rvals) >= 0)
+      if (si && compare_nonzero_chars (si, stmt, rel_off, rvals) >= 0)
 	{
 	  if (offset_out)
 	    {
@@ -385,7 +387,8 @@ get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out,
    When nonnull, uses RVALS to determine range information.  */
 
 static int
-get_stridx (tree exp, wide_int offrng[2] = NULL, range_query *rvals = NULL)
+get_stridx (tree exp, gimple *stmt,
+	    wide_int offrng[2] = NULL, range_query *rvals = NULL)
 {
   if (offrng)
     offrng[0] = offrng[1] = wi::zero (TYPE_PRECISION (ptrdiff_type_node));
@@ -522,7 +525,7 @@ get_stridx (tree exp, wide_int offrng[2] = NULL, range_query *rvals = NULL)
 
   if (TREE_CODE (exp) == ADDR_EXPR)
     {
-      int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
+      int idx = get_addr_stridx (TREE_OPERAND (exp, 0), stmt, exp, NULL);
       if (idx != 0)
 	return idx;
     }
@@ -1016,7 +1019,7 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
 			  c_strlen_data *pdata, bitmap *visited,
 			  range_query *rvals, unsigned *pssa_def_max)
 {
-  int idx = get_stridx (src);
+  int idx = get_stridx (src, stmt);
   if (!idx)
     {
       if (TREE_CODE (src) == SSA_NAME)
@@ -2124,7 +2127,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
   tree src = gimple_call_arg (stmt, 0);
   tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
 		? gimple_call_arg (stmt, 1) : NULL_TREE);
-  int idx = get_stridx (src);
+  int idx = get_stridx (src, stmt);
   if (idx || (bound && integer_zerop (bound)))
     {
       strinfo *si = NULL;
@@ -2304,7 +2307,7 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
   if (!check_nul_terminated_array (NULL_TREE, src))
     return;
 
-  int idx = get_stridx (src);
+  int idx = get_stridx (src, stmt);
   if (idx)
     {
       strinfo *si = NULL;
@@ -2411,12 +2414,12 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   src = gimple_call_arg (stmt, 1);
   dst = gimple_call_arg (stmt, 0);
   lhs = gimple_call_lhs (stmt);
-  idx = get_stridx (src);
+  idx = get_stridx (src, stmt);
   si = NULL;
   if (idx > 0)
     si = get_strinfo (idx);
 
-  didx = get_stridx (dst);
+  didx = get_stridx (dst, stmt);
   olddsi = NULL;
   oldlen = NULL_TREE;
   if (didx > 0)
@@ -2818,7 +2821,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
      when ssa_ver_to_stridx is empty.  That implies the caller isn't
      running under the control of this pass and ssa_ver_to_stridx hasn't
      been created yet.  */
-  int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
+  int sidx = ssa_ver_to_stridx.length () ? get_stridx (src, stmt) : 0;
   if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
     return false;
 
@@ -3092,7 +3095,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
      a lower bound).  */
   tree dstlenp1 = NULL_TREE, srclenp1 = NULL_TREE;;
 
-  int didx = get_stridx (dst);
+  int didx = get_stridx (dst, stmt);
   if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
     {
       /* Compute the size of the destination string including the nul
@@ -3118,7 +3121,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       dst = sidst->ptr;
     }
 
-  int sidx = get_stridx (src);
+  int sidx = get_stridx (src, stmt);
   strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
   if (sisrc)
     {
@@ -3228,7 +3231,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   tree src = gimple_call_arg (stmt, 1);
   tree dst = gimple_call_arg (stmt, 0);
 
-  int didx = get_stridx (dst);
+  int didx = get_stridx (dst, stmt);
   strinfo *olddsi = NULL;
   if (didx > 0)
     olddsi = get_strinfo (didx);
@@ -3242,7 +3245,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       adjust_last_stmt (olddsi, stmt, false, ptr_qry);
     }
 
-  int idx = get_stridx (src);
+  int idx = get_stridx (src, stmt);
   if (idx == 0)
     return;
 
@@ -3418,7 +3421,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 
   tree lhs = gimple_call_lhs (stmt);
 
-  didx = get_stridx (dst);
+  didx = get_stridx (dst, stmt);
   if (didx < 0)
     return;
 
@@ -3428,7 +3431,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 
   srclen = NULL_TREE;
   si = NULL;
-  idx = get_stridx (src);
+  idx = get_stridx (src, stmt);
   if (idx < 0)
     srclen = build_int_cst (size_type_node, ~idx);
   else if (idx > 0)
@@ -3650,7 +3653,7 @@ handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
   if (lhs == NULL_TREE)
     return;
 
-  gcc_assert (get_stridx (lhs) == 0);
+  gcc_assert (get_stridx (lhs, stmt) == 0);
   int idx = new_stridx (lhs);
   tree length = NULL_TREE;
   if (bcode == BUILT_IN_CALLOC)
@@ -3687,7 +3690,7 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
   tree ptr = gimple_call_arg (memset_stmt, 0);
   /* Set to the non-constant offset added to PTR.  */
   wide_int offrng[2];
-  int idx1 = get_stridx (ptr, offrng, ptr_qry.rvals);
+  int idx1 = get_stridx (ptr, memset_stmt, offrng, ptr_qry.rvals);
   if (idx1 <= 0)
     return false;
   strinfo *si1 = get_strinfo (idx1);
@@ -4178,8 +4181,8 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
 
   tree arg1 = gimple_call_arg (stmt, 0);
   tree arg2 = gimple_call_arg (stmt, 1);
-  int idx1 = get_stridx (arg1);
-  int idx2 = get_stridx (arg2);
+  int idx1 = get_stridx (arg1, stmt);
+  int idx2 = get_stridx (arg2, stmt);
 
   /* For strncmp set to the value of the third argument if known.  */
   HOST_WIDE_INT bound = -1;
@@ -4318,7 +4321,7 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
   tree lhs = gimple_assign_lhs (stmt), off;
-  int idx = get_stridx (gimple_assign_rhs1 (stmt));
+  int idx = get_stridx (gimple_assign_rhs1 (stmt), stmt);
   strinfo *si, *zsi;
 
   if (idx == 0)
@@ -4396,7 +4399,8 @@ nonzero_bytes_for_type (tree type, unsigned lenrange[3],
 }
 
 static bool
-count_nonzero_bytes_addr (tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+count_nonzero_bytes_addr (tree, gimple *stmt,
+			  unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
 			  unsigned [3], bool *, bool *, bool *,
 			  range_query *, ssa_name_limit_t &);
 
@@ -4416,7 +4420,8 @@ count_nonzero_bytes_addr (tree, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
    Returns true on success and false otherwise.  */
 
 static bool
-count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
+count_nonzero_bytes (tree exp, gimple *stmt,
+		     unsigned HOST_WIDE_INT offset,
 		     unsigned HOST_WIDE_INT nbytes,
 		     unsigned lenrange[3], bool *nulterm,
 		     bool *allnul, bool *allnonnul, range_query *rvals,
@@ -4435,7 +4440,8 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
 	     exact value is not known) recurse once to set the range
 	     for an arbitrary constant.  */
 	  exp = build_int_cst (type, 1);
-	  return count_nonzero_bytes (exp, offset, 1, lenrange,
+	  return count_nonzero_bytes (exp, stmt,
+				      offset, 1, lenrange,
 				      nulterm, allnul, allnonnul, rvals, snlim);
 	}
 
@@ -4462,7 +4468,8 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
 	  for (unsigned i = 0; i != n; i++)
 	    {
 	      tree def = gimple_phi_arg_def (stmt, i);
-	      if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm,
+	      if (!count_nonzero_bytes (def, stmt,
+					offset, nbytes, lenrange, nulterm,
 					allnul, allnonnul, rvals, snlim))
 		return false;
 	    }
@@ -4519,7 +4526,8 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
 	return false;
 
       /* Handle MEM_REF = SSA_NAME types of assignments.  */
-      return count_nonzero_bytes_addr (arg, offset, nbytes, lenrange, nulterm,
+      return count_nonzero_bytes_addr (arg, stmt,
+				       offset, nbytes, lenrange, nulterm,
 				       allnul, allnonnul, rvals, snlim);
     }
 
@@ -4631,13 +4639,14 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
    bytes that are pointed to by EXP, which should be a pointer.  */
 
 static bool
-count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
+count_nonzero_bytes_addr (tree exp, gimple *stmt,
+			  unsigned HOST_WIDE_INT offset,
 			  unsigned HOST_WIDE_INT nbytes,
 			  unsigned lenrange[3], bool *nulterm,
 			  bool *allnul, bool *allnonnul,
 			  range_query *rvals, ssa_name_limit_t &snlim)
 {
-  int idx = get_stridx (exp);
+  int idx = get_stridx (exp, stmt);
   if (idx > 0)
     {
       strinfo *si = get_strinfo (idx);
@@ -4653,7 +4662,7 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
 	       && TREE_CODE (si->nonzero_chars) == SSA_NAME)
 	{
 	  value_range vr;
-	  rvals->range_of_expr (vr, si->nonzero_chars, si->stmt);
+	  rvals->range_of_expr (vr, si->nonzero_chars, stmt);
 	  if (vr.kind () != VR_RANGE)
 	    return false;
 
@@ -4699,7 +4708,8 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
     }
 
   if (TREE_CODE (exp) == ADDR_EXPR)
-    return count_nonzero_bytes (TREE_OPERAND (exp, 0), offset, nbytes,
+    return count_nonzero_bytes (TREE_OPERAND (exp, 0), stmt,
+				offset, nbytes,
 				lenrange, nulterm, allnul, allnonnul, rvals,
 				snlim);
 
@@ -4719,7 +4729,8 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
 	  for (unsigned i = 0; i != n; i++)
 	    {
 	      tree def = gimple_phi_arg_def (stmt, i);
-	      if (!count_nonzero_bytes_addr (def, offset, nbytes, lenrange,
+	      if (!count_nonzero_bytes_addr (def, stmt,
+					     offset, nbytes, lenrange,
 					     nulterm, allnul, allnonnul, rvals,
 					     snlim))
 		return false;
@@ -4747,7 +4758,8 @@ count_nonzero_bytes_addr (tree exp, unsigned HOST_WIDE_INT offset,
    (the results of strlen).  */
 
 static bool
-count_nonzero_bytes (tree expr_or_type, unsigned lenrange[3], bool *nulterm,
+count_nonzero_bytes (tree expr_or_type, gimple *stmt,
+		     unsigned lenrange[3], bool *nulterm,
 		     bool *allnul, bool *allnonnul, range_query *rvals)
 {
   if (TYPE_P (expr_or_type))
@@ -4765,7 +4777,8 @@ count_nonzero_bytes (tree expr_or_type, unsigned lenrange[3], bool *nulterm,
 
   ssa_name_limit_t snlim;
   tree expr = expr_or_type;
-  return count_nonzero_bytes (expr, 0, 0, lenrange, nulterm, allnul, allnonnul,
+  return count_nonzero_bytes (expr, stmt,
+			      0, 0, lenrange, nulterm, allnul, allnonnul,
 			      rvals, snlim);
 }
 
@@ -4818,18 +4831,19 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	     least OFFSET nonzero characters.  This is trivially true if
 	     OFFSET is zero.  */
 	  offset = tree_to_uhwi (mem_offset);
-	  idx = get_stridx (TREE_OPERAND (lhs, 0));
+	  idx = get_stridx (TREE_OPERAND (lhs, 0), stmt);
 	  if (idx > 0)
 	    si = get_strinfo (idx);
 	  if (offset == 0)
 	    ssaname = TREE_OPERAND (lhs, 0);
-	  else if (si == NULL || compare_nonzero_chars (si, offset, rvals) < 0)
+	  else if (si == NULL
+		   || compare_nonzero_chars (si, stmt, offset, rvals) < 0)
 	    {
 	      *zero_write = rhs ? initializer_zerop (rhs) : false;
 
 	      bool dummy;
 	      unsigned lenrange[] = { UINT_MAX, 0, 0 };
-	      if (count_nonzero_bytes (rhs ? rhs : storetype, lenrange,
+	      if (count_nonzero_bytes (rhs ? rhs : storetype, stmt, lenrange,
 				       &dummy, &dummy, &dummy, rvals))
 		maybe_warn_overflow (stmt, true, lenrange[2], ptr_qry);
 
@@ -4839,7 +4853,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
     }
   else
     {
-      idx = get_addr_stridx (lhs, NULL_TREE, &offset, rvals);
+      idx = get_addr_stridx (lhs, stmt, NULL_TREE, &offset, rvals);
       if (idx > 0)
 	si = get_strinfo (idx);
     }
@@ -4862,7 +4876,8 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
   bool full_string_p;
 
   const bool ranges_valid
-    = count_nonzero_bytes (rhs ? rhs : storetype, lenrange, &full_string_p,
+    = count_nonzero_bytes (rhs ? rhs : storetype, stmt,
+			   lenrange, &full_string_p,
 			   &storing_all_zeros_p, &storing_all_nonzero_p,
 			   rvals);
 
@@ -4895,15 +4910,18 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	{
 	  /* The offset of the last stored byte.  */
 	  unsigned HOST_WIDE_INT endoff = offset + lenrange[2] - 1;
-	  store_before_nul[0] = compare_nonzero_chars (si, offset, rvals);
+	  store_before_nul[0]
+	    = compare_nonzero_chars (si, stmt, offset, rvals);
 	  if (endoff == offset)
 	    store_before_nul[1] = store_before_nul[0];
 	  else
-	    store_before_nul[1] = compare_nonzero_chars (si, endoff, rvals);
+	    store_before_nul[1]
+	      = compare_nonzero_chars (si, stmt, endoff, rvals);
 	}
       else
 	{
-	  store_before_nul[0] = compare_nonzero_chars (si, offset, rvals);
+	  store_before_nul[0]
+	    = compare_nonzero_chars (si, stmt, offset, rvals);
 	  store_before_nul[1] = store_before_nul[0];
 	  gcc_assert (offset == 0 || store_before_nul[0] >= 0);
 	}
@@ -5128,7 +5146,7 @@ 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);
+	  int idx = get_stridx (arg1, call_stmt);
 
 	  if (idx)
 	    {
@@ -5342,7 +5360,7 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
       tree rhs1 = gimple_assign_rhs1 (stmt);
       if (code == MEM_REF)
 	{
-	  idx = get_stridx (TREE_OPERAND (rhs1, 0));
+	  idx = get_stridx (TREE_OPERAND (rhs1, 0), stmt);
 	  if (idx > 0)
 	    {
 	      strinfo *si = get_strinfo (idx);
@@ -5359,7 +5377,7 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 	    }
 	}
       if (idx <= 0)
-	idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
+	idx = get_addr_stridx (rhs1, stmt, NULL_TREE, &coff);
       if (idx > 0)
 	{
 	  strinfo *si = get_strinfo (idx);
@@ -5421,7 +5439,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 	  unsigned lenrange[] = { UINT_MAX, 0, 0 };
 	  tree rhs = gimple_assign_rhs1 (stmt);
 	  const bool ranges_valid
-	    = count_nonzero_bytes (rhs, lenrange, &full_string_p,
+	    = count_nonzero_bytes (rhs, stmt,
+				   lenrange, &full_string_p,
 				   &storing_all_zeros_p, &storing_all_nonzero_p,
 				   rvals);
 	  if (ranges_valid)
@@ -5520,7 +5539,7 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 	      || (gimple_assign_cast_p (stmt)
 		  && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
 	    {
-	      int idx = get_stridx (gimple_assign_rhs1 (stmt));
+	      int idx = get_stridx (gimple_assign_rhs1 (stmt), stmt);
 	      ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
 	    }
 	  else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
@@ -5602,20 +5621,20 @@ class strlen_dom_walker : public dom_walker
 public:
   strlen_dom_walker (cdi_direction direction)
     : dom_walker (direction),
-    evrp (false),
-    ptr_qry (&evrp, &var_cache),
-    var_cache (),
-    m_cleanup_cfg (false)
-  { }
+      ptr_qry (&m_ranger, &var_cache),
+      var_cache (),
+      m_cleanup_cfg (false)
+  {
+  }
 
   ~strlen_dom_walker ();
 
   virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
-  /* EVRP analyzer used for printf argument range processing, and
+  /* Ranger used for printf argument range processing, and
      to track strlen results across integer variable assignments.  */
-  evrp_range_analyzer evrp;
+  gimple_ranger m_ranger;
 
   /* A pointer_query object and its cache to store information about
      pointers and their targets in.  */
@@ -5640,8 +5659,6 @@ strlen_dom_walker::~strlen_dom_walker ()
 edge
 strlen_dom_walker::before_dom_children (basic_block bb)
 {
-  evrp.enter (bb);
-
   basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
 
   if (dombb == NULL)
@@ -5698,12 +5715,12 @@ strlen_dom_walker::before_dom_children (basic_block bb)
       tree result = gimple_phi_result (phi);
       if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
 	{
-	  int idx = get_stridx (gimple_phi_arg_def (phi, 0));
+	  int idx = get_stridx (gimple_phi_arg_def (phi, 0), phi);
 	  if (idx != 0)
 	    {
 	      unsigned int i, n = gimple_phi_num_args (phi);
 	      for (i = 1; i < n; i++)
-		if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
+		if (idx != get_stridx (gimple_phi_arg_def (phi, i), phi))
 		  break;
 	      if (i == n)
 		ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
@@ -5716,12 +5733,6 @@ strlen_dom_walker::before_dom_children (basic_block bb)
   /* Attempt to optimize individual statements.  */
   for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
     {
-      gimple *stmt = gsi_stmt (gsi);
-
-      /* First record ranges generated by this statement so they
-	 can be used by printf argument processing.  */
-      evrp.record_ranges_from_stmt (stmt, false);
-
       /* Reset search depth preformance counter.  */
       ptr_qry.depth = 0;
 
@@ -5744,8 +5755,6 @@ strlen_dom_walker::before_dom_children (basic_block bb)
 void
 strlen_dom_walker::after_dom_children (basic_block bb)
 {
-  evrp.leave (bb);
-
   if (bb->aux)
     {
       stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
-- 
2.31.1


[-- Attachment #3: 0002-Strlen-pass-refactoring.patch --]
[-- Type: text/x-patch, Size: 44388 bytes --]

From a4edbe8ee9e2a8825b84eb0c3db73af78dd022fe Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Sat, 9 Oct 2021 19:26:32 +0200
Subject: [PATCH] Strlen pass refactoring.

This refactors the strlen pass to avoid passing around as much state.
It is meant to be a start.  There's still some more refactoring
that could be done, especially in cleaning up the interface between
the strlen internals and the sprintf pass.

Tested on x86-64 Linux.

gcc/ChangeLog:

	* tree-ssa-strlen.c (class strlen_pass): Rename from
	strlen_dom_walker.
	(handle_builtin_stxncpy_strncat): Move to strlen_pass.
	(handle_assign): Same.
	(adjust_last_stmt): Same.
	(maybe_warn_overflow): Same.
	(handle_builtin_strlen): Same.
	(handle_builtin_strchr): Same.
	(handle_builtin_strcpy): Same.
	(handle_builtin_strncat): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(handle_builtin_memcpy): Same.
	(handle_builtin_strcat): Same.
	(handle_alloc_call): Same.
	(handle_builtin_memset): Same.
	(handle_builtin_memcmp): Same.
	(get_len_or_size): Same.
	(strxcmp_eqz_result): Same.
	(handle_builtin_string_cmp): Same.
	(handle_pointer_plus): Same.
	(count_nonzero_bytes_addr): Same.
	(count_nonzero_bytes): Same.
	(handle_store): Same.
	(strlen_check_and_optimize_call): Same.
	(handle_integral_assign): Same.
	(check_and_optimize_stmt): Same.
	(printf_strlen_execute): Rename strlen_dom_walker to strlen_pass.
---
 gcc/tree-ssa-strlen.c | 483 ++++++++++++++++++++++--------------------
 1 file changed, 255 insertions(+), 228 deletions(-)

diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index df0c2d5ee7a..7109d8fb58a 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -193,9 +193,6 @@ struct laststmt_struct
 } laststmt;
 
 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
-static void handle_builtin_stxncpy_strncat (bool, gimple_stmt_iterator *);
-static bool handle_assign (gimple_stmt_iterator *, tree, bool *,
-			   pointer_query &);
 
 /* Sets MINMAX to either the constant value or the range VAL is in
    and returns either the constant value or VAL on success or null
@@ -232,6 +229,87 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
   return NULL_TREE;
 }
 
+class strlen_pass : public dom_walker
+{
+public:
+  strlen_pass (cdi_direction direction)
+    : dom_walker (direction),
+      ptr_qry (&m_ranger, &var_cache),
+      var_cache (),
+      m_cleanup_cfg (false)
+  {
+  }
+
+  ~strlen_pass ();
+
+  virtual edge before_dom_children (basic_block);
+  virtual void after_dom_children (basic_block);
+
+  bool check_and_optimize_stmt (bool *cleanup_eh);
+  bool check_and_optimize_call (bool *zero_write);
+  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);
+  void handle_builtin_stxncpy_strncat (bool append_p);
+  void handle_builtin_memcpy (built_in_function bcode);
+  void handle_builtin_strcat (built_in_function bcode);
+  void handle_builtin_strncat (built_in_function);
+  bool handle_builtin_memset (bool *zero_write);
+  bool handle_builtin_memcmp ();
+  bool handle_builtin_string_cmp ();
+  void handle_alloc_call (built_in_function);
+  void maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
+			    strinfo *si = NULL, bool plus_one = false,
+			    bool rawmem = false);
+  void maybe_warn_overflow (gimple *stmt, bool call_lhs,
+			    unsigned HOST_WIDE_INT len,
+			    strinfo *si = NULL,
+			    bool plus_one = false, bool rawmem = false);
+  void adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat);
+  tree strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1,
+			   tree arg2, int idx2,
+			   unsigned HOST_WIDE_INT bound,
+			   unsigned HOST_WIDE_INT len[2],
+			   unsigned HOST_WIDE_INT *psize);
+  bool count_nonzero_bytes (tree expr_or_type, gimple *stmt,
+			    unsigned lenrange[3], bool *nulterm,
+			    bool *allnul, bool *allnonnul);
+  bool count_nonzero_bytes (tree exp, gimple *stmt,
+			    unsigned HOST_WIDE_INT offset,
+			    unsigned HOST_WIDE_INT nbytes,
+			    unsigned lenrange[3], bool *nulterm,
+			    bool *allnul, bool *allnonnul,
+			    ssa_name_limit_t &snlim);
+  bool count_nonzero_bytes_addr (tree exp, gimple *stmt,
+				 unsigned HOST_WIDE_INT offset,
+				 unsigned HOST_WIDE_INT nbytes,
+				 unsigned lenrange[3], bool *nulterm,
+				 bool *allnul, bool *allnonnul,
+				 ssa_name_limit_t &snlim);
+  bool get_len_or_size (gimple *stmt, tree arg, int idx,
+			unsigned HOST_WIDE_INT lenrng[2],
+			unsigned HOST_WIDE_INT *size, bool *nulterm);
+
+  /* Ranger used for printf argument range processing, and
+     to track strlen results across integer variable assignments.  */
+  gimple_ranger m_ranger;
+
+  /* A pointer_query object and its cache to store information about
+     pointers and their targets in.  */
+  pointer_query ptr_qry;
+  pointer_query::cache_type var_cache;
+
+  gimple_stmt_iterator m_gsi;
+
+  /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
+     execute function.  */
+  bool m_cleanup_cfg;
+};
+
 /* Return:
 
    *  +1  if SI is known to start with more than OFF nonzero characters.
@@ -242,7 +320,7 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
 	  or the relationship between the number of leading nonzero
 	  characters in SI and OFF is unknown.  */
 
-static inline int
+static int
 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
 {
   if (si->nonzero_chars
@@ -1667,9 +1745,8 @@ valid_builtin_call (gimple *stmt)
    just memcpy (x, y, strlen (y)).  SI must be the zero length
    strinfo.  */
 
-static void
-adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat,
-		  pointer_query &ptr_qry)
+void
+strlen_pass::adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
 {
   tree vuse, callee, len;
   struct laststmt_struct last = laststmt;
@@ -1916,11 +1993,9 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
    RAWMEM may be set by memcpy and other raw memory functions
    to allow accesses across subobject boundaries.  */
 
-static void
-maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
-		     pointer_query &ptr_qry,
-		     strinfo *si = NULL, bool plus_one = false,
-		     bool rawmem = false)
+void
+strlen_pass::maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
+				  strinfo *si, bool plus_one, bool rawmem)
 {
   if (!len || warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
     return;
@@ -2100,23 +2175,23 @@ maybe_warn_overflow (gimple *stmt, bool call_lhs, tree len,
 
 /* Convenience wrapper for the above.  */
 
-static inline void
-maybe_warn_overflow (gimple *stmt, bool call_lhs, unsigned HOST_WIDE_INT len,
-		     pointer_query &ptr_qry, strinfo *si = NULL,
-		     bool plus_one = false, bool rawmem = false)
+void
+strlen_pass::maybe_warn_overflow (gimple *stmt, bool call_lhs,
+				  unsigned HOST_WIDE_INT len,
+				  strinfo *si, bool plus_one, bool rawmem)
 {
   tree tlen = build_int_cst (size_type_node, len);
-  maybe_warn_overflow (stmt, call_lhs, tlen, ptr_qry, si, plus_one, rawmem);
+  maybe_warn_overflow (stmt, call_lhs, tlen, si, plus_one, rawmem);
 }
 
 /* Handle a strlen call.  If strlen of the argument is known, replace
    the strlen call with the known value, otherwise remember that strlen
    of the argument is stored in the lhs SSA_NAME.  */
 
-static void
-handle_builtin_strlen (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strlen ()
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   tree lhs = gimple_call_lhs (stmt);
 
   if (lhs == NULL_TREE)
@@ -2170,8 +2245,8 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
 	  if (bound)
 	    rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
 
-	  gimplify_and_update_call_from_tree (gsi, rhs);
-	  stmt = gsi_stmt (*gsi);
+	  gimplify_and_update_call_from_tree (&m_gsi, rhs);
+	  stmt = gsi_stmt (m_gsi);
 	  update_stmt (stmt);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
@@ -2269,8 +2344,8 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
 	      }
 	    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 (gsi, ret);
-	    stmt = gsi_stmt (*gsi);
+	    gimplify_and_update_call_from_tree (&m_gsi, ret);
+	    stmt = gsi_stmt (m_gsi);
 	    update_stmt (stmt);
 	    if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	      {
@@ -2288,10 +2363,10 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
    the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
    that lhs of the call is endptr and strlen of the argument is endptr - x.  */
 
-static void
-handle_builtin_strchr (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strchr ()
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   tree lhs = gimple_call_lhs (stmt);
 
   if (lhs == NULL_TREE)
@@ -2347,8 +2422,8 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
 					      TREE_TYPE (rhs)))
 		rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
 	    }
-	  gimplify_and_update_call_from_tree (gsi, rhs);
-	  stmt = gsi_stmt (*gsi);
+	  gimplify_and_update_call_from_tree (&m_gsi, rhs);
+	  stmt = gsi_stmt (m_gsi);
 	  update_stmt (stmt);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
@@ -2400,14 +2475,13 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
    is the same after this call.  Furthermore, attempt to convert it to
    memcpy.  Uses RVALS to determine range information.  */
 
-static void
-handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
-		       pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_strcpy (built_in_function bcode)
 {
   int idx, didx;
   tree src, dst, srclen, len, lhs, type, fn, oldlen;
   bool success;
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   strinfo *si, *dsi, *olddsi, *zsi;
   location_t loc;
 
@@ -2428,7 +2502,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
     return;
 
   if (olddsi != NULL)
-    adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+    adjust_last_stmt (olddsi, stmt, false);
 
   srclen = NULL_TREE;
   if (si != NULL)
@@ -2436,10 +2510,10 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   else if (idx < 0)
     srclen = build_int_cst (size_type_node, ~idx);
 
-  maybe_warn_overflow (stmt, false, srclen, ptr_qry, olddsi, true);
+  maybe_warn_overflow (stmt, false, srclen, olddsi, true);
 
   if (olddsi != NULL)
-    adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+    adjust_last_stmt (olddsi, stmt, false);
 
   loc = gimple_location (stmt);
   if (srclen == NULL_TREE)
@@ -2630,7 +2704,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   if (fn == NULL_TREE)
     return;
 
-  len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
+  len = force_gimple_operand_gsi (&m_gsi, len, true, NULL_TREE, true,
 				  GSI_SAME_STMT);
   if (dump_file && (dump_flags & TDF_DETAILS) != 0)
     {
@@ -2638,13 +2712,13 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     }
   if (gimple_call_num_args (stmt) == 2)
-    success = update_gimple_call (gsi, fn, 3, dst, src, len);
+    success = update_gimple_call (&m_gsi, fn, 3, dst, src, len);
   else
-    success = update_gimple_call (gsi, fn, 4, dst, src, len,
+    success = update_gimple_call (&m_gsi, fn, 4, dst, src, len,
 				  gimple_call_arg (stmt, 2));
   if (success)
     {
-      stmt = gsi_stmt (*gsi);
+      stmt = gsi_stmt (m_gsi);
       update_stmt (stmt);
       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	{
@@ -2668,11 +2742,11 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
    size argument is derived from a call to strlen() on the source argument,
    and if so, issue an appropriate warning.  */
 
-static void
-handle_builtin_strncat (built_in_function, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_strncat (built_in_function)
 {
   /* Same as stxncpy().  */
-  handle_builtin_stxncpy_strncat (true, gsi);
+  handle_builtin_stxncpy_strncat (true);
 }
 
 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
@@ -3077,13 +3151,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
    and if so, issue the appropriate warning.
    APPEND_P is true for strncat.  */
 
-static void
-handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_builtin_stxncpy_strncat (bool append_p)
 {
   if (!strlen_to_stridx)
     return;
 
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
 
   tree dst = gimple_call_arg (stmt, 0);
   tree src = gimple_call_arg (stmt, 1);
@@ -3161,7 +3235,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
   stridx_strlenloc *pss = strlen_to_stridx->get (len);
   if (!pss || pss->first <= 0)
     {
-      if (maybe_diag_stxncpy_trunc (*gsi, src, len))
+      if (maybe_diag_stxncpy_trunc (m_gsi, src, len))
 	suppress_warning (stmt, OPT_Wstringop_truncation);
 
       return;
@@ -3219,12 +3293,11 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
    is that plus one, strlen of the first argument is the same after this
    call.  Uses RVALS to determine range information.  */
 
-static void
-handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
-		       pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_memcpy (built_in_function bcode)
 {
   tree lhs, oldlen, newlen;
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   strinfo *si, *dsi;
 
   tree len = gimple_call_arg (stmt, 2);
@@ -3241,8 +3314,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   if (olddsi != NULL
       && !integer_zerop (len))
     {
-      maybe_warn_overflow (stmt, false, len, ptr_qry, olddsi, false, true);
-      adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+      maybe_warn_overflow (stmt, false, len, olddsi, false, true);
+      adjust_last_stmt (olddsi, stmt, false);
     }
 
   int idx = get_stridx (src, stmt);
@@ -3319,7 +3392,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
     }
 
   if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
-    adjust_last_stmt (olddsi, stmt, false, ptr_qry);
+    adjust_last_stmt (olddsi, stmt, false);
 
   if (didx == 0)
     {
@@ -3400,14 +3473,13 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
    to convert it to memcpy/strcpy if the length of the first argument
    is known.  */
 
-static void
-handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
-		       pointer_query &ptr_qry)
+void
+strlen_pass::handle_builtin_strcat (built_in_function bcode)
 {
   int idx, didx;
   tree srclen, args, type, fn, objsz, endptr;
   bool success;
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   strinfo *si, *dsi;
   location_t loc = gimple_location (stmt);
 
@@ -3584,7 +3656,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       len = fold_convert_loc (loc, type, unshare_expr (srclen));
       len = fold_build2_loc (loc, PLUS_EXPR, type, len,
 			     build_int_cst (type, 1));
-      len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
+      len = force_gimple_operand_gsi (&m_gsi, len, true, NULL_TREE, true,
 				      GSI_SAME_STMT);
     }
   if (endptr)
@@ -3593,14 +3665,14 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
     dst = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dst), dst,
 			   fold_convert_loc (loc, sizetype,
 					     unshare_expr (dstlen)));
-  dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
+  dst = force_gimple_operand_gsi (&m_gsi, dst, true, NULL_TREE, true,
 				  GSI_SAME_STMT);
   if (objsz)
     {
       objsz = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (objsz), objsz,
 			       fold_convert_loc (loc, TREE_TYPE (objsz),
 						 unshare_expr (dstlen)));
-      objsz = force_gimple_operand_gsi (gsi, objsz, true, NULL_TREE, true,
+      objsz = force_gimple_operand_gsi (&m_gsi, objsz, true, NULL_TREE, true,
 					GSI_SAME_STMT);
     }
   if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -3609,14 +3681,14 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     }
   if (srclen != NULL_TREE)
-    success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
+    success = update_gimple_call (&m_gsi, fn, 3 + (objsz != NULL_TREE),
 				  dst, src, len, objsz);
   else
-    success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
+    success = update_gimple_call (&m_gsi, fn, 2 + (objsz != NULL_TREE),
 				  dst, src, objsz);
   if (success)
     {
-      stmt = gsi_stmt (*gsi);
+      stmt = gsi_stmt (m_gsi);
       update_stmt (stmt);
       if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	{
@@ -3627,7 +3699,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 	 computed by transforming this strcpy into stpcpy.  */
       if (srclen == NULL_TREE && dsi->dont_invalidate)
 	dsi->stmt = stmt;
-      adjust_last_stmt (dsi, stmt, true, ptr_qry);
+      adjust_last_stmt (dsi, stmt, true);
       if (srclen != NULL_TREE)
 	{
 	  laststmt.stmt = stmt;
@@ -3645,10 +3717,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 /* Handle a call to an allocation function like alloca, malloc or calloc,
    or an ordinary allocation function declared with attribute alloc_size.  */
 
-static void
-handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_alloc_call (built_in_function bcode)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   tree lhs = gimple_call_lhs (stmt);
   if (lhs == NULL_TREE)
     return;
@@ -3682,11 +3754,10 @@ handle_alloc_call (enum built_in_function bcode, gimple_stmt_iterator *gsi)
    return true when the call is transformed, false otherwise.
    When nonnull uses RVALS to determine range information.  */
 
-static bool
-handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
-		       pointer_query &ptr_qry)
+bool
+strlen_pass::handle_builtin_memset (bool *zero_write)
 {
-  gimple *memset_stmt = gsi_stmt (*gsi);
+  gimple *memset_stmt = gsi_stmt (m_gsi);
   tree ptr = gimple_call_arg (memset_stmt, 0);
   /* Set to the non-constant offset added to PTR.  */
   wide_int offrng[2];
@@ -3706,8 +3777,7 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
   tree memset_size = gimple_call_arg (memset_stmt, 2);
 
   /* Check for overflow.  */
-  maybe_warn_overflow (memset_stmt, false, memset_size, ptr_qry, NULL,
-		       false, true);
+  maybe_warn_overflow (memset_stmt, false, memset_size, NULL, false, true);
 
   /* Bail when there is no statement associated with the destination
      (the statement may be null even when SI1->ALLOC is not).  */
@@ -3747,11 +3817,11 @@ handle_builtin_memset (gimple_stmt_iterator *gsi, bool *zero_write,
   if (lhs)
     {
       gimple *assign = gimple_build_assign (lhs, ptr);
-      gsi_replace (gsi, assign, false);
+      gsi_replace (&m_gsi, assign, false);
     }
   else
     {
-      gsi_remove (gsi, true);
+      gsi_remove (&m_gsi, true);
       release_defs (memset_stmt);
     }
 
@@ -3835,10 +3905,10 @@ use_in_zero_equality (tree res, bool exclusive = true)
    with a __builtin_memcmp_eq call where possible.
    return true when call is transformed, return false otherwise.  */
 
-static bool
-handle_builtin_memcmp (gimple_stmt_iterator *gsi)
+bool
+strlen_pass::handle_builtin_memcmp ()
 {
-  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  gcall *stmt = as_a <gcall *> (gsi_stmt (m_gsi));
   tree res = gimple_call_lhs (stmt);
 
   if (!res || !use_in_zero_equality (res))
@@ -3880,7 +3950,7 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
 				  fold_build2_loc (loc, NE_EXPR,
 						   boolean_type_node,
 						   arg1, arg2));
-	  gimplify_and_update_call_from_tree (gsi, res);
+	  gimplify_and_update_call_from_tree (&m_gsi, res);
 	  return true;
 	}
     }
@@ -3897,11 +3967,10 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
    *NULTERM to true, otherwise to false.  When nonnull uses RVALS to
    determine range information. Returns true on success.  */
 
-static bool
-get_len_or_size (gimple *stmt, tree arg, int idx,
-		 unsigned HOST_WIDE_INT lenrng[2],
-		 unsigned HOST_WIDE_INT *size, bool *nulterm,
-		 range_query *rvals)
+bool
+strlen_pass::get_len_or_size (gimple *stmt, tree arg, int idx,
+			      unsigned HOST_WIDE_INT lenrng[2],
+			      unsigned HOST_WIDE_INT *size, bool *nulterm)
 {
   /* Invalidate.  */
   *size = HOST_WIDE_INT_M1U;
@@ -3954,7 +4023,7 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
   /* Set MAXBOUND to an arbitrary non-null non-integer node as a request
      to have it set to the length of the longest string in a PHI.  */
   lendata.maxbound = arg;
-  get_range_strlen_dynamic (arg, stmt, &lendata, rvals);
+  get_range_strlen_dynamic (arg, stmt, &lendata, ptr_qry.rvals);
 
   unsigned HOST_WIDE_INT maxbound = HOST_WIDE_INT_M1U;
   if (tree_fits_uhwi_p (lendata.maxbound)
@@ -4011,18 +4080,20 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
    to be at least as long and need not be nul-terminated) and size.
    Otherwise return null.  */
 
-static tree
-strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1, tree arg2, int idx2,
-		    unsigned HOST_WIDE_INT bound, unsigned HOST_WIDE_INT len[2],
-		    unsigned HOST_WIDE_INT *psize, range_query *rvals)
+tree
+strlen_pass::strxcmp_eqz_result (gimple *stmt, tree arg1, int idx1,
+				 tree arg2, int idx2,
+				 unsigned HOST_WIDE_INT bound,
+				 unsigned HOST_WIDE_INT len[2],
+				 unsigned HOST_WIDE_INT *psize)
 {
   /* Determine the range the length of each string is in and whether it's
      known to be nul-terminated, or the size of the array it's stored in.  */
   bool nul1, nul2;
   unsigned HOST_WIDE_INT siz1, siz2;
   unsigned HOST_WIDE_INT len1rng[2], len2rng[2];
-  if (!get_len_or_size (stmt, arg1, idx1, len1rng, &siz1, &nul1, rvals)
-      || !get_len_or_size (stmt, arg2, idx2, len2rng, &siz2, &nul2, rvals))
+  if (!get_len_or_size (stmt, arg1, idx1, len1rng, &siz1, &nul1)
+      || !get_len_or_size (stmt, arg2, idx2, len2rng, &siz2, &nul2))
     return NULL_TREE;
 
   /* BOUND is set to HWI_M1U for strcmp and less to strncmp, and LENiRNG
@@ -4170,10 +4241,10 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
    is not known.  Return true when the call has been transformed into
    another and false otherwise.  */
 
-static bool
-handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
+bool
+strlen_pass::handle_builtin_string_cmp ()
 {
-  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  gcall *stmt = as_a <gcall *> (gsi_stmt (m_gsi));
   tree lhs = gimple_call_lhs (stmt);
 
   if (!lhs)
@@ -4217,7 +4288,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
        or definitely unequal and if so, either fold the result to zero
        (when equal) or set the range of the result to ~[0, 0] otherwise.  */
     if (tree eqz = strxcmp_eqz_result (stmt, arg1, idx1, arg2, idx2, bound,
-				       len, &siz, rvals))
+				       len, &siz))
       {
 	if (integer_zerop (eqz))
 	  {
@@ -4233,7 +4304,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
 	  }
 	/* When the two strings are definitely equal (such as when they
 	   are both empty) fold the call to the constant result.  */
-	replace_call_with_value (gsi, integer_zero_node);
+	replace_call_with_value (&m_gsi, integer_zero_node);
 	return true;
       }
   }
@@ -4253,9 +4324,8 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
     unsigned HOST_WIDE_INT arsz1, arsz2;
     bool nulterm[2];
 
-    if (!get_len_or_size (stmt, arg1, idx1, len1rng, &arsz1, nulterm, rvals)
-	|| !get_len_or_size (stmt, arg2, idx2, len2rng, &arsz2, nulterm + 1,
-			     rvals))
+    if (!get_len_or_size (stmt, arg1, idx1, len1rng, &arsz1, nulterm)
+	|| !get_len_or_size (stmt, arg2, idx2, len2rng, &arsz2, nulterm + 1))
       return false;
 
     if (len1rng[0] == len1rng[1] && len1rng[0] < HOST_WIDE_INT_MAX)
@@ -4303,7 +4373,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
 					   : BUILT_IN_STRNCMP_EQ))
 	{
 	  tree n = build_int_cst (size_type_node, cmpsiz);
-	  update_gimple_call (gsi, fn, 3, arg1, arg2, n);
+	  update_gimple_call (&m_gsi, fn, 3, arg1, arg2, n);
 	  return true;
 	}
     }
@@ -4316,10 +4386,10 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi, range_query *rvals)
    p = q + off is pointing to a '\0' character of a string, call
    zero_length_string on it.  */
 
-static void
-handle_pointer_plus (gimple_stmt_iterator *gsi)
+void
+strlen_pass::handle_pointer_plus ()
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   tree lhs = gimple_assign_lhs (stmt), off;
   int idx = get_stridx (gimple_assign_rhs1 (stmt), stmt);
   strinfo *si, *zsi;
@@ -4362,8 +4432,8 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
       enum tree_code rhs_code
 	= useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
 	  ? SSA_NAME : NOP_EXPR;
-      gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
-      gcc_assert (gsi_stmt (*gsi) == stmt);
+      gimple_assign_set_rhs_with_ops (&m_gsi, rhs_code, si->endptr);
+      gcc_assert (gsi_stmt (m_gsi) == stmt);
       update_stmt (stmt);
     }
 }
@@ -4398,12 +4468,6 @@ nonzero_bytes_for_type (tree type, unsigned lenrange[3],
   return true;
 }
 
-static bool
-count_nonzero_bytes_addr (tree, gimple *stmt,
-			  unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
-			  unsigned [3], bool *, bool *, bool *,
-			  range_query *, ssa_name_limit_t &);
-
 /* Recursively determine the minimum and maximum number of leading nonzero
    bytes in the representation of EXP and set LENRANGE[0] and LENRANGE[1]
    to each.
@@ -4419,13 +4483,13 @@ count_nonzero_bytes_addr (tree, gimple *stmt,
    Avoids recursing deeper than the limits in SNLIM allow.
    Returns true on success and false otherwise.  */
 
-static bool
-count_nonzero_bytes (tree exp, gimple *stmt,
-		     unsigned HOST_WIDE_INT offset,
-		     unsigned HOST_WIDE_INT nbytes,
-		     unsigned lenrange[3], bool *nulterm,
-		     bool *allnul, bool *allnonnul, range_query *rvals,
-		     ssa_name_limit_t &snlim)
+bool
+strlen_pass::count_nonzero_bytes (tree exp, gimple *stmt,
+				  unsigned HOST_WIDE_INT offset,
+				  unsigned HOST_WIDE_INT nbytes,
+				  unsigned lenrange[3], bool *nulterm,
+				  bool *allnul, bool *allnonnul,
+				  ssa_name_limit_t &snlim)
 {
   if (TREE_CODE (exp) == SSA_NAME)
     {
@@ -4442,7 +4506,7 @@ count_nonzero_bytes (tree exp, gimple *stmt,
 	  exp = build_int_cst (type, 1);
 	  return count_nonzero_bytes (exp, stmt,
 				      offset, 1, lenrange,
-				      nulterm, allnul, allnonnul, rvals, snlim);
+				      nulterm, allnul, allnonnul, snlim);
 	}
 
       gimple *stmt = SSA_NAME_DEF_STMT (exp);
@@ -4470,7 +4534,7 @@ count_nonzero_bytes (tree exp, gimple *stmt,
 	      tree def = gimple_phi_arg_def (stmt, i);
 	      if (!count_nonzero_bytes (def, stmt,
 					offset, nbytes, lenrange, nulterm,
-					allnul, allnonnul, rvals, snlim))
+					allnul, allnonnul, snlim))
 		return false;
 	    }
 
@@ -4528,7 +4592,7 @@ count_nonzero_bytes (tree exp, gimple *stmt,
       /* Handle MEM_REF = SSA_NAME types of assignments.  */
       return count_nonzero_bytes_addr (arg, stmt,
 				       offset, nbytes, lenrange, nulterm,
-				       allnul, allnonnul, rvals, snlim);
+				       allnul, allnonnul, snlim);
     }
 
   if (VAR_P (exp) || TREE_CODE (exp) == CONST_DECL)
@@ -4638,13 +4702,13 @@ count_nonzero_bytes (tree exp, gimple *stmt,
 /* Like count_nonzero_bytes, but instead of counting bytes in EXP, count
    bytes that are pointed to by EXP, which should be a pointer.  */
 
-static bool
-count_nonzero_bytes_addr (tree exp, gimple *stmt,
-			  unsigned HOST_WIDE_INT offset,
-			  unsigned HOST_WIDE_INT nbytes,
-			  unsigned lenrange[3], bool *nulterm,
-			  bool *allnul, bool *allnonnul,
-			  range_query *rvals, ssa_name_limit_t &snlim)
+bool
+strlen_pass::count_nonzero_bytes_addr (tree exp, gimple *stmt,
+				       unsigned HOST_WIDE_INT offset,
+				       unsigned HOST_WIDE_INT nbytes,
+				       unsigned lenrange[3], bool *nulterm,
+				       bool *allnul, bool *allnonnul,
+				       ssa_name_limit_t &snlim)
 {
   int idx = get_stridx (exp, stmt);
   if (idx > 0)
@@ -4662,7 +4726,7 @@ count_nonzero_bytes_addr (tree exp, gimple *stmt,
 	       && TREE_CODE (si->nonzero_chars) == SSA_NAME)
 	{
 	  value_range vr;
-	  rvals->range_of_expr (vr, si->nonzero_chars, stmt);
+	  ptr_qry.rvals->range_of_expr (vr, si->nonzero_chars, stmt);
 	  if (vr.kind () != VR_RANGE)
 	    return false;
 
@@ -4710,7 +4774,7 @@ count_nonzero_bytes_addr (tree exp, gimple *stmt,
   if (TREE_CODE (exp) == ADDR_EXPR)
     return count_nonzero_bytes (TREE_OPERAND (exp, 0), stmt,
 				offset, nbytes,
-				lenrange, nulterm, allnul, allnonnul, rvals,
+				lenrange, nulterm, allnul, allnonnul,
 				snlim);
 
   if (TREE_CODE (exp) == SSA_NAME)
@@ -4731,8 +4795,7 @@ count_nonzero_bytes_addr (tree exp, gimple *stmt,
 	      tree def = gimple_phi_arg_def (stmt, i);
 	      if (!count_nonzero_bytes_addr (def, stmt,
 					     offset, nbytes, lenrange,
-					     nulterm, allnul, allnonnul, rvals,
-					     snlim))
+					     nulterm, allnul, allnonnul, snlim))
 		return false;
 	    }
 
@@ -4757,10 +4820,10 @@ count_nonzero_bytes_addr (tree exp, gimple *stmt,
    RVALS is used to determine ranges of dynamically computed string lengths
    (the results of strlen).  */
 
-static bool
-count_nonzero_bytes (tree expr_or_type, gimple *stmt,
-		     unsigned lenrange[3], bool *nulterm,
-		     bool *allnul, bool *allnonnul, range_query *rvals)
+bool
+strlen_pass::count_nonzero_bytes (tree expr_or_type, gimple *stmt,
+				  unsigned lenrange[3], bool *nulterm,
+				  bool *allnul, bool *allnonnul)
 {
   if (TYPE_P (expr_or_type))
     return nonzero_bytes_for_type (expr_or_type, lenrange,
@@ -4779,7 +4842,7 @@ count_nonzero_bytes (tree expr_or_type, gimple *stmt,
   tree expr = expr_or_type;
   return count_nonzero_bytes (expr, stmt,
 			      0, 0, lenrange, nulterm, allnul, allnonnul,
-			      rvals, snlim);
+			      snlim);
 }
 
 /* Handle a single or multibyte store other than by a built-in function,
@@ -4788,11 +4851,10 @@ count_nonzero_bytes (tree expr_or_type, gimple *stmt,
    '*(int*)a = 12345').  Return true to let the caller advance *GSI to
    the next statement in the basic block and false otherwise.  */
 
-static bool
-handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
-	      pointer_query &ptr_qry)
+bool
+strlen_pass::handle_store (bool *zero_write)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   /* The LHS and RHS of the store.  The RHS is null if STMT is a function
      call.  STORETYPE is the type of the store (determined from either
      the RHS of the assignment statement or the LHS of a function call.  */
@@ -4844,8 +4906,8 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	      bool dummy;
 	      unsigned lenrange[] = { UINT_MAX, 0, 0 };
 	      if (count_nonzero_bytes (rhs ? rhs : storetype, stmt, lenrange,
-				       &dummy, &dummy, &dummy, rvals))
-		maybe_warn_overflow (stmt, true, lenrange[2], ptr_qry);
+				       &dummy, &dummy, &dummy))
+		maybe_warn_overflow (stmt, true, lenrange[2]);
 
 	      return true;
 	    }
@@ -4878,8 +4940,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
   const bool ranges_valid
     = count_nonzero_bytes (rhs ? rhs : storetype, stmt,
 			   lenrange, &full_string_p,
-			   &storing_all_zeros_p, &storing_all_nonzero_p,
-			   rvals);
+			   &storing_all_zeros_p, &storing_all_nonzero_p);
 
   if (ranges_valid)
     {
@@ -4887,7 +4948,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
       storing_nonzero_p = lenrange[1] > 0;
       *zero_write = storing_all_zeros_p;
 
-      maybe_warn_overflow (stmt, true, lenrange[2], ptr_qry);
+      maybe_warn_overflow (stmt, true, lenrange[2]);
     }
   else
     {
@@ -4937,13 +4998,13 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	    {
 	      unlink_stmt_vdef (stmt);
 	      release_defs (stmt);
-	      gsi_remove (gsi, true);
+	      gsi_remove (&m_gsi, true);
 	      return false;
 	    }
 	  else
 	    {
 	      si->writable = true;
-	      gsi_next (gsi);
+	      gsi_next (&m_gsi);
 	      return false;
 	    }
 	}
@@ -4977,7 +5038,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	       size_t len4 = strlen (q);    // can be folded to len2
 	       bar (len, len2, len3, len4);
 	       } */
-	  gsi_next (gsi);
+	  gsi_next (&m_gsi);
 	  return false;
 	}
 
@@ -5008,7 +5069,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write,
 	    /* We're overwriting the nul terminator with a nonzero or
 	       unknown character.  If the previous stmt was a memcpy,
 	       its length may be decreased.  */
-	    adjust_last_stmt (si, stmt, false, ptr_qry);
+	    adjust_last_stmt (si, stmt, false);
 	  si = unshare_strinfo (si);
 	  if (storing_nonzero_p)
 	    {
@@ -5224,11 +5285,10 @@ is_char_type (tree type)
    Return true to let the caller advance *GSI to the next statement
    in the basic block and false otherwise.  */
 
-static bool
-strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
-				pointer_query &ptr_qry)
+bool
+strlen_pass::check_and_optimize_call (bool *zero_write)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
 
   if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
     {
@@ -5238,12 +5298,12 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
 
       if (lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (fntype)))
 	{
-	  handle_alloc_call (BUILT_IN_NONE, gsi);
+	  handle_alloc_call (BUILT_IN_NONE);
 	  return true;
 	}
 
       if (tree lhs = gimple_call_lhs (stmt))
-	handle_assign (gsi, lhs, zero_write, ptr_qry);
+	handle_assign (lhs, zero_write);
 
       /* Proceed to handle user-defined formatting functions.  */
     }
@@ -5254,68 +5314,68 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
   if (!flag_optimize_strlen
       || !strlen_optimize
       || !valid_builtin_call (stmt))
-    return !handle_printf_call (gsi, ptr_qry);
+    return !handle_printf_call (&m_gsi, ptr_qry);
 
   tree callee = gimple_call_fndecl (stmt);
   switch (DECL_FUNCTION_CODE (callee))
     {
     case BUILT_IN_STRLEN:
     case BUILT_IN_STRNLEN:
-      handle_builtin_strlen (gsi);
+      handle_builtin_strlen ();
       break;
     case BUILT_IN_STRCHR:
-      handle_builtin_strchr (gsi);
+      handle_builtin_strchr ();
       break;
     case BUILT_IN_STRCPY:
     case BUILT_IN_STRCPY_CHK:
     case BUILT_IN_STPCPY:
     case BUILT_IN_STPCPY_CHK:
-      handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+      handle_builtin_strcpy (DECL_FUNCTION_CODE (callee));
       break;
 
     case BUILT_IN_STRNCAT:
     case BUILT_IN_STRNCAT_CHK:
-      handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
+      handle_builtin_strncat (DECL_FUNCTION_CODE (callee));
       break;
 
     case BUILT_IN_STPNCPY:
     case BUILT_IN_STPNCPY_CHK:
     case BUILT_IN_STRNCPY:
     case BUILT_IN_STRNCPY_CHK:
-      handle_builtin_stxncpy_strncat (false, gsi);
+      handle_builtin_stxncpy_strncat (false);
       break;
 
     case BUILT_IN_MEMCPY:
     case BUILT_IN_MEMCPY_CHK:
     case BUILT_IN_MEMPCPY:
     case BUILT_IN_MEMPCPY_CHK:
-      handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+      handle_builtin_memcpy (DECL_FUNCTION_CODE (callee));
       break;
     case BUILT_IN_STRCAT:
     case BUILT_IN_STRCAT_CHK:
-      handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi, ptr_qry);
+      handle_builtin_strcat (DECL_FUNCTION_CODE (callee));
       break;
     case BUILT_IN_ALLOCA:
     case BUILT_IN_ALLOCA_WITH_ALIGN:
     case BUILT_IN_MALLOC:
     case BUILT_IN_CALLOC:
-      handle_alloc_call (DECL_FUNCTION_CODE (callee), gsi);
+      handle_alloc_call (DECL_FUNCTION_CODE (callee));
       break;
     case BUILT_IN_MEMSET:
-      if (handle_builtin_memset (gsi, zero_write, ptr_qry))
+      if (handle_builtin_memset (zero_write))
 	return false;
       break;
     case BUILT_IN_MEMCMP:
-      if (handle_builtin_memcmp (gsi))
+      if (handle_builtin_memcmp ())
 	return false;
       break;
     case BUILT_IN_STRCMP:
     case BUILT_IN_STRNCMP:
-      if (handle_builtin_string_cmp (gsi, ptr_qry.rvals))
+      if (handle_builtin_string_cmp ())
 	return false;
       break;
     default:
-      if (handle_printf_call (gsi, ptr_qry))
+      if (handle_printf_call (&m_gsi, ptr_qry))
 	return false;
       break;
     }
@@ -5326,11 +5386,10 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi, bool *zero_write,
 /* Handle an assignment statement at *GSI to a LHS of integral type.
    If GSI's basic block needs clean-up of EH, set *CLEANUP_EH to true.  */
 
-static void
-handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
-			range_query *rvals)
+void
+strlen_pass::handle_integral_assign (bool *cleanup_eh)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
   tree lhs = gimple_assign_lhs (stmt);
   tree lhs_type = TREE_TYPE (lhs);
 
@@ -5399,11 +5458,11 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 		  /* Reading the final '\0' character.  */
 		  tree zero = build_int_cst (lhs_type, 0);
 		  gimple_set_vuse (stmt, NULL_TREE);
-		  gimple_assign_set_rhs_from_tree (gsi, zero);
+		  gimple_assign_set_rhs_from_tree (&m_gsi, zero);
 		  *cleanup_eh
 		    |= maybe_clean_or_replace_eh_stmt (stmt,
-						       gsi_stmt (*gsi));
-		  stmt = gsi_stmt (*gsi);
+						       gsi_stmt (m_gsi));
+		  stmt = gsi_stmt (m_gsi);
 		  update_stmt (stmt);
 
 		  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -5441,8 +5500,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 	  const bool ranges_valid
 	    = count_nonzero_bytes (rhs, stmt,
 				   lenrange, &full_string_p,
-				   &storing_all_zeros_p, &storing_all_nonzero_p,
-				   rvals);
+				   &storing_all_zeros_p,
+				   &storing_all_nonzero_p);
 	  if (ranges_valid)
 	    {
 	      tree length = build_int_cst (sizetype, lenrange[0]);
@@ -5465,9 +5524,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 /* Handle assignment statement at *GSI to LHS.  Set *ZERO_WRITE if
    the assignent stores all zero bytes..  */
 
-static bool
-handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
-	       pointer_query &ptr_qry)
+bool
+strlen_pass::handle_assign (tree lhs, bool *zero_write)
 {
   tree type = TREE_TYPE (lhs);
   if (TREE_CODE (type) == ARRAY_TYPE)
@@ -5497,7 +5555,7 @@ handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
     }
 
   /* Handle a single or multibyte assignment.  */
-  if (is_char_store && !handle_store (gsi, zero_write, ptr_qry))
+  if (is_char_store && !handle_store (zero_write))
     return false;
 
   return true;
@@ -5510,11 +5568,10 @@ handle_assign (gimple_stmt_iterator *gsi, tree lhs, bool *zero_write,
    true.  Return true to let the caller advance *GSI to the next statement
    in the basic block and false otherwise.  */
 
-static bool
-check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
-			 pointer_query &ptr_qry)
+bool
+strlen_pass::check_and_optimize_stmt (bool *cleanup_eh)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (m_gsi);
 
   /* For statements that modify a string, set to true if the write
      is only zeros.  */
@@ -5522,7 +5579,7 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 
   if (is_gimple_call (stmt))
     {
-      if (!strlen_check_and_optimize_call (gsi, &zero_write, ptr_qry))
+      if (!check_and_optimize_call (&zero_write))
 	return false;
     }
   else if (!flag_optimize_strlen || !strlen_optimize)
@@ -5543,13 +5600,13 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
 	      ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
 	    }
 	  else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
-	    handle_pointer_plus (gsi);
+	    handle_pointer_plus ();
 	}
       else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (lhs_type))
 	/* Handle assignment to a character.  */
-	handle_integral_assign (gsi, cleanup_eh, ptr_qry.rvals);
+	handle_integral_assign (cleanup_eh);
       else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
-	if (!handle_assign (gsi, lhs, &zero_write, ptr_qry))
+	if (!handle_assign (lhs, &zero_write))
 	  return false;
     }
   else if (gcond *cond = dyn_cast<gcond *> (stmt))
@@ -5616,39 +5673,9 @@ do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
     }
 }
 
-class strlen_dom_walker : public dom_walker
-{
-public:
-  strlen_dom_walker (cdi_direction direction)
-    : dom_walker (direction),
-      ptr_qry (&m_ranger, &var_cache),
-      var_cache (),
-      m_cleanup_cfg (false)
-  {
-  }
-
-  ~strlen_dom_walker ();
-
-  virtual edge before_dom_children (basic_block);
-  virtual void after_dom_children (basic_block);
-
-  /* Ranger used for printf argument range processing, and
-     to track strlen results across integer variable assignments.  */
-  gimple_ranger m_ranger;
-
-  /* A pointer_query object and its cache to store information about
-     pointers and their targets in.  */
-  pointer_query ptr_qry;
-  pointer_query::cache_type var_cache;
-
-  /* Flag that will trigger TODO_cleanup_cfg to be returned in strlen
-     execute function.  */
-  bool m_cleanup_cfg;
-};
-
 /* Release pointer_query cache.  */
 
-strlen_dom_walker::~strlen_dom_walker ()
+strlen_pass::~strlen_pass ()
 {
   ptr_qry.flush_cache ();
 }
@@ -5657,7 +5684,7 @@ strlen_dom_walker::~strlen_dom_walker ()
    string ops by remembering string lengths pointed by pointer SSA_NAMEs.  */
 
 edge
-strlen_dom_walker::before_dom_children (basic_block bb)
+strlen_pass::before_dom_children (basic_block bb)
 {
   basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
 
@@ -5731,13 +5758,13 @@ strlen_dom_walker::before_dom_children (basic_block bb)
   bool cleanup_eh = false;
 
   /* Attempt to optimize individual statements.  */
-  for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+  for (m_gsi = gsi_start_bb (bb); !gsi_end_p (m_gsi); )
     {
       /* Reset search depth preformance counter.  */
       ptr_qry.depth = 0;
 
-      if (check_and_optimize_stmt (&gsi, &cleanup_eh, ptr_qry))
-	gsi_next (&gsi);
+      if (check_and_optimize_stmt (&cleanup_eh))
+	gsi_next (&m_gsi);
     }
 
   if (cleanup_eh && gimple_purge_dead_eh_edges (bb))
@@ -5753,7 +5780,7 @@ strlen_dom_walker::before_dom_children (basic_block bb)
    owned by the current bb, clear bb->aux.  */
 
 void
-strlen_dom_walker::after_dom_children (basic_block bb)
+strlen_pass::after_dom_children (basic_block bb)
 {
   if (bb->aux)
     {
@@ -5799,7 +5826,7 @@ printf_strlen_execute (function *fun, bool warn_only)
 
   /* String length optimization is implemented as a walk of the dominator
      tree and a forward walk of statements within each block.  */
-  strlen_dom_walker walker (CDI_DOMINATORS);
+  strlen_pass walker (CDI_DOMINATORS);
   walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-- 
2.31.1


  reply	other threads:[~2021-10-15 10:39 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-08 15:12 Aldy Hernandez
2021-10-08 16:51 ` Martin Sebor
2021-10-08 17:56   ` Andrew MacLeod
2021-10-08 20:27     ` Martin Sebor
2021-10-09 15:04   ` Aldy Hernandez
2021-10-09 16:19     ` Martin Sebor
2021-10-09 17:59       ` Martin Sebor
2021-10-11  6:54         ` Aldy Hernandez
2021-10-09 18:47 ` Aldy Hernandez
2021-10-14 22:07   ` Martin Sebor
2021-10-14 23:45     ` Jeff Law
2021-10-15  0:47     ` Andrew MacLeod
2021-10-15 10:39       ` Aldy Hernandez [this message]
2021-10-17 22:49         ` Jeff Law
2021-10-18  7:43           ` Aldy Hernandez
2021-10-22 11:11         ` Aldy Hernandez
2021-10-29 20:04         ` Aldy Hernandez
2021-11-09  0:09         ` Jeff Law
2021-10-17 22:52 ` Jeff Law
2021-10-18  8:17   ` Aldy Hernandez
2021-10-20 20:58     ` Jeff Law
2021-10-21  7:42       ` Aldy Hernandez
2021-10-21 18:20         ` Jeff Law
2021-10-23 21:32           ` Jeff Law
2021-10-25  1:59             ` Jeff Law
2021-10-21 10:20       ` Richard Biener
2021-10-21 12:56         ` Aldy Hernandez
2021-10-21 13:14           ` Richard Biener
2021-10-21 13:30             ` Aldy Hernandez
2021-10-21 13:46               ` Richard Biener
2021-10-21 14:17                 ` Aldy Hernandez
2021-10-21 13:43           ` Jeff Law
2021-10-21 14:18             ` Aldy Hernandez
2021-10-25  2:15     ` Jeff Law
2021-10-25  4:42       ` Jeff Law
2021-10-25 11:27         ` Aldy Hernandez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d12640dc-3bb1-4d7d-ecd8-557beed01fe5@redhat.com \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=jeffreyalaw@gmail.com \
    --cc=msebor@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).