diff options
author | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-27 04:07:23 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-27 04:07:23 +0000 |
commit | 7b6bb739b6651354dbc7173f9758c32217a9b7d4 (patch) | |
tree | 4178f4b0a073f34b85c57bc7f6ce049afc51ca6d | |
parent | 06ebd7a521dee8ac84a1eaf4df735c6b72298d33 (diff) | |
download | gcc-7b6bb739b6651354dbc7173f9758c32217a9b7d4.zip gcc-7b6bb739b6651354dbc7173f9758c32217a9b7d4.tar.gz gcc-7b6bb739b6651354dbc7173f9758c32217a9b7d4.tar.bz2 |
Introduce USE_IRANGE and add constructors to seamlessly convert between
irange and value_range_base.
From-SVN: r272727
-rw-r--r-- | gcc/calls.c | 2 | ||||
-rw-r--r-- | gcc/function-tests.c | 2 | ||||
-rw-r--r-- | gcc/gimple-ssa-warn-restrict.c | 3 | ||||
-rw-r--r-- | gcc/range.c | 65 | ||||
-rw-r--r-- | gcc/range.h | 52 | ||||
-rw-r--r-- | gcc/selftest.h | 2 | ||||
-rw-r--r-- | gcc/ssa-range.cc | 6 | ||||
-rw-r--r-- | gcc/ssa.h | 1 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 52 | ||||
-rw-r--r-- | gcc/tree-vrp.h | 54 | ||||
-rw-r--r-- | gcc/vr-values.c | 17 |
11 files changed, 146 insertions, 110 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 79cb8d0..a58d135 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1260,7 +1260,7 @@ get_size_range (tree exp, tree range[2], bool allow_zero /* = false */, { wide_int min, max; enum value_range_kind kind = get_range_info (exp, &min, &max); - r = value_range_to_irange (exptype, kind, min, max); + r = irange (kind, exptype, min, max); } else if (!call || TREE_CODE (exp) != SSA_NAME || !integral || !ranger.range_of_expr (r, exp, call) diff --git a/gcc/function-tests.c b/gcc/function-tests.c index bb96ca2..be3f67f 100644 --- a/gcc/function-tests.c +++ b/gcc/function-tests.c @@ -579,7 +579,7 @@ test_iranges () tree fndecl = build_trivial_high_gimple_function (); function *fun = DECL_STRUCT_FUNCTION (fndecl); push_cfun (fun); - irange_tests (); + range_tests (); pop_cfun (); } diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 6701e2d8..9b7e910 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -31,6 +31,7 @@ #include "ssa.h" #include "gimple-pretty-print.h" #include "ssa-range.h" +#include "tree-vrp.h" #include "gimple-ssa-warn-restrict.h" #include "diagnostic-core.h" #include "fold-const.h" @@ -301,7 +302,7 @@ ranger_get_range_info (gimple *stmt, tree ssa, wide_int *min, wide_int *max) if (r.undefined_p ()) return VR_UNDEFINED; - value_range_base vr = irange_to_value_range (r); + value_range_base vr = r; *min = wi::to_wide (vr.min ()); *max = wi::to_wide (vr.max ()); return vr.kind (); diff --git a/gcc/range.c b/gcc/range.c index 7ff2475..8864a56 100644 --- a/gcc/range.c +++ b/gcc/range.c @@ -52,9 +52,8 @@ range_compatible_p (tree t1, tree t2) bool irange::operator== (const irange &r) const { - /* Special case UNDEFINED, because the value_range_base - implementation may not have a type for a freshly initialized - UNDEFINED. */ + // Special case this because a freshly initialized range may be + // typeless. if (undefined_p ()) return r.undefined_p (); @@ -88,7 +87,7 @@ range_from_ssa (tree ssa) return irange (type); wide_int min, max; enum value_range_kind kind = get_range_info (ssa, &min, &max); - return value_range_to_irange (type, kind, min, max); + return irange (kind, type, min, max); } // This function returns a range for tree node EXPR in R. Return @@ -208,7 +207,7 @@ range_negatives (tree type) return r; } -#if !IRANGE_WITH_VALUE_RANGE +#if USE_IRANGE // Standalone irange implementation. // Subtract 1 from X and set OVERFLOW if the operation overflows. @@ -231,10 +230,16 @@ void irange::init (tree type, const wide_int &lbound, const wide_int &ubound, value_range_kind rt) { - // Even though we accept a full value_range_kind, we *ONLY* use it to - // distinguish a plain range from an inverse range. - gcc_checking_assert (rt == VR_RANGE || rt == VR_ANTI_RANGE); - + if (rt == VR_UNDEFINED) + { + set_undefined (type); + return; + } + if (rt == VR_VARYING) + { + set_varying (type); + return; + } gcc_checking_assert (irange::supports_type_p (type)); gcc_checking_assert (TYPE_PRECISION (type) == lbound.get_precision ()); gcc_checking_assert (lbound.get_precision () == ubound.get_precision ()); @@ -287,7 +292,6 @@ irange::irange (tree type) irange::irange (value_range_kind rt, tree type, const wide_int &lbound, const wide_int &ubound) { - gcc_checking_assert (rt == VR_RANGE || rt == VR_ANTI_RANGE); init (type, lbound, ubound, rt); } @@ -980,7 +984,7 @@ irange::singleton_p (tree *result) const return false; } -// Convert irange to a value_range_kind. +// Convert irange to a value_range. value_range_base irange_to_value_range (const irange &r) @@ -1041,24 +1045,9 @@ irange_to_value_range (const irange &r) return vr; } -// Convert a value_range to an irange and store it in R. - -irange -value_range_to_irange (tree type, enum value_range_kind kind, - const wide_int &min, const wide_int &max) -{ - gcc_checking_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)); - irange r; - if (kind == VR_VARYING || kind == VR_UNDEFINED) - r.set_varying (type); - else - r = irange (kind, type, min, max); - return r; -} - -// Same as above, but takes an entire value_range instead of piecemeal. +// Convert a value_range into an irange. -irange +static irange value_range_to_irange (const value_range_base &vr) { tree type = vr.type (); @@ -1070,16 +1059,20 @@ value_range_to_irange (const value_range_base &vr) r.set_undefined (type); return r; } - return value_range_to_irange (type, vr.kind (), - wi::to_wide (vr.min ()), - wi::to_wide (vr.max ())); + return irange (vr.kind (), vr.min (), vr.max ()); } -#endif // !IRANGE_WITH_VALUE_RANGE + +irange::irange (const value_range_base &vr) +{ + *this = value_range_to_irange (vr); +} + +#endif // USE_IRANGE #if CHECKING_P #include "stor-layout.h" -// Ideally this should go in namespace selftest, but irange_tests +// Ideally this should go in namespace selftest, but range_tests // needs to be a friend of class irange so it can access // irange::m_max_pairs. @@ -1104,7 +1097,7 @@ value_range_to_irange (const value_range_base &vr) // Run all of the selftests within this file. void -irange_tests () +range_tests () { tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1); irange i1, i2, i3; @@ -1576,11 +1569,11 @@ irange_tests () // Test irange / value_range conversion functions. r0 = irange (VR_ANTI_RANGE, INT (10), INT (20)); - value_range_base vr = irange_to_value_range (r0); + value_range_base vr = r0; ASSERT_TRUE (vr.kind () == VR_ANTI_RANGE); ASSERT_TRUE (wi::eq_p (10, wi::to_wide (vr.min ())) && wi::eq_p (20, wi::to_wide (vr.max ()))); - r1 = value_range_to_irange (vr); + r1 = vr; ASSERT_TRUE (r0 == r1); } diff --git a/gcc/range.h b/gcc/range.h index ec13c40..9205d0b 100644 --- a/gcc/range.h +++ b/gcc/range.h @@ -1,5 +1,5 @@ /* Header file for range analysis. - Copyright (C) 2017 Free Software Foundation, Inc. + Copyright (C) 2017-2019 Free Software Foundation, Inc. Contributed by Aldy Hernandez <aldyh@redhat.com>. This file is part of GCC. @@ -21,13 +21,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_RANGE_H #define GCC_RANGE_H -// Enable this to implement irange piggybacking on value_range. -#define IRANGE_WITH_VALUE_RANGE 0 - -#if IRANGE_WITH_VALUE_RANGE -typedef value_range_base irange; -typedef value_range_storage irange_storage; -#else +#if USE_IRANGE // This is the standalone irange implementation. class irange_storage; @@ -57,7 +51,7 @@ class irange_storage; class irange { friend class irange_storage; - friend void irange_tests (); + friend void range_tests (); public: irange (); @@ -67,6 +61,10 @@ class irange irange (value_range_kind, tree, tree); irange (tree, tree); irange (tree type, const irange_storage *); +#if USE_IRANGE + /* Only for branch. */ + irange (const value_range_base &); +#endif static bool supports_type_p (tree type); static bool supports_ssa_p (tree ssa); @@ -298,26 +296,6 @@ irange_storage::empty_pair_p (unsigned i, unsigned j, tree type) const && trailing_bounds[j] == wi::zero (precision)); } -#endif // IRANGE_WITH_VALUE_RANGE - -// Common code between the alternate irange implementations. - -irange range_zero (tree type); -irange range_nonzero (tree type); -irange range_intersect (const irange &, const irange &); -irange range_union (const irange &, const irange &); -irange range_invert (const irange &); -irange range_from_ssa (tree ssa); -irange range_positives (tree type); -irange range_negatives (tree type); -irange value_range_to_irange (const value_range_base &); -irange value_range_to_irange (tree type, enum value_range_kind kind, - const wide_int &, const wide_int &); -value_range_base irange_to_value_range (const irange &); - -// Extract a range from a tree node. -bool get_tree_range (irange &r, tree expr); - // Return true if TYPE is a valid type for irange to operate on. // Otherwise return FALSE. @@ -353,4 +331,20 @@ irange::supports_p (tree expr) return supports_type_p (TREE_TYPE (expr)); } +value_range_base irange_to_value_range (const irange &); +#endif // USE_IRANGE + +// Common code between the alternate irange implementations. + +irange range_zero (tree type); +irange range_nonzero (tree type); +irange range_intersect (const irange &, const irange &); +irange range_union (const irange &, const irange &); +irange range_invert (const irange &); +irange range_from_ssa (tree ssa); +irange range_positives (tree type); +irange range_negatives (tree type); + +// Extract a range from a tree node. +bool get_tree_range (irange &r, tree expr); #endif // GCC_RANGE_H diff --git a/gcc/selftest.h b/gcc/selftest.h index bb82453..e18d4ef 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -259,7 +259,7 @@ extern int num_passes; /* This is outside of the selftest namespace because it's a friend of class irange. */ -extern void irange_tests (); +extern void range_tests (); /* Macros for writing tests. */ diff --git a/gcc/ssa-range.cc b/gcc/ssa-range.cc index 3691988..cc83f01 100644 --- a/gcc/ssa-range.cc +++ b/gcc/ssa-range.cc @@ -954,7 +954,7 @@ global_ranger::export_global_ranges () if (!dbg_cnt (ranger_export_count)) return; - value_range_base vr = irange_to_value_range (r); + value_range_base vr = r; set_range_info (name, vr); if (dump_file) { @@ -1122,12 +1122,12 @@ loop_ranger::adjust_phi_with_loop_info (irange &r, gphi *phi) if (l && l->header == gimple_bb (phi)) { tree phi_result = PHI_RESULT (phi); - value_range vr = irange_to_value_range (r); + value_range_base vr = r; m_vr_values->adjust_range_with_scev (&vr, l, phi, phi_result); if (vr.constant_p ()) { irange old = r; - r = value_range_to_irange (vr); + r = vr; if (old != r && dump_file && (dump_flags & TDF_DETAILS)) { @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "gimple-ssa.h" #include "tree-vrp.h" +#include "range.h" #include "tree-ssanames.h" #include "tree-phinodes.h" #include "ssa-iterators.h" diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 9f36407..f102a89 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2464,6 +2464,7 @@ range_ops_fold_binary_expr (value_range_base *vr, vr0.set_varying (expr_type); else if (vr1.undefined_p ()) vr1.set_varying (expr_type); + /* Handle symbolics. Worth moving into range-ops?? */ if ((code == PLUS_EXPR || code == MINUS_EXPR) && (vr0.symbolic_p () || vr1.symbolic_p ())) @@ -2475,12 +2476,17 @@ range_ops_fold_binary_expr (value_range_base *vr, } if (handle_symbolics_in_pointer_plus_expr (vr, code, expr_type, &vr0, &vr1)) return; + /* Do the range-ops dance. */ + value_range_base n0 = normalize_for_range_ops (vr0); + value_range_base n1 = normalize_for_range_ops (vr1); +#if USE_IRANGE irange ir; - irange ir0 = value_range_to_irange (normalize_for_range_ops (vr0)); - irange ir1 = value_range_to_irange (normalize_for_range_ops (vr1)); - op->fold_range (ir, ir0, ir1); - *vr = irange_to_value_range (ir); + op->fold_range (ir, n0, n1); + *vr = ir; +#else + op->fold_range (*vr, n0, n1); +#endif } /* Fold a unary expression of a value_range with range-ops. */ @@ -2503,6 +2509,7 @@ range_ops_fold_unary_expr (value_range_base *vr, vr->set_undefined (expr_type); return; } + /* Handle symbolics. Worth moving into range-ops?? */ if (code == NEGATE_EXPR && vr0->symbolic_p ()) { @@ -2532,12 +2539,18 @@ range_ops_fold_unary_expr (value_range_base *vr, vr->set_varying (expr_type); return; } + + /* Do the range-ops dance. */ + value_range_base n0 = normalize_for_range_ops (*vr0); + value_range_base n1 (expr_type); +#if USE_IRANGE irange ir; - irange ir0 = value_range_to_irange (normalize_for_range_ops (*vr0)); - irange ir1 (expr_type); - op->fold_range (ir, ir0, ir1); - *vr = irange_to_value_range (ir); + op->fold_range (ir, n0, n1); + *vr = ir; +#else + op->fold_range (*vr, n0, n1); +#endif } /* Generic folding of a binary expression between two value_ranges. @@ -7554,23 +7567,10 @@ determine_value_range (tree expr, wide_int *min, wide_int *max) return VR_VARYING; } -#if IRANGE_WITH_VALUE_RANGE -irange -value_range_to_irange (const value_range_base &vr) -{ - return vr; -} - -irange -value_range_to_irange (tree type, enum value_range_kind kind, - const wide_int &min, const wide_int &max) -{ - return irange (kind, type, min, max); -} - -value_range_base -irange_to_value_range (const irange &ir) +#if USE_IRANGE +/* Only for branch. */ +value_range_base::value_range_base (const irange &ir) { - return ir; + *this = irange_to_value_range (ir); } -#endif // IRANGE_TO_VALUE_RANGE +#endif // USE_IRANGE diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index 189b896..b186c25 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -22,12 +22,24 @@ along with GCC; see the file COPYING3. If not see class value_range_storage; +// Set to one if irange is a standalone class containing multiple +// sub-ranges, or zero if irange is just value_range_base underneath. +#define USE_IRANGE 1 + +#if USE_IRANGE +class irange; +#else +class value_range_base; +typedef value_range_base irange; +typedef value_range_storage irange_storage; +#endif + /* Range of values that can be associated with an SSA_NAME after VRP has executed. */ class GTY((for_user)) value_range_base { friend class value_range_storage; - friend void irange_tests (); + friend void range_tests (); public: value_range_base (); value_range_base (value_range_kind, tree, tree); @@ -37,6 +49,10 @@ public: value_range_base (tree type, const wide_int &, const wide_int &); value_range_base (tree type, const value_range_storage *); value_range_base (tree type); +#if USE_IRANGE + /* Only for branch. */ + value_range_base (const irange &); +#endif void set (value_range_kind, tree, tree); void set (tree); @@ -84,7 +100,6 @@ public: void invert (); void dump () const; value_range_base normalize_symbolics () const; - // FIXME: Perhaps rewrite the irange versions to use pointers instead. void union_ (const value_range_base &); void intersect (const value_range_base &); @@ -288,6 +303,41 @@ struct assert_info tree expr; }; +// Return true if TYPE is a valid type for value_range to operate on. +// Otherwise return FALSE. + +inline bool +value_range_base::supports_type_p (tree type) +{ + if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) + return type; + return NULL; +} + +// Return true if SSA is a valid ssa_name for value_range to operate on. +// Otherwise return FALSE. + +inline bool +value_range_base::supports_ssa_p (tree ssa) +{ + if (!SSA_NAME_IS_VIRTUAL_OPERAND (ssa)) + return supports_type_p (TREE_TYPE (ssa)); + return false; +} + +// Return true if EXPR is a valid tree expression for value_range to +// operate on. Otherwise return FALSE. + +inline bool +value_range_base::supports_p (tree expr) +{ + if (TYPE_P (expr)) + return supports_type_p (expr); + else if (TREE_CODE (expr) == SSA_NAME) + return supports_ssa_p (expr); + return supports_type_p (TREE_TYPE (expr)); +} + extern void register_edge_assert_for (tree, edge, enum tree_code, tree, tree, vec<assert_info> &); extern bool stmt_interesting_for_vrp (gimple *); diff --git a/gcc/vr-values.c b/gcc/vr-values.c index a4fb83e..0d80f1e 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -73,7 +73,7 @@ vr_values::get_irange (tree op, gimple *stmt ATTRIBUTE_UNUSED) && !vr->constant_p ())) return irange (TREE_TYPE (op)); - return value_range_to_irange (*vr); + return *vr; } /* Set value range VR to a non-negative range of type TYPE. */ @@ -1835,10 +1835,8 @@ range_misc::adjust_range_with_loop (irange &ir, struct loop *loop, /* Normalize the ranges for INIT and TEM to a constant range, and call the generic extract_range_from_binary_expr. */ - irange ir0 = get_irange (init, stmt); - irange ir1 = get_irange (tem, stmt); - value_range_base vr0 = irange_to_value_range (ir0); - value_range_base vr1 = irange_to_value_range (ir1); + value_range_base vr0 = get_irange (init, stmt); + value_range_base vr1 = get_irange (tem, stmt); value_range_base maxvr; range_fold_binary_expr (&maxvr, PLUS_EXPR, TREE_TYPE (init), &vr0, &vr1); @@ -1947,9 +1945,9 @@ vr_values::adjust_range_with_scev (value_range_base *vr, struct loop *loop, /* Bail on anything remotely symbolic. */ if (!vr->varying_p () && !vr->undefined_p () && !vr->constant_p ()) return; - irange ir = value_range_to_irange (*vr); + irange ir = *vr; adjust_range_with_loop (ir, loop, stmt, var); - *vr = irange_to_value_range (ir); + *vr = ir; } /* Dump value ranges of all SSA_NAMEs to FILE. */ @@ -3632,7 +3630,7 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt) irange ir; if (range_int_cst_p (vr)) - ir = value_range_to_irange (*vr); + ir = *vr; if (!ir.undefined_p () && range_fits_type_p (ir, @@ -3675,8 +3673,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt) if (TREE_CODE (op) == SSA_NAME) { // FIXME: We should convert this entire function to iranges. - irange ir = get_irange (op, stmt); - vr_obj = irange_to_value_range (ir); + vr_obj = get_irange (op, stmt); vr = &vr_obj; /* We can only handle integer ranges. */ |