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;