From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2136) id E153A3870C01; Mon, 1 May 2023 06:34:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E153A3870C01 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1682922853; bh=GYJ+I2iigT4jrtJbD/fQ5ce3nhugE6hTJXIf1OJhyDE=; h=From:To:Subject:Date:From; b=R2gmxJJDLzfCnuvTBJfVpIVCpyXf1R8eCbswX1vQGEl3sVS6YqcWF3+O9XEikajY8 lVLFnZ5im1o6k8//pNXGjEyajwpXq3T6CSUx5cSHGGwnZf6h01Wfqzk8NaAX9nLnp0 8ilMNLquMJQKytr1xYa76hu+e8R5NowqbMtBHP70= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Aldy Hernandez To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-375] Replace vrp_val* with wide_ints. X-Act-Checkin: gcc X-Git-Author: Aldy Hernandez X-Git-Refname: refs/heads/master X-Git-Oldrev: cb779afeff204fdb278e55006ea7d269a4606d85 X-Git-Newrev: 8b2181a415fda05c48a13f915cc42214462d19cb Message-Id: <20230501063413.E153A3870C01@sourceware.org> Date: Mon, 1 May 2023 06:34:13 +0000 (GMT) List-Id: https://gcc.gnu.org/g:8b2181a415fda05c48a13f915cc42214462d19cb commit r14-375-g8b2181a415fda05c48a13f915cc42214462d19cb Author: Aldy Hernandez Date: Thu Feb 16 14:25:52 2023 +0100 Replace vrp_val* with wide_ints. This patch removes all uses of vrp_val_{min,max} in favor for a irange_val_* which are wide_int based. This will leave only one use of vrp_val_* which returns trees in range_of_ssa_name_with_loop_info() because it needs to work with non-integers (floats, etc). In a follow-up patch, this function will also be cleaned up such that vrp_val_* can be deleted. The functions min_limit and max_limit in range-op.cc are now useless as they're basically irange_val*. I didn't rename them yet to avoid churn. I'll do it in a later patch. gcc/ChangeLog: * gimple-range-fold.cc (adjust_pointer_diff_expr): Rewrite with irange_val*. (vrp_val_max): New. (vrp_val_min): New. * gimple-range-op.cc (cfn_strlen::fold_range): Use irange_val_*. * range-op.cc (max_limit): Same. (min_limit): Same. (plus_minus_ranges): Same. (operator_rshift::op1_range): Same. (operator_cast::inside_domain_p): Same. * value-range.cc (vrp_val_is_max): Delete. (vrp_val_is_min): Delete. (range_tests_misc): Use irange_val_*. * value-range.h (vrp_val_is_min): Delete. (vrp_val_is_max): Delete. (vrp_val_max): Delete. (irange_val_min): New. (vrp_val_min): Delete. (irange_val_max): New. * vr-values.cc (check_for_binary_op_overflow): Use irange_val_*. Diff: --- gcc/gimple-range-fold.cc | 40 ++++++++++++++++++++++++++++++++++++---- gcc/gimple-range-op.cc | 8 +++----- gcc/range-op.cc | 19 ++++++++----------- gcc/value-range.cc | 37 ++++++------------------------------- gcc/value-range.h | 41 ++++++++--------------------------------- gcc/vr-values.cc | 48 +++++++++++++++++------------------------------- 6 files changed, 78 insertions(+), 115 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 62875a35038..1b76e6e02a3 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -360,10 +360,10 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt) && vrp_operand_equal_p (op1, gimple_call_arg (call, 0)) && integer_zerop (gimple_call_arg (call, 1))) { - tree max = vrp_val_max (ptrdiff_type_node); - unsigned prec = TYPE_PRECISION (TREE_TYPE (max)); - wide_int wmaxm1 = wi::to_wide (max, prec) - 1; - res.intersect (int_range<2> (TREE_TYPE (max), wi::zero (prec), wmaxm1)); + wide_int maxm1 = irange_val_max (ptrdiff_type_node) - 1; + res.intersect (int_range<2> (ptrdiff_type_node, + wi::zero (TYPE_PRECISION (ptrdiff_type_node)), + maxm1)); } } @@ -966,6 +966,38 @@ tree_upper_bound (const vrange &r, tree type) return NULL; } +// Return the maximum value for TYPE. + +static inline tree +vrp_val_max (const_tree type) +{ + if (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type)) + return wide_int_to_tree (const_cast (type), irange_val_max (type)); + if (frange::supports_p (type)) + { + REAL_VALUE_TYPE r = frange_val_max (type); + return build_real (const_cast (type), r); + } + return NULL_TREE; +} + +// Return the minimum value for TYPE. + +static inline tree +vrp_val_min (const_tree type) +{ + if (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type)) + return wide_int_to_tree (const_cast (type), irange_val_min (type)); + if (frange::supports_p (type)) + { + REAL_VALUE_TYPE r = frange_val_min (type); + return build_real (const_cast (type), r); + } + return NULL_TREE; +} + // If SCEV has any information about phi node NAME, return it as a range in R. void diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 29c7c776a2c..3aef8357d8d 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -900,15 +900,13 @@ public: virtual bool fold_range (irange &r, tree type, const irange &, const irange &, relation_trio) const { - tree max = vrp_val_max (ptrdiff_type_node); - wide_int wmax - = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); + wide_int max = irange_val_max (ptrdiff_type_node); // To account for the terminating NULL, the maximum length // is one less than the maximum array size, which in turn // is one less than PTRDIFF_MAX (or SIZE_MAX where it's // smaller than the former type). // FIXME: Use max_object_size() - 1 here. - r.set (type, wi::zero (TYPE_PRECISION (type)), wmax - 2); + r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2); return true; } } op_cfn_strlen; @@ -936,7 +934,7 @@ public: wi::shwi (m_is_pos ? 0 : 1, TYPE_PRECISION (type)), size ? wi::shwi (size - m_is_pos, TYPE_PRECISION (type)) - : wi::to_wide (vrp_val_max (type))); + : irange_val_max (type)); return true; } private: diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 224a561c170..fc0eef998e4 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -97,7 +97,7 @@ update_known_bitmask (irange &r, tree_code code, static inline wide_int max_limit (const_tree type) { - return wi::max_value (TYPE_PRECISION (type) , TYPE_SIGN (type)); + return irange_val_max (type); } // Return the lower limit for a type. @@ -105,7 +105,7 @@ max_limit (const_tree type) static inline wide_int min_limit (const_tree type) { - return wi::min_value (TYPE_PRECISION (type) , TYPE_SIGN (type)); + return irange_val_min (type); } // Return false if shifting by OP is undefined behavior. Otherwise, return @@ -1463,14 +1463,14 @@ plus_minus_ranges (irange &r_ov, irange &r_normal, const irange &offset, { // [ 0 , INF - OFF] lb = wi::zero (prec); - ub = wi::sub (wi::to_wide (vrp_val_max (type)), off, UNSIGNED, &ov); + ub = wi::sub (irange_val_max (type), off, UNSIGNED, &ov); kind = VREL_GT; } else { // [ OFF, INF ] lb = off; - ub = wi::to_wide (vrp_val_max (type)); + ub = irange_val_max (type); kind = VREL_LT; } int_range<2> normal_range (type, lb, ub); @@ -2594,13 +2594,10 @@ operator_rshift::op1_range (irange &r, // OP1 is anything from 0011 1000 to 0011 1111. That is, a // range from LHS<<3 plus a mask of the 3 bits we shifted on the // right hand side (0x07). - tree mask = fold_build1 (BIT_NOT_EXPR, type, - fold_build2 (LSHIFT_EXPR, type, - build_minus_one_cst (type), - wide_int_to_tree (op2.type (), shift))); + wide_int mask = wi::bit_not (wi::lshift (wi::minus_one (prec), shift)); int_range_max mask_range (type, wi::zero (TYPE_PRECISION (type)), - wi::to_wide (mask)); + mask); op_plus.fold_range (ub, type, lb, mask_range); r = lb; r.union_ (ub); @@ -2731,8 +2728,8 @@ operator_cast::inside_domain_p (const wide_int &min, const wide_int &max, const irange &range) const { - wide_int domain_min = wi::to_wide (vrp_val_min (range.type ())); - wide_int domain_max = wi::to_wide (vrp_val_max (range.type ())); + wide_int domain_min = irange_val_min (range.type ()); + wide_int domain_max = irange_val_max (range.type ()); signop domain_sign = TYPE_SIGN (range.type ()); return (wi::le_p (min, domain_max, domain_sign) && wi::le_p (max, domain_max, domain_sign) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index f2148722a3a..cf694ccaa28 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -1990,31 +1990,6 @@ debug (const value_range &vr) fprintf (stderr, "\n"); } -/* Return whether VAL is equal to the maximum value of its type. - We can't do a simple equality comparison with TYPE_MAX_VALUE because - C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE - is not == to the integer constant with the same value in the type. */ - -bool -vrp_val_is_max (const_tree val) -{ - tree type_max = vrp_val_max (TREE_TYPE (val)); - return (val == type_max - || (type_max != NULL_TREE - && operand_equal_p (val, type_max, 0))); -} - -/* Return whether VAL is equal to the minimum value of its type. */ - -bool -vrp_val_is_min (const_tree val) -{ - tree type_min = vrp_val_min (TREE_TYPE (val)); - return (val == type_min - || (type_min != NULL_TREE - && operand_equal_p (val, type_min, 0))); -} - /* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */ bool @@ -2369,11 +2344,11 @@ range_tests_misc () // Test 1-bit signed integer union. // [-1,-1] U [0,0] = VARYING. tree one_bit_type = build_nonstandard_integer_type (1, 0); - tree one_bit_min = vrp_val_min (one_bit_type); - tree one_bit_max = vrp_val_max (one_bit_type); + wide_int one_bit_min = irange_val_min (one_bit_type); + wide_int one_bit_max = irange_val_max (one_bit_type); { - int_range<2> min = tree_range (one_bit_min, one_bit_min); - int_range<2> max = tree_range (one_bit_max, one_bit_max); + int_range<2> min = int_range<2> (one_bit_type, one_bit_min, one_bit_min); + int_range<2> max = int_range<2> (one_bit_type, one_bit_max, one_bit_max); max.union_ (min); ASSERT_TRUE (max.varying_p ()); } @@ -2382,8 +2357,8 @@ range_tests_misc () // Test inversion of 1-bit signed integers. { - int_range<2> min = tree_range (one_bit_min, one_bit_min); - int_range<2> max = tree_range (one_bit_max, one_bit_max); + int_range<2> min = int_range<2> (one_bit_type, one_bit_min, one_bit_min); + int_range<2> max = int_range<2> (one_bit_type, one_bit_max, one_bit_max); int_range<2> t; t = min; t.invert (); diff --git a/gcc/value-range.h b/gcc/value-range.h index 633a234d41f..b040e2f254f 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -635,8 +635,6 @@ Value_Range::supports_type_p (const_tree type) extern value_range_kind get_legacy_range (const irange &, tree &min, tree &max); extern void dump_value_range (FILE *, const vrange *); -extern bool vrp_val_is_min (const_tree); -extern bool vrp_val_is_max (const_tree); extern bool vrp_operand_equal_p (const_tree, const_tree); inline REAL_VALUE_TYPE frange_val_min (const_tree type); inline REAL_VALUE_TYPE frange_val_max (const_tree type); @@ -952,41 +950,18 @@ contains_zero_p (const irange &r) return r.contains_p (zero); } -// Return the maximum value for TYPE. - -inline tree -vrp_val_max (const_tree type) +inline wide_int +irange_val_min (const_tree type) { - if (INTEGRAL_TYPE_P (type)) - return TYPE_MAX_VALUE (type); - if (POINTER_TYPE_P (type)) - { - wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); - return wide_int_to_tree (const_cast (type), max); - } - if (frange::supports_p (type)) - { - REAL_VALUE_TYPE r = frange_val_max (type); - return build_real (const_cast (type), r); - } - return NULL_TREE; + gcc_checking_assert (irange::supports_p (type)); + return wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)); } -// Return the minimum value for TYPE. - -inline tree -vrp_val_min (const_tree type) +inline wide_int +irange_val_max (const_tree type) { - if (INTEGRAL_TYPE_P (type)) - return TYPE_MIN_VALUE (type); - if (POINTER_TYPE_P (type)) - return build_zero_cst (const_cast (type)); - if (frange::supports_p (type)) - { - REAL_VALUE_TYPE r = frange_val_min (type); - return build_real (const_cast (type), r); - } - return NULL_TREE; + gcc_checking_assert (irange::supports_p (type)); + return wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); } inline diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 49ae324419a..31df6b85ce6 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -103,34 +103,16 @@ check_for_binary_op_overflow (range_query *query, tree op0, tree op1, bool *ovf, gimple *s = NULL) { value_range vr0, vr1; - if (!query->range_of_expr (vr0, op0, s)) + if (!query->range_of_expr (vr0, op0, s) || vr0.undefined_p ()) vr0.set_varying (TREE_TYPE (op0)); - if (!query->range_of_expr (vr1, op1, s)) + if (!query->range_of_expr (vr1, op1, s) || vr1.undefined_p ()) vr1.set_varying (TREE_TYPE (op1)); - tree vr0min, vr0max, vr1min, vr1max; - if (vr0.undefined_p () || vr0.varying_p ()) - { - vr0min = vrp_val_min (TREE_TYPE (op0)); - vr0max = vrp_val_max (TREE_TYPE (op0)); - } - else - { - tree type = vr0.type (); - vr0min = wide_int_to_tree (type, vr0.lower_bound ()); - vr0max = wide_int_to_tree (type, vr0.upper_bound ()); - } - if (vr1.undefined_p () || vr1.varying_p ()) - { - vr1min = vrp_val_min (TREE_TYPE (op1)); - vr1max = vrp_val_max (TREE_TYPE (op1)); - } - else - { - tree type = vr1.type (); - vr1min = wide_int_to_tree (type, vr1.lower_bound ()); - vr1max = wide_int_to_tree (type, vr1.upper_bound ()); - } + tree vr0min = wide_int_to_tree (TREE_TYPE (op0), vr0.lower_bound ()); + tree vr0max = wide_int_to_tree (TREE_TYPE (op0), vr0.upper_bound ()); + tree vr1min = wide_int_to_tree (TREE_TYPE (op1), vr1.lower_bound ()); + tree vr1max = wide_int_to_tree (TREE_TYPE (op1), vr1.upper_bound ()); + *ovf = arith_overflowed_p (subcode, type, vr0min, subcode == MINUS_EXPR ? vr1max : vr1min); if (arith_overflowed_p (subcode, type, vr0max, @@ -152,10 +134,12 @@ check_for_binary_op_overflow (range_query *query, widest_int wmin, wmax; widest_int w[4]; int i; - w[0] = wi::to_widest (vr0min); - w[1] = wi::to_widest (vr0max); - w[2] = wi::to_widest (vr1min); - w[3] = wi::to_widest (vr1max); + signop sign0 = TYPE_SIGN (TREE_TYPE (op0)); + signop sign1 = TYPE_SIGN (TREE_TYPE (op1)); + w[0] = widest_int::from (vr0.lower_bound (), sign0); + w[1] = widest_int::from (vr0.upper_bound (), sign0); + w[2] = widest_int::from (vr1.lower_bound (), sign1); + w[3] = widest_int::from (vr1.upper_bound (), sign1); for (i = 0; i < 4; i++) { widest_int wt; @@ -186,8 +170,10 @@ check_for_binary_op_overflow (range_query *query, } /* The result of op0 CODE op1 is known to be in range [wmin, wmax]. */ - widest_int wtmin = wi::to_widest (vrp_val_min (type)); - widest_int wtmax = wi::to_widest (vrp_val_max (type)); + widest_int wtmin + = widest_int::from (irange_val_min (type), TYPE_SIGN (type)); + widest_int wtmax + = widest_int::from (irange_val_max (type), TYPE_SIGN (type)); /* If all values in [wmin, wmax] are smaller than [wtmin, wtmax] or all are larger than [wtmin, wtmax], the arithmetic operation will always overflow. */