This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Refactor non-SSA_NAME handling out of get_range_strlen



This patch factors handling of non-SSA_NAME arguments out of
get_range_strlen.  It is the equivalent of patch #1 from Martin's
original submission.  Again, this should not affect behavior of GCC at all.

I'm attaching the normal diff as well as a -b diff which shows that most
of the change is just removing an indentation level.

Bootstrapped and regression tested on x86_64-linux-gnu.  Committing to
the trunk.  This is likely all I'll do today.  Next up will be API
changes to the key functions.

Jeff
commit a44f5ba24979f373fbcbc5dc25a43a5fd0cdc9c2
Author: Jeff Law <law@torsion.usersys.redhat.com>
Date:   Fri Dec 21 11:35:43 2018 -0500

            * gimple-fold.c (get_range_strlen_tree): Factored out of
            get_range_strlen.  Minor comment updates/additions.  Assert
            argument is not a simple SSA_NAME.
            (get_range_strlen): Call get_range_strlen_tree as appropriate.
            Minor comment updates/additions.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 65f87a3ddfa..15d43d25774 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2018-12-24  Martin Sebor  <msebor@redhat.com>
+
+	* gimple-fold.c (get_range_strlen_tree): Factored out of
+	get_range_strlen.  Minor comment updates/additions.  Assert
+	argument is not a simple SSA_NAME.
+	(get_range_strlen): Call get_range_strlen_tree as appropriate.
+	Minor comment updates/additions.
+
 2018-12-24  Jan Hubicka  <hubicka@ucw.cz>
 
 	* ipa-devirt.c (dump_targets): Cap number of targets printed.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b1dd4416567..4f84f0c0cc3 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -66,6 +66,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vector-builder.h"
 #include "tree-ssa-strlen.h"
 
+static bool get_range_strlen (tree, tree[2], bitmap *, int,
+		  int, bool *, unsigned, tree *);
+
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
    We can get declarations that are not possible to reference for various
@@ -1258,222 +1261,243 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
   return true;
 }
 
-
-/* Obtain the minimum and maximum string length or minimum and maximum
-   value of ARG in LENGTH[0] and LENGTH[1], respectively.
-   If ARG is an SSA name variable, follow its use-def chains.  When
-   TYPE == 0, if LENGTH[1] is not equal to the length we determine or
-   if we are unable to determine the length or value, return false.
-   VISITED is a bitmap of visited variables.
-   TYPE is 0 if string length should be obtained, 1 for maximum string
-   length and 2 for maximum value ARG can have.
-   When FUZZY is non-zero and the length of a string cannot be determined,
-   the function instead considers as the maximum possible length the
-   size of a character array it may refer to.  If FUZZY is 2, it will handle
-   PHIs and COND_EXPRs optimistically, if we can determine string length
-   minimum and maximum, it will use the minimum from the ones where it
-   can be determined.
-   Set *FLEXP to true if the range of the string lengths has been
-   obtained from the upper bound of an array at the end of a struct.
-   Such an array may hold a string that's longer than its upper bound
-   due to it being used as a poor-man's flexible array member.
-   Pass NONSTR through to children.
-   ELTSIZE is 1 for normal single byte character strings, and 2 or
-   4 for wide characer strings.  ELTSIZE is by default 1.  */
+/* Helper of get_range_strlen for ARG that is not an SSA_NAME.  */
 
 static bool
-get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
-		  int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
+get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
+		       int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
 {
-  tree var, val = NULL_TREE;
-  gimple *def_stmt;
-
+  gcc_assert (TREE_CODE (arg) != SSA_NAME);
+ 
   /* The minimum and maximum length.  */
   tree *const minlen = length;
   tree *const maxlen = length + 1;
 
-  if (TREE_CODE (arg) != SSA_NAME)
+  /* The length computed by this invocation of the function.  */
+  tree val = NULL_TREE;
+
+  /* We can end up with &(*iftmp_1)[0] here as well, so handle it.  */
+  if (TREE_CODE (arg) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
     {
-      /* We can end up with &(*iftmp_1)[0] here as well, so handle it.  */
-      if (TREE_CODE (arg) == ADDR_EXPR
-	  && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
+      tree op = TREE_OPERAND (arg, 0);
+      if (integer_zerop (TREE_OPERAND (op, 1)))
 	{
-	  tree op = TREE_OPERAND (arg, 0);
-	  if (integer_zerop (TREE_OPERAND (op, 1)))
-	    {
-	      tree aop0 = TREE_OPERAND (op, 0);
-	      if (TREE_CODE (aop0) == INDIRECT_REF
-		  && TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
-		return get_range_strlen (TREE_OPERAND (aop0, 0), length,
-					 visited, type, fuzzy, flexp,
-					 eltsize, nonstr);
-	    }
-	  else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
-	    {
-	      /* Fail if an array is the last member of a struct object
-		 since it could be treated as a (fake) flexible array
-		 member.  */
-	      tree idx = TREE_OPERAND (op, 1);
-
-	      arg = TREE_OPERAND (op, 0);
-	      tree optype = TREE_TYPE (arg);
-	      if (tree dom = TYPE_DOMAIN (optype))
-		if (tree bound = TYPE_MAX_VALUE (dom))
-		  if (TREE_CODE (bound) == INTEGER_CST
-		      && TREE_CODE (idx) == INTEGER_CST
-		      && tree_int_cst_lt (bound, idx))
-		    return false;
-	    }
+	  tree aop0 = TREE_OPERAND (op, 0);
+	  if (TREE_CODE (aop0) == INDIRECT_REF
+	      && TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
+	    return get_range_strlen (TREE_OPERAND (aop0, 0), length,
+				     visited, type, fuzzy, flexp,
+				     eltsize, nonstr);
 	}
-
-      if (type == 2)
+      else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
 	{
-	  val = arg;
-	  if (TREE_CODE (val) != INTEGER_CST
-	      || tree_int_cst_sgn (val) < 0)
-	    return false;
+	  /* Fail if an array is the last member of a struct object
+	     since it could be treated as a (fake) flexible array
+	     member.  */
+	  tree idx = TREE_OPERAND (op, 1);
+
+	  arg = TREE_OPERAND (op, 0);
+	  tree optype = TREE_TYPE (arg);
+	  if (tree dom = TYPE_DOMAIN (optype))
+	    if (tree bound = TYPE_MAX_VALUE (dom))
+	      if (TREE_CODE (bound) == INTEGER_CST
+		  && TREE_CODE (idx) == INTEGER_CST
+		  && tree_int_cst_lt (bound, idx))
+		return false;
 	}
-      else
-	{
-	  c_strlen_data lendata = { };
-	  val = c_strlen (arg, 1, &lendata, eltsize);
+    }
 
-	  /* If we potentially had a non-terminated string, then
-	     bubble that information up to the caller.  */
-	  if (!val && lendata.decl)
-	    {
-	      *nonstr = lendata.decl;
-	      *minlen = lendata.minlen;
-	      *maxlen = lendata.minlen;
-	      return type == 0 ? false : true;
-	    }
+  if (type == 2)
+    {
+      /* We are computing the maximum value (not string length).  */
+      val = arg;
+      if (TREE_CODE (val) != INTEGER_CST
+	  || tree_int_cst_sgn (val) < 0)
+	return false;
+    }
+  else
+    {
+      c_strlen_data lendata = { };
+      val = c_strlen (arg, 1, &lendata, eltsize);
+
+      /* If we potentially had a non-terminated string, then
+	 bubble that information up to the caller.  */
+      if (!val && lendata.decl)
+	{
+	  *nonstr = lendata.decl;
+	  *minlen = lendata.minlen;
+	  *maxlen = lendata.minlen;
+	  return type == 0 ? false : true;
 	}
+    }
+
+  if (!val && fuzzy)
+    {
+      if (TREE_CODE (arg) == ADDR_EXPR)
+	return get_range_strlen (TREE_OPERAND (arg, 0), length,
+				 visited, type, fuzzy, flexp,
+				 eltsize, nonstr);
 
-      if (!val && fuzzy)
+      if (TREE_CODE (arg) == ARRAY_REF)
 	{
-	  if (TREE_CODE (arg) == ADDR_EXPR)
-	    return get_range_strlen (TREE_OPERAND (arg, 0), length,
-				     visited, type, fuzzy, flexp,
-				     eltsize, nonstr);
+	  tree optype = TREE_TYPE (TREE_OPERAND (arg, 0));
 
-	  if (TREE_CODE (arg) == ARRAY_REF)
-	    {
-	      tree optype = TREE_TYPE (TREE_OPERAND (arg, 0));
+	  /* Determine the "innermost" array type.  */
+	  while (TREE_CODE (optype) == ARRAY_TYPE
+		 && TREE_CODE (TREE_TYPE (optype)) == ARRAY_TYPE)
+	    optype = TREE_TYPE (optype);
 
-	      /* Determine the "innermost" array type.  */
-	      while (TREE_CODE (optype) == ARRAY_TYPE
-		     && TREE_CODE (TREE_TYPE (optype)) == ARRAY_TYPE)
-		optype = TREE_TYPE (optype);
+	  /* Avoid arrays of pointers.  */
+	  tree eltype = TREE_TYPE (optype);
+	  if (TREE_CODE (optype) != ARRAY_TYPE
+	      || !INTEGRAL_TYPE_P (eltype))
+	    return false;
 
-	      /* Avoid arrays of pointers.  */
-	      tree eltype = TREE_TYPE (optype);
-	      if (TREE_CODE (optype) != ARRAY_TYPE
-		  || !INTEGRAL_TYPE_P (eltype))
-		return false;
+	  /* Fail when the array bound is unknown or zero.  */
+	  val = TYPE_SIZE_UNIT (optype);
+	  if (!val || integer_zerop (val))
+	    return false;
 
-	      /* Fail when the array bound is unknown or zero.  */
-	      val = TYPE_SIZE_UNIT (optype);
-	      if (!val || integer_zerop (val))
-		return false;
+	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
+			      integer_one_node);
 
-	      val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
-				 integer_one_node);
-	      /* Set the minimum size to zero since the string in
-		 the array could have zero length.  */
-	      *minlen = ssize_int (0);
+	  /* Set the minimum size to zero since the string in
+	     the array could have zero length.  */
+	  *minlen = ssize_int (0);
 
-	      if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF
-		  && optype == TREE_TYPE (TREE_OPERAND (arg, 0))
-		  && array_at_struct_end_p (TREE_OPERAND (arg, 0)))
-		*flexp = true;
-	    }
-	  else if (TREE_CODE (arg) == COMPONENT_REF
-		   && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
-		       == ARRAY_TYPE))
+	  if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF
+	      && optype == TREE_TYPE (TREE_OPERAND (arg, 0))
+	      && array_at_struct_end_p (TREE_OPERAND (arg, 0)))
+	    *flexp = true;
+	}
+      else if (TREE_CODE (arg) == COMPONENT_REF
+	       && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
+		   == ARRAY_TYPE))
+	{
+	  /* Use the type of the member array to determine the upper
+	     bound on the length of the array.  This may be overly
+	     optimistic if the array itself isn't NUL-terminated and
+	     the caller relies on the subsequent member to contain
+	     the NUL but that would only be considered valid if
+	     the array were the last member of a struct.
+	      Set *FLEXP to true if the array whose bound is being
+	     used is at the end of a struct.  */
+	  if (array_at_struct_end_p (arg))
+	    *flexp = true;
+
+	  tree fld = TREE_OPERAND (arg, 1);
+
+	  tree optype = TREE_TYPE (fld);
+
+	  /* Determine the "innermost" array type.  */
+	  while (TREE_CODE (optype) == ARRAY_TYPE
+		 && TREE_CODE (TREE_TYPE (optype)) == ARRAY_TYPE)
+	    optype = TREE_TYPE (optype);
+
+	  /* Fail when the array bound is unknown or zero.  */
+	  val = TYPE_SIZE_UNIT (optype);
+	  if (!val || integer_zerop (val))
+	    return false;
+	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
+			     integer_one_node);
+
+	  /* Set the minimum size to zero since the string in
+	     the array could have zero length.  */
+	  *minlen = ssize_int (0);
+	}
+
+      if (VAR_P (arg))
+	{
+	  tree type = TREE_TYPE (arg);
+	  if (POINTER_TYPE_P (type))
+	    type = TREE_TYPE (type);
+
+	  if (TREE_CODE (type) == ARRAY_TYPE)
 	    {
-	      /* Use the type of the member array to determine the upper
-		 bound on the length of the array.  This may be overly
-		 optimistic if the array itself isn't NUL-terminated and
-		 the caller relies on the subsequent member to contain
-		 the NUL but that would only be considered valid if
-		 the array were the last member of a struct.
-		 Set *FLEXP to true if the array whose bound is being
-		 used is at the end of a struct.  */
-	      if (array_at_struct_end_p (arg))
-		*flexp = true;
-
-	      tree fld = TREE_OPERAND (arg, 1);
-
-	      tree optype = TREE_TYPE (fld);
-
-	      /* Determine the "innermost" array type.  */
-	      while (TREE_CODE (optype) == ARRAY_TYPE
-		     && TREE_CODE (TREE_TYPE (optype)) == ARRAY_TYPE)
-		optype = TREE_TYPE (optype);
-
-	      /* Fail when the array bound is unknown or zero.  */
-	      val = TYPE_SIZE_UNIT (optype);
-	      if (!val || integer_zerop (val))
+	      val = TYPE_SIZE_UNIT (type);
+	      if (!val
+		  || TREE_CODE (val) != INTEGER_CST
+		  || integer_zerop (val))
 		return false;
-	      val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
-				 integer_one_node);
+	      val = wide_int_to_tree (TREE_TYPE (val),
+				      wi::sub (wi::to_wide (val), 1));
+
 	      /* Set the minimum size to zero since the string in
 		 the array could have zero length.  */
 	      *minlen = ssize_int (0);
 	    }
-
-	  if (VAR_P (arg))
-	    {
-	      tree type = TREE_TYPE (arg);
-	      if (POINTER_TYPE_P (type))
-		type = TREE_TYPE (type);
-
-	      if (TREE_CODE (type) == ARRAY_TYPE)
-		{
-		  val = TYPE_SIZE_UNIT (type);
-		  if (!val
-		      || TREE_CODE (val) != INTEGER_CST
-		      || integer_zerop (val))
-		    return false;
-		  val = wide_int_to_tree (TREE_TYPE (val),
-					  wi::sub (wi::to_wide (val), 1));
-		  /* Set the minimum size to zero since the string in
-		     the array could have zero length.  */
-		  *minlen = ssize_int (0);
-		}
-	    }
 	}
+    }
 
-      if (!val)
-	return false;
+  if (!val)
+    return false;
 
-      if (!*minlen
-	  || (type > 0
-	      && TREE_CODE (*minlen) == INTEGER_CST
-	      && TREE_CODE (val) == INTEGER_CST
-	      && tree_int_cst_lt (val, *minlen)))
-	*minlen = val;
+  /* Adjust the lower bound on the string length as necessary.  */
+  if (!*minlen
+      || (type > 0
+	  && TREE_CODE (*minlen) == INTEGER_CST
+	  && TREE_CODE (val) == INTEGER_CST
+	  && tree_int_cst_lt (val, *minlen)))
+    *minlen = val;
 
-      if (*maxlen)
+  if (*maxlen)
+    {
+      /* Adjust the more conservative bound if possible/necessary
+	 and fail otherwise.  */
+      if (type > 0)
 	{
-	  if (type > 0)
-	    {
-	      if (TREE_CODE (*maxlen) != INTEGER_CST
-		  || TREE_CODE (val) != INTEGER_CST)
-		return false;
-
-	      if (tree_int_cst_lt (*maxlen, val))
-		*maxlen = val;
-	      return true;
-	    }
-	  else if (simple_cst_equal (val, *maxlen) != 1)
+	  if (TREE_CODE (*maxlen) != INTEGER_CST
+	      || TREE_CODE (val) != INTEGER_CST)
 	    return false;
-	}
 
-      *maxlen = val;
-      return true;
+	  if (tree_int_cst_lt (*maxlen, val))
+	    *maxlen = val;
+	  return true;
+	}
+      else if (simple_cst_equal (val, *maxlen) != 1)
+	{
+	  /* Fail if the length of this ARG is different from that
+	     previously determined from another ARG.  */
+	  return false;
+	}
     }
 
+  *maxlen = val;
+  return true;
+}
+
+/* Obtain the minimum and maximum string length or minimum and maximum
+   value of ARG in LENGTH[0] and LENGTH[1], respectively.
+   If ARG is an SSA name variable, follow its use-def chains.  When
+   TYPE == 0, if LENGTH[1] is not equal to the length we determine or
+   if we are unable to determine the length or value, return false.
+   VISITED is a bitmap of visited variables.
+   TYPE is 0 if string length should be obtained, 1 for maximum string
+   length and 2 for maximum value ARG can have.
+   When FUZZY is non-zero and the length of a string cannot be determined,
+   the function instead considers as the maximum possible length the
+   size of a character array it may refer to.  If FUZZY is 2, it will handle
+   PHIs and COND_EXPRs optimistically, if we can determine string length
+   minimum and maximum, it will use the minimum from the ones where it
+   can be determined.
+   Set *FLEXP to true if the range of the string lengths has been
+   obtained from the upper bound of an array at the end of a struct.
+   Such an array may hold a string that's longer than its upper bound
+   due to it being used as a poor-man's flexible array member.
+   Pass NONSTR through to children.
+   ELTSIZE is 1 for normal single byte character strings, and 2 or
+   4 for wide characer strings.  ELTSIZE is by default 1.  */
+
+static bool
+get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
+		  int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
+{
+
+  if (TREE_CODE (arg) != SSA_NAME)
+    return get_range_strlen_tree (arg, length, visited, type, fuzzy, flexp,
+				  eltsize, nonstr);
+
   /* If ARG is registered for SSA update we cannot look at its defining
      statement.  */
   if (name_registered_for_update_p (arg))
@@ -1485,8 +1509,11 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
   if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (arg)))
     return true;
 
-  var = arg;
-  def_stmt = SSA_NAME_DEF_STMT (var);
+  tree var = arg;
+  gimple *def_stmt = SSA_NAME_DEF_STMT (var);
+
+  /* The minimum and maximum length.  */
+  tree *const maxlen = length + 1;
 
   switch (gimple_code (def_stmt))
     {
@@ -1550,7 +1577,6 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
         return false;
     }
 }
-
 /* Determine the minimum and maximum value or string length that ARG
    refers to and store each in the first two elements of MINMAXLEN.
    For expressions that point to strings of unknown lengths that are
commit a44f5ba24979f373fbcbc5dc25a43a5fd0cdc9c2
Author: Jeff Law <law@torsion.usersys.redhat.com>
Date:   Fri Dec 21 11:35:43 2018 -0500

            * gimple-fold.c (get_range_strlen_tree): Factored out of
            get_range_strlen.  Minor comment updates/additions.  Assert
            argument is not a simple SSA_NAME.
            (get_range_strlen): Call get_range_strlen_tree as appropriate.
            Minor comment updates/additions.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 65f87a3ddfa..15d43d25774 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2018-12-24  Martin Sebor  <msebor@redhat.com>
+
+	* gimple-fold.c (get_range_strlen_tree): Factored out of
+	get_range_strlen.  Minor comment updates/additions.  Assert
+	argument is not a simple SSA_NAME.
+	(get_range_strlen): Call get_range_strlen_tree as appropriate.
+	Minor comment updates/additions.
+
 2018-12-24  Jan Hubicka  <hubicka@ucw.cz>
 
 	* ipa-devirt.c (dump_targets): Cap number of targets printed.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b1dd4416567..4f84f0c0cc3 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -66,6 +66,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vector-builder.h"
 #include "tree-ssa-strlen.h"
 
+static bool get_range_strlen (tree, tree[2], bitmap *, int,
+		  int, bool *, unsigned, tree *);
+
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
    We can get declarations that are not possible to reference for various
@@ -1258,42 +1261,21 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
   return true;
 }
 
-
-/* Obtain the minimum and maximum string length or minimum and maximum
-   value of ARG in LENGTH[0] and LENGTH[1], respectively.
-   If ARG is an SSA name variable, follow its use-def chains.  When
-   TYPE == 0, if LENGTH[1] is not equal to the length we determine or
-   if we are unable to determine the length or value, return false.
-   VISITED is a bitmap of visited variables.
-   TYPE is 0 if string length should be obtained, 1 for maximum string
-   length and 2 for maximum value ARG can have.
-   When FUZZY is non-zero and the length of a string cannot be determined,
-   the function instead considers as the maximum possible length the
-   size of a character array it may refer to.  If FUZZY is 2, it will handle
-   PHIs and COND_EXPRs optimistically, if we can determine string length
-   minimum and maximum, it will use the minimum from the ones where it
-   can be determined.
-   Set *FLEXP to true if the range of the string lengths has been
-   obtained from the upper bound of an array at the end of a struct.
-   Such an array may hold a string that's longer than its upper bound
-   due to it being used as a poor-man's flexible array member.
-   Pass NONSTR through to children.
-   ELTSIZE is 1 for normal single byte character strings, and 2 or
-   4 for wide characer strings.  ELTSIZE is by default 1.  */
+/* Helper of get_range_strlen for ARG that is not an SSA_NAME.  */
 
 static bool
-get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
+get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
 		       int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
 {
-  tree var, val = NULL_TREE;
-  gimple *def_stmt;
+  gcc_assert (TREE_CODE (arg) != SSA_NAME);
  
   /* The minimum and maximum length.  */
   tree *const minlen = length;
   tree *const maxlen = length + 1;
 
-  if (TREE_CODE (arg) != SSA_NAME)
-    {
+  /* The length computed by this invocation of the function.  */
+  tree val = NULL_TREE;
+
   /* We can end up with &(*iftmp_1)[0] here as well, so handle it.  */
   if (TREE_CODE (arg) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
@@ -1328,6 +1310,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 
   if (type == 2)
     {
+      /* We are computing the maximum value (not string length).  */
       val = arg;
       if (TREE_CODE (val) != INTEGER_CST
 	  || tree_int_cst_sgn (val) < 0)
@@ -1378,6 +1361,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 
 	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
 			      integer_one_node);
+
 	  /* Set the minimum size to zero since the string in
 	     the array could have zero length.  */
 	  *minlen = ssize_int (0);
@@ -1417,6 +1401,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 	    return false;
 	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
 			     integer_one_node);
+
 	  /* Set the minimum size to zero since the string in
 	     the array could have zero length.  */
 	  *minlen = ssize_int (0);
@@ -1437,6 +1422,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 		return false;
 	      val = wide_int_to_tree (TREE_TYPE (val),
 				      wi::sub (wi::to_wide (val), 1));
+
 	      /* Set the minimum size to zero since the string in
 		 the array could have zero length.  */
 	      *minlen = ssize_int (0);
@@ -1447,6 +1433,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
   if (!val)
     return false;
 
+  /* Adjust the lower bound on the string length as necessary.  */
   if (!*minlen
       || (type > 0
 	  && TREE_CODE (*minlen) == INTEGER_CST
@@ -1456,6 +1443,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 
   if (*maxlen)
     {
+      /* Adjust the more conservative bound if possible/necessary
+	 and fail otherwise.  */
       if (type > 0)
 	{
 	  if (TREE_CODE (*maxlen) != INTEGER_CST
@@ -1467,12 +1456,47 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 	  return true;
 	}
       else if (simple_cst_equal (val, *maxlen) != 1)
+	{
+	  /* Fail if the length of this ARG is different from that
+	     previously determined from another ARG.  */
 	  return false;
 	}
+    }
 
   *maxlen = val;
   return true;
-    }
+}
+
+/* Obtain the minimum and maximum string length or minimum and maximum
+   value of ARG in LENGTH[0] and LENGTH[1], respectively.
+   If ARG is an SSA name variable, follow its use-def chains.  When
+   TYPE == 0, if LENGTH[1] is not equal to the length we determine or
+   if we are unable to determine the length or value, return false.
+   VISITED is a bitmap of visited variables.
+   TYPE is 0 if string length should be obtained, 1 for maximum string
+   length and 2 for maximum value ARG can have.
+   When FUZZY is non-zero and the length of a string cannot be determined,
+   the function instead considers as the maximum possible length the
+   size of a character array it may refer to.  If FUZZY is 2, it will handle
+   PHIs and COND_EXPRs optimistically, if we can determine string length
+   minimum and maximum, it will use the minimum from the ones where it
+   can be determined.
+   Set *FLEXP to true if the range of the string lengths has been
+   obtained from the upper bound of an array at the end of a struct.
+   Such an array may hold a string that's longer than its upper bound
+   due to it being used as a poor-man's flexible array member.
+   Pass NONSTR through to children.
+   ELTSIZE is 1 for normal single byte character strings, and 2 or
+   4 for wide characer strings.  ELTSIZE is by default 1.  */
+
+static bool
+get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
+		  int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
+{
+
+  if (TREE_CODE (arg) != SSA_NAME)
+    return get_range_strlen_tree (arg, length, visited, type, fuzzy, flexp,
+				  eltsize, nonstr);
 
   /* If ARG is registered for SSA update we cannot look at its defining
      statement.  */
@@ -1485,8 +1509,11 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
   if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (arg)))
     return true;
 
-  var = arg;
-  def_stmt = SSA_NAME_DEF_STMT (var);
+  tree var = arg;
+  gimple *def_stmt = SSA_NAME_DEF_STMT (var);
+
+  /* The minimum and maximum length.  */
+  tree *const maxlen = length + 1;
 
   switch (gimple_code (def_stmt))
     {
@@ -1550,7 +1577,6 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
         return false;
     }
 }
-
 /* Determine the minimum and maximum value or string length that ARG
    refers to and store each in the first two elements of MINMAXLEN.
    For expressions that point to strings of unknown lengths that are

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]