aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@gcc.gnu.org>2019-06-27 04:07:23 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2019-06-27 04:07:23 +0000
commit7b6bb739b6651354dbc7173f9758c32217a9b7d4 (patch)
tree4178f4b0a073f34b85c57bc7f6ce049afc51ca6d
parent06ebd7a521dee8ac84a1eaf4df735c6b72298d33 (diff)
downloadgcc-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.c2
-rw-r--r--gcc/function-tests.c2
-rw-r--r--gcc/gimple-ssa-warn-restrict.c3
-rw-r--r--gcc/range.c65
-rw-r--r--gcc/range.h52
-rw-r--r--gcc/selftest.h2
-rw-r--r--gcc/ssa-range.cc6
-rw-r--r--gcc/ssa.h1
-rw-r--r--gcc/tree-vrp.c52
-rw-r--r--gcc/tree-vrp.h54
-rw-r--r--gcc/vr-values.c17
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))
{
diff --git a/gcc/ssa.h b/gcc/ssa.h
index 56a8d10..2fe4add 100644
--- a/gcc/ssa.h
+++ b/gcc/ssa.h
@@ -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. */