Attached is revision 3 of the patch incorporating your
determine_value_range function with the requested changes.

Martin
PR testsuite/85888 - New test case c-c++-common/attr-nonstring-6.c from r260541 fails with excess errors

gcc/ChangeLog:

	PR testsuite/85888
	* builtins.c (expand_builtin_strncmp): Call expand_call with
	the original CALL_EXPR since no stabilization has been done.
	* gcc/tree-ssanames.c (get_range_info): Call determine_value_range
	for arguments other than SSA_NAME.
	* calls.c (get_size_range): Call get_range_info even for non-SSA
	arguments.
	* tree-vrp.h (determine_value_range): Declared new function.
	* tree-vrp.c (determine_value_range_1, determine_value_range): New.

diff --git a/gcc/calls.c b/gcc/calls.c
index 35bcff7..f6bf3a6 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1319,7 +1319,7 @@ get_size_range (tree exp, tree range[2], bool allow_zero /* = false */)
   wide_int min, max;
   enum value_range_type range_type;
 
-  if (TREE_CODE (exp) == SSA_NAME && integral)
+  if (integral)
     range_type = get_range_info (exp, &min, &max);
   else
     range_type = VR_VARYING;
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 6cce43b..b5d257b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -398,25 +398,30 @@ set_range_info (tree name, enum value_range_type range_type,
 
 
 /* Gets range information MIN, MAX and returns enum value_range_type
-   corresponding to tree ssa_name NAME.  enum value_range_type returned
-   is used to determine if MIN and MAX are valid values.  */
+   corresponding to expression EXPR.  Returned value_range_type is
+   used to determine if MIN and MAX are valid values.  */
 
 enum value_range_type
-get_range_info (const_tree name, wide_int *min, wide_int *max)
+get_range_info (const_tree expr, wide_int *min, wide_int *max)
 {
-  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (expr)));
   gcc_assert (min && max);
-  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+  if (TREE_CODE (expr) == SSA_NAME)
+    {
+      range_info_def *ri = SSA_NAME_RANGE_INFO (expr);
 
-  /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
-     with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
-  if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (name)))
-	      > 2 * HOST_BITS_PER_WIDE_INT))
-    return VR_VARYING;
+      /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
+	 with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
+      if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (expr)))
+		  > 2 * HOST_BITS_PER_WIDE_INT))
+	return VR_VARYING;
+
+      *min = ri->get_min ();
+      *max = ri->get_max ();
+      return SSA_NAME_RANGE_TYPE (expr);
+    }
 
-  *min = ri->get_min ();
-  *max = ri->get_max ();
-  return SSA_NAME_RANGE_TYPE (name);
+  return determine_value_range (const_cast<tree> (expr), min, max);
 }
 
 /* Set nonnull attribute to pointer NAME.  */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 6c482dd..1b1084b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -7130,3 +7130,62 @@ make_pass_vrp (gcc::context *ctxt)
 {
   return new pass_vrp (ctxt);
 }
+
+
+/* Worker for determine_value_range.  */
+
+static void
+determine_value_range_1 (value_range *vr, tree expr)
+{
+  if (BINARY_CLASS_P (expr))
+    {
+      value_range vr0 = VR_INITIALIZER, vr1 = VR_INITIALIZER;
+      determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0));
+      determine_value_range_1 (&vr1, TREE_OPERAND (expr, 1));
+      extract_range_from_binary_expr_1 (vr, TREE_CODE (expr), TREE_TYPE (expr),
+					&vr0, &vr1);
+    }
+  else if (UNARY_CLASS_P (expr))
+    {
+      value_range vr0 = VR_INITIALIZER;
+      determine_value_range_1 (&vr0, TREE_OPERAND (expr, 0));
+      extract_range_from_unary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
+				     &vr0, TREE_TYPE (TREE_OPERAND (expr, 0)));
+    }
+  else if (TREE_CODE (expr) == INTEGER_CST)
+    set_value_range_to_value (vr, expr, NULL);
+  else
+    {
+      value_range_type kind;
+      wide_int min, max;
+      /* For SSA names try to extract range info computed by VRP.  Otherwise
+	 fall back to varying.  */
+      if (TREE_CODE (expr) == SSA_NAME
+	  && INTEGRAL_TYPE_P (TREE_TYPE (expr))
+	  && (kind = get_range_info (expr, &min, &max)) != VR_VARYING)
+	set_value_range (vr, kind, wide_int_to_tree (TREE_TYPE (expr), min),
+			 wide_int_to_tree (TREE_TYPE (expr), max), NULL);
+      else
+	set_value_range_to_varying (vr);
+    }
+}
+
+/* Compute a value-range for EXPR and set it in *MIN and *MAX.  Return
+   determined the range type.  */
+
+value_range_type
+determine_value_range (tree expr, wide_int *min, wide_int *max)
+{
+  value_range vr = VR_INITIALIZER;
+  determine_value_range_1 (&vr, expr);
+  if ((vr.type == VR_RANGE
+       || vr.type == VR_ANTI_RANGE)
+      && !symbolic_range_p (&vr))
+    {
+      *min = wi::to_wide (vr.min);
+      *max = wi::to_wide (vr.max);
+      return vr.type;
+    }
+
+  return VR_VARYING;
+}
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index d8f60be..608ca56 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -119,7 +119,7 @@ extern bool range_int_cst_singleton_p (value_range *);
 extern int value_inside_range (tree, tree, tree);
 extern tree get_single_symbol (tree, bool *, tree *);
 extern void maybe_set_nonzero_bits (edge, tree);
-
+extern value_range_type determine_value_range (tree, wide_int *, wide_int *);
 
 struct switch_update {
   gswitch *stmt;

Reply via email to