aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@gcc.gnu.org>2019-06-27 04:07:31 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2019-06-27 04:07:31 +0000
commit43e0b376cbb83c77a14be605c3858309b496d88a (patch)
treef53b38d924ac79a0320d696390fa7f908ddb40c8
parent7b6bb739b6651354dbc7173f9758c32217a9b7d4 (diff)
downloadgcc-43e0b376cbb83c77a14be605c3858309b496d88a.zip
gcc-43e0b376cbb83c77a14be605c3858309b496d88a.tar.gz
gcc-43e0b376cbb83c77a14be605c3858309b496d88a.tar.bz2
Move ssa-range* things from range.[hc] into ssa-range-gori.
From-SVN: r272728
-rw-r--r--gcc/range.c1093
-rw-r--r--gcc/range.h7
-rw-r--r--gcc/ssa-range-gori.cc77
-rw-r--r--gcc/ssa-range-gori.h3
-rw-r--r--gcc/ssa-range.h1
-rw-r--r--gcc/tree-vrp.h4
-rw-r--r--gcc/vr-values.c3
7 files changed, 589 insertions, 599 deletions
diff --git a/gcc/range.c b/gcc/range.c
index 8864a56..f0f711b 100644
--- a/gcc/range.c
+++ b/gcc/range.c
@@ -75,80 +75,6 @@ irange::operator!= (const irange &r) const
return !(*this == r);
}
-// Set range from an SSA_NAME's available range. If there is no
-// available range, build a range for its entire domain.
-
-irange
-range_from_ssa (tree ssa)
-{
- tree type = TREE_TYPE (ssa);
- gcc_checking_assert (irange::supports_type_p (type));
- if (!SSA_NAME_RANGE_INFO (ssa) || POINTER_TYPE_P (type))
- return irange (type);
- wide_int min, max;
- enum value_range_kind kind = get_range_info (ssa, &min, &max);
- return irange (kind, type, min, max);
-}
-
-// This function returns a range for tree node EXPR in R. Return
-// false if ranges are not supported.
-
-bool
-get_tree_range (irange &r, tree expr)
-{
- tree type;
- switch (TREE_CODE (expr))
- {
- case INTEGER_CST:
- if (!TREE_OVERFLOW_P (expr))
- r = irange (expr, expr);
- else
- // If we encounter an overflow, simply punt and drop to varying
- // since we hvae no idea how it will be used.
- r.set_varying (TREE_TYPE (expr));
- return true;
-
- case SSA_NAME:
- if (irange::supports_ssa_p (expr))
- {
- r = range_from_ssa (expr);
- return true;
- }
- break;
-
- case ADDR_EXPR:
- {
- // handle &var which can show up in phi arguments
- bool ov;
- type = TREE_TYPE (expr);
- if (irange::supports_type_p (type))
- {
- if (tree_single_nonzero_warnv_p (expr, &ov))
- r = range_nonzero (type);
- else
- r.set_varying (type);
- return true;
- }
- break;
- }
-
- default:
- if (TYPE_P (expr))
- type = expr;
- else
- type = TREE_TYPE (expr);
- if (irange::supports_type_p (type))
- {
- // Set to range for this type.
- r.set_varying (type);
- return true;
- }
- break;
- }
-
- return false;
-}
-
irange
range_intersect (const irange &r1, const irange &r2)
{
@@ -207,6 +133,515 @@ range_negatives (tree type)
return r;
}
+#if CHECKING_P
+#include "stor-layout.h"
+
+// 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.
+
+#define INT(N) build_int_cst (integer_type_node, (N))
+#define UINT(N) build_int_cstu (unsigned_type_node, (N))
+#define INT16(N) build_int_cst (short_integer_type_node, (N))
+#define UINT16(N) build_int_cstu (short_unsigned_type_node, (N))
+#define INT64(N) build_int_cstu (long_long_integer_type_node, (N))
+#define UINT64(N) build_int_cstu (long_long_unsigned_type_node, (N))
+#define UINT128(N) build_int_cstu (u128_type, (N))
+#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
+#define SCHAR(N) build_int_cst (signed_char_type_node, (N))
+
+#define RANGE3(A,B,C,D,E,F) \
+( i1 = irange (INT (A), INT (B)), \
+ i2 = irange (INT (C), INT (D)), \
+ i3 = irange (INT (E), INT (F)), \
+ i1.union_ (i2), \
+ i1.union_ (i3), \
+ i1 )
+
+// Run all of the selftests within this file.
+
+void
+range_tests ()
+{
+ tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
+ irange i1, i2, i3;
+ irange r0, r1, rold;
+
+ // Test that NOT(255) is [0..254] in 8-bit land.
+ irange not_255 (VR_ANTI_RANGE, UCHAR (255), UCHAR (255));
+ ASSERT_TRUE (not_255 == irange (UCHAR (0), UCHAR (254)));
+
+ // Test that NOT(0) is [1..255] in 8-bit land.
+ irange not_zero = range_nonzero (unsigned_char_type_node);
+ ASSERT_TRUE (not_zero == irange (UCHAR (1), UCHAR (255)));
+
+ // Check that [0,127][0x..ffffff80,0x..ffffff]
+ // => ~[128, 0x..ffffff7f].
+ r0 = irange (UINT128 (0), UINT128 (127));
+ tree high = build_minus_one_cst (u128_type);
+ // low = -1 - 127 => 0x..ffffff80.
+ tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127));
+ r1 = irange (low, high); // [0x..ffffff80, 0x..ffffffff]
+ // r0 = [0,127][0x..ffffff80,0x..fffffff].
+ r0.union_ (r1);
+ // r1 = [128, 0x..ffffff7f].
+ r1 = irange (UINT128(128),
+ fold_build2 (MINUS_EXPR, u128_type,
+ build_minus_one_cst (u128_type),
+ UINT128(128)));
+ r0.invert ();
+ ASSERT_TRUE (r0 == r1);
+
+ r0.set_varying (integer_type_node);
+ tree minint = wide_int_to_tree (integer_type_node, r0.lower_bound ());
+ tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ());
+
+ r0.set_varying (short_integer_type_node);
+ tree minshort = wide_int_to_tree (short_integer_type_node, r0.lower_bound ());
+ tree maxshort = wide_int_to_tree (short_integer_type_node, r0.upper_bound ());
+
+ r0.set_varying (unsigned_type_node);
+ tree maxuint = wide_int_to_tree (unsigned_type_node, r0.upper_bound ());
+
+ // Check that ~[0,5] => [6,MAX] for unsigned int.
+ r0 = irange (UINT (0), UINT (5));
+ r0.invert ();
+ ASSERT_TRUE (r0 == irange (UINT(6), maxuint));
+
+ // Check that ~[10,MAX] => [0,9] for unsigned int.
+ r0 = irange (VR_RANGE, UINT(10), maxuint);
+ r0.invert ();
+ ASSERT_TRUE (r0 == irange (UINT (0), UINT (9)));
+
+ // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
+ r0 = irange (VR_ANTI_RANGE, UINT128 (0), UINT128 (5));
+ r1 = irange (UINT128(6), build_minus_one_cst (u128_type));
+ ASSERT_TRUE (r0 == r1);
+
+ // Check that [~5] is really [-MIN,4][6,MAX].
+ r0 = irange (VR_ANTI_RANGE, INT (5), INT (5));
+ r1 = irange (minint, INT (4));
+ r1.union_ (irange (INT (6), maxint));
+ ASSERT_FALSE (r1.undefined_p ());
+ ASSERT_TRUE (r0 == r1);
+
+ r1 = irange (INT (5), INT (5));
+ r1.check ();
+ irange r2 (r1);
+ ASSERT_TRUE (r1 == r2);
+
+ r1 = irange (INT (5), INT (10));
+ r1.check ();
+
+ r1 = irange (integer_type_node,
+ wi::to_wide (INT (5)), wi::to_wide (INT (10)));
+ r1.check ();
+ ASSERT_TRUE (r1.contains_p (INT (7)));
+
+ r1 = irange (SCHAR (0), SCHAR (20));
+ ASSERT_TRUE (r1.contains_p (SCHAR(15)));
+ ASSERT_FALSE (r1.contains_p (SCHAR(300)));
+
+ // If a range is in any way outside of the range for the converted
+ // to range, default to the range for the new type.
+ r1 = irange (integer_zero_node, maxint);
+ r1.cast (short_integer_type_node);
+ ASSERT_TRUE (r1.lower_bound () == wi::to_wide (minshort)
+ && r1.upper_bound() == wi::to_wide (maxshort));
+
+ // (unsigned char)[-5,-1] => [251,255].
+ r0 = rold = irange (SCHAR (-5), SCHAR (-1));
+ r0.cast (unsigned_char_type_node);
+ ASSERT_TRUE (r0 == irange (UCHAR (251), UCHAR (255)));
+ r0.cast (signed_char_type_node);
+ ASSERT_TRUE (r0 == rold);
+
+ // (signed char)[15, 150] => [-128,-106][15,127].
+ r0 = rold = irange (UCHAR (15), UCHAR (150));
+ r0.cast (signed_char_type_node);
+ r1 = irange (SCHAR (15), SCHAR (127));
+ r2 = irange (SCHAR (-128), SCHAR (-106));
+ r1.union_ (r2);
+ ASSERT_TRUE (r1 == r0);
+ r0.cast (unsigned_char_type_node);
+ ASSERT_TRUE (r0 == rold);
+
+ // (unsigned char)[-5, 5] => [0,5][251,255].
+ r0 = rold = irange (SCHAR (-5), SCHAR (5));
+ r0.cast (unsigned_char_type_node);
+ r1 = irange (UCHAR (251), UCHAR (255));
+ r2 = irange (UCHAR (0), UCHAR (5));
+ r1.union_ (r2);
+ ASSERT_TRUE (r0 == r1);
+ r0.cast (signed_char_type_node);
+ ASSERT_TRUE (r0 == rold);
+
+ // (unsigned char)[-5,5] => [0,5][251,255].
+ r0 = irange (INT (-5), INT (5));
+ r0.cast (unsigned_char_type_node);
+ r1 = irange (UCHAR (0), UCHAR (5));
+ r1.union_ (irange (UCHAR (251), UCHAR (255)));
+ ASSERT_TRUE (r0 == r1);
+
+ // (unsigned char)[5U,1974U] => [0,255].
+ r0 = irange (UINT (5), UINT (1974));
+ r0.cast (unsigned_char_type_node);
+ ASSERT_TRUE (r0 == irange (UCHAR (0), UCHAR (255)));
+ r0.cast (integer_type_node);
+ // Going to a wider range should not sign extend.
+ ASSERT_TRUE (r0 == irange (INT (0), INT (255)));
+
+ // (unsigned char)[-350,15] => [0,255].
+ r0 = irange (INT (-350), INT (15));
+ r0.cast (unsigned_char_type_node);
+ ASSERT_TRUE (r0 == irange (TYPE_MIN_VALUE (unsigned_char_type_node),
+ TYPE_MAX_VALUE (unsigned_char_type_node)));
+
+ // Casting [-120,20] from signed char to unsigned short.
+ // => [0, 20][0xff88, 0xffff].
+ r0 = irange (SCHAR (-120), SCHAR (20));
+ r0.cast (short_unsigned_type_node);
+ r1 = irange (UINT16 (0), UINT16 (20));
+ r2 = irange (UINT16 (0xff88), UINT16 (0xffff));
+ r1.union_ (r2);
+ ASSERT_TRUE (r0 == r1);
+ // A truncating cast back to signed char will work because [-120, 20]
+ // is representable in signed char.
+ r0.cast (signed_char_type_node);
+ ASSERT_TRUE (r0 == irange (SCHAR (-120), SCHAR (20)));
+
+ // unsigned char -> signed short
+ // (signed short)[(unsigned char)25, (unsigned char)250]
+ // => [(signed short)25, (signed short)250]
+ r0 = rold = irange (UCHAR (25), UCHAR (250));
+ r0.cast (short_integer_type_node);
+ r1 = irange (INT16 (25), INT16 (250));
+ ASSERT_TRUE (r0 == r1);
+ r0.cast (unsigned_char_type_node);
+ ASSERT_TRUE (r0 == rold);
+
+ // Test casting a wider signed [-MIN,MAX] to a nar`rower unsigned.
+ r0 = irange (TYPE_MIN_VALUE (long_long_integer_type_node),
+ TYPE_MAX_VALUE (long_long_integer_type_node));
+ r0.cast (short_unsigned_type_node);
+ r1 = irange (TYPE_MIN_VALUE (short_unsigned_type_node),
+ TYPE_MAX_VALUE (short_unsigned_type_node));
+ ASSERT_TRUE (r0 == r1);
+
+ // Test that casting a range with MAX_PAIRS that changes sign is
+ // done conservatively.
+ //
+ // (unsigned short)[-5,5][20,30][40,50]...
+ // => (unsigned short)[-5,50]
+ // => [0,50][65531,65535]
+ r0 = irange (INT16 (-5), INT16 (5));
+ gcc_assert (irange::m_max_pairs * 2 * 10 + 10 < 32767);
+ unsigned i;
+ for (i = 2; i < irange::m_max_pairs * 2; i += 2)
+ {
+ r1 = irange (INT16 (i * 10), INT16 (i * 10 + 10));
+ r0.union_ (r1);
+ }
+ r0.cast(short_unsigned_type_node);
+ r1 = irange (UINT16 (0), UINT16 ((i - 2) * 10 + 10));
+ r2 = irange (UINT16 (65531), UINT16 (65535));
+ r1.union_ (r2);
+ ASSERT_TRUE (r0 == r1);
+
+ // NOT([10,20]) ==> [-MIN,9][21,MAX].
+ r0 = r1 = irange (INT (10), INT (20));
+ r2 = irange (minint, INT(9));
+ r2.union_ (irange (INT(21), maxint));
+ ASSERT_FALSE (r2.undefined_p ());
+ r1.invert ();
+ ASSERT_TRUE (r1 == r2);
+ // Test that NOT(NOT(x)) == x.
+ r2.invert ();
+ ASSERT_TRUE (r0 == r2);
+
+ // NOT(-MIN,+MAX) is the empty set and should return false.
+ r0 = irange (minint, maxint);
+ r0.invert ();
+ ASSERT_TRUE (r0.undefined_p ());
+ r1.set_undefined ();
+ ASSERT_TRUE (r0 == r1);
+
+ // Test that booleans and their inverse work as expected.
+ r0 = range_zero (boolean_type_node);
+ ASSERT_TRUE (r0 == irange (build_zero_cst (boolean_type_node),
+ build_zero_cst (boolean_type_node)));
+ r0.invert();
+ ASSERT_TRUE (r0 == irange (build_one_cst (boolean_type_node),
+ build_one_cst (boolean_type_node)));
+
+ // Casting NONZERO to a narrower type will wrap/overflow so
+ // it's just the entire range for the narrower type.
+ //
+ // "NOT 0 at signed 32-bits" ==> [-MIN_32,-1][1, +MAX_32]. This is
+ // is outside of the range of a smaller range, return the full
+ // smaller range.
+ r0 = range_nonzero (integer_type_node);
+ r0.cast (short_integer_type_node);
+ r1 = irange (TYPE_MIN_VALUE (short_integer_type_node),
+ TYPE_MAX_VALUE (short_integer_type_node));
+ ASSERT_TRUE (r0 == r1);
+
+ // Casting NONZERO from a narrower signed to a wider signed.
+ //
+ // NONZERO signed 16-bits is [-MIN_16,-1][1, +MAX_16].
+ // Converting this to 32-bits signed is [-MIN_16,-1][1, +MAX_16].
+ r0 = range_nonzero (short_integer_type_node);
+ r0.cast (integer_type_node);
+ r1 = irange (INT (-32768), INT (-1));
+ r2 = irange (INT (1), INT (32767));
+ r1.union_ (r2);
+ ASSERT_TRUE (r0 == r1);
+
+ if (irange::m_max_pairs > 2)
+ {
+ // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (5), INT (8));
+ r0.union_ (r1);
+ r1 = irange (INT (1), INT (3));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == RANGE3 (1, 3, 5, 8, 10, 20));
+
+ // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
+ r1 = irange (INT (-5), INT (0));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == RANGE3 (-5, 3, 5, 8, 10, 20));
+ }
+
+ // [10,20] U [30,40] ==> [10,20][30,40].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (30), INT (40));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
+ irange (INT (30), INT (40))));
+ if (irange::m_max_pairs > 2)
+ {
+ // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
+ r1 = irange (INT (50), INT (60));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == RANGE3 (10, 20, 30, 40, 50, 60));
+ // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80].
+ r1 = irange (INT (70), INT (80));
+ r0.union_ (r1);
+
+ r2 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r2.union_ (irange (INT (70), INT (80)));
+ ASSERT_TRUE (r0 == r2);
+ }
+
+ // Make sure NULL and non-NULL of pointer types work, and that
+ // inverses of them are consistent.
+ tree voidp = build_pointer_type (void_type_node);
+ r0 = range_zero (voidp);
+ r1 = r0;
+ r0.invert ();
+ r0.invert ();
+ ASSERT_TRUE (r0 == r1);
+
+ if (irange::m_max_pairs > 2)
+ {
+ // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (6), INT (35));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (6), INT (40)),
+ irange (INT (50), INT (60))));
+
+ // [10,20][30,40][50,60] U [6,60] => [6,60] */
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (6), INT (60));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (6), INT (60)));
+
+ // [10,20][30,40][50,60] U [6,70] => [6,70].
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (6), INT (70));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (6), INT (70)));
+
+ // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (35), INT (70));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
+ irange (INT (30), INT (70))));
+ }
+
+ // [10,20][30,40] U [25,70] => [10,70].
+ r0 = range_union (irange (INT (10), INT (20)),
+ irange (INT (30), INT (40)));
+ r1 = irange (INT (25), INT (70));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
+ irange (INT (25), INT (70))));
+
+ if (irange::m_max_pairs > 2)
+ {
+ // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (15), INT (35));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (40)),
+ irange (INT (50), INT (60))));
+ }
+
+ // [10,20] U [15, 30] => [10, 30].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (15), INT (30));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (10), INT (30)));
+
+ // [10,20] U [25,25] => [10,20][25,25].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (25), INT (25));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
+ irange (INT (25), INT (25))));
+
+ if (irange::m_max_pairs > 2)
+ {
+ // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = irange (INT (35), INT (35));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == RANGE3 (10, 20, 30, 40, 50, 60));
+ }
+
+ // [15,40] U [] => [15,40].
+ r0 = irange (INT (15), INT (40));
+ r1.set_undefined ();
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (15), INT (40)));
+
+ // [10,20] U [10,10] => [10,20].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (10), INT (10));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (10), INT (20)));
+
+ // [10,20] U [9,9] => [9,20].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (9), INT (9));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == irange (INT (9), INT (20)));
+
+ if (irange::m_max_pairs > 2)
+ {
+ // [10,10][12,12][20,100] ^ [15,200].
+ r0 = RANGE3 (10, 10, 12, 12, 20, 100);
+ r1 = irange (INT (15), INT (200));
+ r0.intersect (r1);
+ ASSERT_TRUE (r0 == irange (INT (20), INT (100)));
+
+ // [10,20][30,40][50,60] ^ [15,25][38,51][55,70]
+ // => [15,20][38,40][50,51][55,60]
+ r0 = RANGE3 (10, 20, 30, 40, 50, 60);
+ r1 = RANGE3 (15, 25, 38, 51, 55, 70);
+ r0.intersect (r1);
+ if (irange::m_max_pairs == 3)
+ {
+ // When pairs==3, we don't have enough space, so
+ // conservatively handle things. Thus, the ...[50,60].
+ ASSERT_TRUE (r0 == RANGE3 (15, 20, 38, 40, 50, 60));
+ }
+ else
+ {
+ r2 = RANGE3 (15, 20, 38, 40, 50, 51);
+ r2.union_ (irange (INT (55), INT (60)));
+ ASSERT_TRUE (r0 == r2);
+ }
+
+ // [15,20][30,40][50,60] ^ [15,35][40,90][100,200]
+ // => [15,20][30,35][40,60]
+ r0 = RANGE3 (15, 20, 30, 40, 50, 60);
+ r1 = RANGE3 (15, 35, 40, 90, 100, 200);
+ r0.intersect (r1);
+ if (irange::m_max_pairs == 3)
+ {
+ // When pairs==3, we don't have enough space, so
+ // conservatively handle things.
+ ASSERT_TRUE (r0 == RANGE3 (15, 20, 30, 35, 40, 60));
+ }
+ else
+ {
+ r2 = RANGE3 (15, 20, 30, 35, 40, 40);
+ r2.union_ (irange (INT (50), INT (60)));
+ ASSERT_TRUE (r0 == r2);
+ }
+
+ // Test cases where a union inserts a sub-range inside a larger
+ // range.
+ //
+ // [8,10][135,255] U [14,14] => [8,10][14,14][135,255]
+ r0 = range_union (irange (INT (8), INT (10)),
+ irange (INT (135), INT (255)));
+ r1 = irange (INT (14), INT (14));
+ r0.union_ (r1);
+ ASSERT_TRUE (r0 == RANGE3 (8, 10, 14, 14, 135, 255));
+ }
+
+ // [10,20] ^ [15,30] => [15,20].
+ r0 = irange (INT (10), INT (20));
+ r1 = irange (INT (15), INT (30));
+ r0.intersect (r1);
+ ASSERT_TRUE (r0 == irange (INT (15), INT (20)));
+
+ // [10,20][30,40] ^ [40,50] => [40,40].
+ r0 = range_union (irange (INT (10), INT (20)),
+ irange (INT (30), INT (40)));
+ r1 = irange (INT (40), INT (50));
+ r0.intersect (r1);
+ ASSERT_TRUE (r0 == irange (INT (40), INT (40)));
+
+ // Test non-destructive intersection.
+ r0 = rold = irange (INT (10), INT (20));
+ ASSERT_FALSE (range_intersect (r0, irange (INT (15),
+ INT (30))).undefined_p ());
+ ASSERT_TRUE (r0 == rold);
+
+ // Test the internal sanity of wide_int's wrt HWIs.
+ ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),
+ TYPE_SIGN (boolean_type_node))
+ == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)));
+
+ // Test irange_storage.
+ r0 = irange (INT (5), INT (10));
+ irange_storage *stow = irange_storage::alloc (r0);
+ r1 = irange (integer_type_node, stow);
+ ASSERT_TRUE (r0 == r1);
+
+ // Test irange_storage with signed 1-bit fields.
+ tree s1bit_type = make_signed_type (1);
+ r0 = irange (build_int_cst (s1bit_type, -1), build_int_cst (s1bit_type, 0));
+ stow = irange_storage::alloc (r0);
+ r1 = irange (s1bit_type, stow);
+ ASSERT_TRUE (r0 == r1);
+
+ // Test zero_p().
+ r0 = irange (INT (0), INT (0));
+ ASSERT_TRUE (r0.zero_p ());
+
+ // Test nonzero_p().
+ r0 = irange (INT (0), INT (0));
+ r0.invert ();
+ ASSERT_TRUE (r0.nonzero_p ());
+
+ // Test irange / value_range conversion functions.
+ r0 = irange (VR_ANTI_RANGE, INT (10), INT (20));
+ 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 = vr;
+ ASSERT_TRUE (r0 == r1);
+}
+#endif // CHECKING_P
+
#if USE_IRANGE
// Standalone irange implementation.
@@ -1068,513 +1503,3 @@ irange::irange (const value_range_base &vr)
}
#endif // USE_IRANGE
-
-#if CHECKING_P
-#include "stor-layout.h"
-
-// 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.
-
-#define INT(N) build_int_cst (integer_type_node, (N))
-#define UINT(N) build_int_cstu (unsigned_type_node, (N))
-#define INT16(N) build_int_cst (short_integer_type_node, (N))
-#define UINT16(N) build_int_cstu (short_unsigned_type_node, (N))
-#define INT64(N) build_int_cstu (long_long_integer_type_node, (N))
-#define UINT64(N) build_int_cstu (long_long_unsigned_type_node, (N))
-#define UINT128(N) build_int_cstu (u128_type, (N))
-#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
-#define SCHAR(N) build_int_cst (signed_char_type_node, (N))
-
-#define RANGE3(A,B,C,D,E,F) \
-( i1 = irange (INT (A), INT (B)), \
- i2 = irange (INT (C), INT (D)), \
- i3 = irange (INT (E), INT (F)), \
- i1.union_ (i2), \
- i1.union_ (i3), \
- i1 )
-
-// Run all of the selftests within this file.
-
-void
-range_tests ()
-{
- tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
- irange i1, i2, i3;
- irange r0, r1, rold;
-
- // Test that NOT(255) is [0..254] in 8-bit land.
- irange not_255 (VR_ANTI_RANGE, UCHAR (255), UCHAR (255));
- ASSERT_TRUE (not_255 == irange (UCHAR (0), UCHAR (254)));
-
- // Test that NOT(0) is [1..255] in 8-bit land.
- irange not_zero = range_nonzero (unsigned_char_type_node);
- ASSERT_TRUE (not_zero == irange (UCHAR (1), UCHAR (255)));
-
- // Check that [0,127][0x..ffffff80,0x..ffffff]
- // => ~[128, 0x..ffffff7f].
- r0 = irange (UINT128 (0), UINT128 (127));
- tree high = build_minus_one_cst (u128_type);
- // low = -1 - 127 => 0x..ffffff80.
- tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127));
- r1 = irange (low, high); // [0x..ffffff80, 0x..ffffffff]
- // r0 = [0,127][0x..ffffff80,0x..fffffff].
- r0.union_ (r1);
- // r1 = [128, 0x..ffffff7f].
- r1 = irange (UINT128(128),
- fold_build2 (MINUS_EXPR, u128_type,
- build_minus_one_cst (u128_type),
- UINT128(128)));
- r0.invert ();
- ASSERT_TRUE (r0 == r1);
-
- r0.set_varying (integer_type_node);
- tree minint = wide_int_to_tree (integer_type_node, r0.lower_bound ());
- tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ());
-
- r0.set_varying (short_integer_type_node);
- tree minshort = wide_int_to_tree (short_integer_type_node, r0.lower_bound ());
- tree maxshort = wide_int_to_tree (short_integer_type_node, r0.upper_bound ());
-
- r0.set_varying (unsigned_type_node);
- tree maxuint = wide_int_to_tree (unsigned_type_node, r0.upper_bound ());
-
- // Check that ~[0,5] => [6,MAX] for unsigned int.
- r0 = irange (UINT (0), UINT (5));
- r0.invert ();
- ASSERT_TRUE (r0 == irange (UINT(6), maxuint));
-
- // Check that ~[10,MAX] => [0,9] for unsigned int.
- r0 = irange (VR_RANGE, UINT(10), maxuint);
- r0.invert ();
- ASSERT_TRUE (r0 == irange (UINT (0), UINT (9)));
-
- // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
- r0 = irange (VR_ANTI_RANGE, UINT128 (0), UINT128 (5));
- r1 = irange (UINT128(6), build_minus_one_cst (u128_type));
- ASSERT_TRUE (r0 == r1);
-
- // Check that [~5] is really [-MIN,4][6,MAX].
- r0 = irange (VR_ANTI_RANGE, INT (5), INT (5));
- r1 = irange (minint, INT (4));
- r1.union_ (irange (INT (6), maxint));
- ASSERT_FALSE (r1.undefined_p ());
- ASSERT_TRUE (r0 == r1);
-
- r1 = irange (INT (5), INT (5));
- r1.check ();
- irange r2 (r1);
- ASSERT_TRUE (r1 == r2);
-
- r1 = irange (INT (5), INT (10));
- r1.check ();
-
- r1 = irange (integer_type_node,
- wi::to_wide (INT (5)), wi::to_wide (INT (10)));
- r1.check ();
- ASSERT_TRUE (r1.contains_p (INT (7)));
-
- r1 = irange (SCHAR (0), SCHAR (20));
- ASSERT_TRUE (r1.contains_p (SCHAR(15)));
- ASSERT_FALSE (r1.contains_p (SCHAR(300)));
-
- // If a range is in any way outside of the range for the converted
- // to range, default to the range for the new type.
- r1 = irange (integer_zero_node, maxint);
- r1.cast (short_integer_type_node);
- ASSERT_TRUE (r1.lower_bound () == wi::to_wide (minshort)
- && r1.upper_bound() == wi::to_wide (maxshort));
-
- // (unsigned char)[-5,-1] => [251,255].
- r0 = rold = irange (SCHAR (-5), SCHAR (-1));
- r0.cast (unsigned_char_type_node);
- ASSERT_TRUE (r0 == irange (UCHAR (251), UCHAR (255)));
- r0.cast (signed_char_type_node);
- ASSERT_TRUE (r0 == rold);
-
- // (signed char)[15, 150] => [-128,-106][15,127].
- r0 = rold = irange (UCHAR (15), UCHAR (150));
- r0.cast (signed_char_type_node);
- r1 = irange (SCHAR (15), SCHAR (127));
- r2 = irange (SCHAR (-128), SCHAR (-106));
- r1.union_ (r2);
- ASSERT_TRUE (r1 == r0);
- r0.cast (unsigned_char_type_node);
- ASSERT_TRUE (r0 == rold);
-
- // (unsigned char)[-5, 5] => [0,5][251,255].
- r0 = rold = irange (SCHAR (-5), SCHAR (5));
- r0.cast (unsigned_char_type_node);
- r1 = irange (UCHAR (251), UCHAR (255));
- r2 = irange (UCHAR (0), UCHAR (5));
- r1.union_ (r2);
- ASSERT_TRUE (r0 == r1);
- r0.cast (signed_char_type_node);
- ASSERT_TRUE (r0 == rold);
-
- // (unsigned char)[-5,5] => [0,5][251,255].
- r0 = irange (INT (-5), INT (5));
- r0.cast (unsigned_char_type_node);
- r1 = irange (UCHAR (0), UCHAR (5));
- r1.union_ (irange (UCHAR (251), UCHAR (255)));
- ASSERT_TRUE (r0 == r1);
-
- // (unsigned char)[5U,1974U] => [0,255].
- r0 = irange (UINT (5), UINT (1974));
- r0.cast (unsigned_char_type_node);
- ASSERT_TRUE (r0 == irange (UCHAR (0), UCHAR (255)));
- r0.cast (integer_type_node);
- // Going to a wider range should not sign extend.
- ASSERT_TRUE (r0 == irange (INT (0), INT (255)));
-
- // (unsigned char)[-350,15] => [0,255].
- r0 = irange (INT (-350), INT (15));
- r0.cast (unsigned_char_type_node);
- ASSERT_TRUE (r0 == irange (TYPE_MIN_VALUE (unsigned_char_type_node),
- TYPE_MAX_VALUE (unsigned_char_type_node)));
-
- // Casting [-120,20] from signed char to unsigned short.
- // => [0, 20][0xff88, 0xffff].
- r0 = irange (SCHAR (-120), SCHAR (20));
- r0.cast (short_unsigned_type_node);
- r1 = irange (UINT16 (0), UINT16 (20));
- r2 = irange (UINT16 (0xff88), UINT16 (0xffff));
- r1.union_ (r2);
- ASSERT_TRUE (r0 == r1);
- // A truncating cast back to signed char will work because [-120, 20]
- // is representable in signed char.
- r0.cast (signed_char_type_node);
- ASSERT_TRUE (r0 == irange (SCHAR (-120), SCHAR (20)));
-
- // unsigned char -> signed short
- // (signed short)[(unsigned char)25, (unsigned char)250]
- // => [(signed short)25, (signed short)250]
- r0 = rold = irange (UCHAR (25), UCHAR (250));
- r0.cast (short_integer_type_node);
- r1 = irange (INT16 (25), INT16 (250));
- ASSERT_TRUE (r0 == r1);
- r0.cast (unsigned_char_type_node);
- ASSERT_TRUE (r0 == rold);
-
- // Test casting a wider signed [-MIN,MAX] to a nar`rower unsigned.
- r0 = irange (TYPE_MIN_VALUE (long_long_integer_type_node),
- TYPE_MAX_VALUE (long_long_integer_type_node));
- r0.cast (short_unsigned_type_node);
- r1 = irange (TYPE_MIN_VALUE (short_unsigned_type_node),
- TYPE_MAX_VALUE (short_unsigned_type_node));
- ASSERT_TRUE (r0 == r1);
-
- // Test that casting a range with MAX_PAIRS that changes sign is
- // done conservatively.
- //
- // (unsigned short)[-5,5][20,30][40,50]...
- // => (unsigned short)[-5,50]
- // => [0,50][65531,65535]
- r0 = irange (INT16 (-5), INT16 (5));
- gcc_assert (irange::m_max_pairs * 2 * 10 + 10 < 32767);
- unsigned i;
- for (i = 2; i < irange::m_max_pairs * 2; i += 2)
- {
- r1 = irange (INT16 (i * 10), INT16 (i * 10 + 10));
- r0.union_ (r1);
- }
- r0.cast(short_unsigned_type_node);
- r1 = irange (UINT16 (0), UINT16 ((i - 2) * 10 + 10));
- r2 = irange (UINT16 (65531), UINT16 (65535));
- r1.union_ (r2);
- ASSERT_TRUE (r0 == r1);
-
- // NOT([10,20]) ==> [-MIN,9][21,MAX].
- r0 = r1 = irange (INT (10), INT (20));
- r2 = irange (minint, INT(9));
- r2.union_ (irange (INT(21), maxint));
- ASSERT_FALSE (r2.undefined_p ());
- r1.invert ();
- ASSERT_TRUE (r1 == r2);
- // Test that NOT(NOT(x)) == x.
- r2.invert ();
- ASSERT_TRUE (r0 == r2);
-
- // NOT(-MIN,+MAX) is the empty set and should return false.
- r0 = irange (minint, maxint);
- r0.invert ();
- ASSERT_TRUE (r0.undefined_p ());
- r1.set_undefined ();
- ASSERT_TRUE (r0 == r1);
-
- // Test that booleans and their inverse work as expected.
- r0 = range_zero (boolean_type_node);
- ASSERT_TRUE (r0 == irange (build_zero_cst (boolean_type_node),
- build_zero_cst (boolean_type_node)));
- r0.invert();
- ASSERT_TRUE (r0 == irange (build_one_cst (boolean_type_node),
- build_one_cst (boolean_type_node)));
-
- // Casting NONZERO to a narrower type will wrap/overflow so
- // it's just the entire range for the narrower type.
- //
- // "NOT 0 at signed 32-bits" ==> [-MIN_32,-1][1, +MAX_32]. This is
- // is outside of the range of a smaller range, return the full
- // smaller range.
- r0 = range_nonzero (integer_type_node);
- r0.cast (short_integer_type_node);
- r1 = irange (TYPE_MIN_VALUE (short_integer_type_node),
- TYPE_MAX_VALUE (short_integer_type_node));
- ASSERT_TRUE (r0 == r1);
-
- // Casting NONZERO from a narrower signed to a wider signed.
- //
- // NONZERO signed 16-bits is [-MIN_16,-1][1, +MAX_16].
- // Converting this to 32-bits signed is [-MIN_16,-1][1, +MAX_16].
- r0 = range_nonzero (short_integer_type_node);
- r0.cast (integer_type_node);
- r1 = irange (INT (-32768), INT (-1));
- r2 = irange (INT (1), INT (32767));
- r1.union_ (r2);
- ASSERT_TRUE (r0 == r1);
-
- if (irange::m_max_pairs > 2)
- {
- // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (5), INT (8));
- r0.union_ (r1);
- r1 = irange (INT (1), INT (3));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == RANGE3 (1, 3, 5, 8, 10, 20));
-
- // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
- r1 = irange (INT (-5), INT (0));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == RANGE3 (-5, 3, 5, 8, 10, 20));
- }
-
- // [10,20] U [30,40] ==> [10,20][30,40].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (30), INT (40));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
- irange (INT (30), INT (40))));
- if (irange::m_max_pairs > 2)
- {
- // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
- r1 = irange (INT (50), INT (60));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == RANGE3 (10, 20, 30, 40, 50, 60));
- // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80].
- r1 = irange (INT (70), INT (80));
- r0.union_ (r1);
-
- r2 = RANGE3 (10, 20, 30, 40, 50, 60);
- r2.union_ (irange (INT (70), INT (80)));
- ASSERT_TRUE (r0 == r2);
- }
-
- // Make sure NULL and non-NULL of pointer types work, and that
- // inverses of them are consistent.
- tree voidp = build_pointer_type (void_type_node);
- r0 = range_zero (voidp);
- r1 = r0;
- r0.invert ();
- r0.invert ();
- ASSERT_TRUE (r0 == r1);
-
- if (irange::m_max_pairs > 2)
- {
- // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (6), INT (35));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (6), INT (40)),
- irange (INT (50), INT (60))));
-
- // [10,20][30,40][50,60] U [6,60] => [6,60] */
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (6), INT (60));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (6), INT (60)));
-
- // [10,20][30,40][50,60] U [6,70] => [6,70].
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (6), INT (70));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (6), INT (70)));
-
- // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (35), INT (70));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
- irange (INT (30), INT (70))));
- }
-
- // [10,20][30,40] U [25,70] => [10,70].
- r0 = range_union (irange (INT (10), INT (20)),
- irange (INT (30), INT (40)));
- r1 = irange (INT (25), INT (70));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
- irange (INT (25), INT (70))));
-
- if (irange::m_max_pairs > 2)
- {
- // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (15), INT (35));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (40)),
- irange (INT (50), INT (60))));
- }
-
- // [10,20] U [15, 30] => [10, 30].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (15), INT (30));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (10), INT (30)));
-
- // [10,20] U [25,25] => [10,20][25,25].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (25), INT (25));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == range_union (irange (INT (10), INT (20)),
- irange (INT (25), INT (25))));
-
- if (irange::m_max_pairs > 2)
- {
- // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = irange (INT (35), INT (35));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == RANGE3 (10, 20, 30, 40, 50, 60));
- }
-
- // [15,40] U [] => [15,40].
- r0 = irange (INT (15), INT (40));
- r1.set_undefined ();
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (15), INT (40)));
-
- // [10,20] U [10,10] => [10,20].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (10), INT (10));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (10), INT (20)));
-
- // [10,20] U [9,9] => [9,20].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (9), INT (9));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == irange (INT (9), INT (20)));
-
- if (irange::m_max_pairs > 2)
- {
- // [10,10][12,12][20,100] ^ [15,200].
- r0 = RANGE3 (10, 10, 12, 12, 20, 100);
- r1 = irange (INT (15), INT (200));
- r0.intersect (r1);
- ASSERT_TRUE (r0 == irange (INT (20), INT (100)));
-
- // [10,20][30,40][50,60] ^ [15,25][38,51][55,70]
- // => [15,20][38,40][50,51][55,60]
- r0 = RANGE3 (10, 20, 30, 40, 50, 60);
- r1 = RANGE3 (15, 25, 38, 51, 55, 70);
- r0.intersect (r1);
- if (irange::m_max_pairs == 3)
- {
- // When pairs==3, we don't have enough space, so
- // conservatively handle things. Thus, the ...[50,60].
- ASSERT_TRUE (r0 == RANGE3 (15, 20, 38, 40, 50, 60));
- }
- else
- {
- r2 = RANGE3 (15, 20, 38, 40, 50, 51);
- r2.union_ (irange (INT (55), INT (60)));
- ASSERT_TRUE (r0 == r2);
- }
-
- // [15,20][30,40][50,60] ^ [15,35][40,90][100,200]
- // => [15,20][30,35][40,60]
- r0 = RANGE3 (15, 20, 30, 40, 50, 60);
- r1 = RANGE3 (15, 35, 40, 90, 100, 200);
- r0.intersect (r1);
- if (irange::m_max_pairs == 3)
- {
- // When pairs==3, we don't have enough space, so
- // conservatively handle things.
- ASSERT_TRUE (r0 == RANGE3 (15, 20, 30, 35, 40, 60));
- }
- else
- {
- r2 = RANGE3 (15, 20, 30, 35, 40, 40);
- r2.union_ (irange (INT (50), INT (60)));
- ASSERT_TRUE (r0 == r2);
- }
-
- // Test cases where a union inserts a sub-range inside a larger
- // range.
- //
- // [8,10][135,255] U [14,14] => [8,10][14,14][135,255]
- r0 = range_union (irange (INT (8), INT (10)),
- irange (INT (135), INT (255)));
- r1 = irange (INT (14), INT (14));
- r0.union_ (r1);
- ASSERT_TRUE (r0 == RANGE3 (8, 10, 14, 14, 135, 255));
- }
-
- // [10,20] ^ [15,30] => [15,20].
- r0 = irange (INT (10), INT (20));
- r1 = irange (INT (15), INT (30));
- r0.intersect (r1);
- ASSERT_TRUE (r0 == irange (INT (15), INT (20)));
-
- // [10,20][30,40] ^ [40,50] => [40,40].
- r0 = range_union (irange (INT (10), INT (20)),
- irange (INT (30), INT (40)));
- r1 = irange (INT (40), INT (50));
- r0.intersect (r1);
- ASSERT_TRUE (r0 == irange (INT (40), INT (40)));
-
- // Test non-destructive intersection.
- r0 = rold = irange (INT (10), INT (20));
- ASSERT_FALSE (range_intersect (r0, irange (INT (15),
- INT (30))).undefined_p ());
- ASSERT_TRUE (r0 == rold);
-
- // Test the internal sanity of wide_int's wrt HWIs.
- ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),
- TYPE_SIGN (boolean_type_node))
- == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)));
-
- // Test irange_storage.
- r0 = irange (INT (5), INT (10));
- irange_storage *stow = irange_storage::alloc (r0);
- r1 = irange (integer_type_node, stow);
- ASSERT_TRUE (r0 == r1);
-
- // Test irange_storage with signed 1-bit fields.
- tree s1bit_type = make_signed_type (1);
- r0 = irange (build_int_cst (s1bit_type, -1), build_int_cst (s1bit_type, 0));
- stow = irange_storage::alloc (r0);
- r1 = irange (s1bit_type, stow);
- ASSERT_TRUE (r0 == r1);
-
- // Test zero_p().
- r0 = irange (INT (0), INT (0));
- ASSERT_TRUE (r0.zero_p ());
-
- // Test nonzero_p().
- r0 = irange (INT (0), INT (0));
- r0.invert ();
- ASSERT_TRUE (r0.nonzero_p ());
-
- // Test irange / value_range conversion functions.
- r0 = irange (VR_ANTI_RANGE, INT (10), INT (20));
- 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 = vr;
- ASSERT_TRUE (r0 == r1);
-}
-
-#endif // CHECKING_P
diff --git a/gcc/range.h b/gcc/range.h
index 9205d0b..5b10232 100644
--- a/gcc/range.h
+++ b/gcc/range.h
@@ -61,10 +61,7 @@ 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);
@@ -341,10 +338,6 @@ 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/ssa-range-gori.cc b/gcc/ssa-range-gori.cc
index 1e67da7..f5fdaf0 100644
--- a/gcc/ssa-range-gori.cc
+++ b/gcc/ssa-range-gori.cc
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "wide-int.h"
#include "ssa-range.h"
+#include "fold-const.h"
// Construct a range_def_chain
@@ -470,9 +471,81 @@ gori_map::dump(FILE *f)
}
}
+// Set range from an SSA_NAME's available range. If there is no
+// available range, build a range for its entire domain.
-// Overloaded get_tree_range to perform substitution of NAME wth
-// RANGE_OF_NAME if expr happens to match it.
+irange
+range_from_ssa (tree ssa)
+{
+ tree type = TREE_TYPE (ssa);
+ gcc_checking_assert (irange::supports_type_p (type));
+ if (!SSA_NAME_RANGE_INFO (ssa) || POINTER_TYPE_P (type))
+ return irange (type);
+ wide_int min, max;
+ enum value_range_kind kind = get_range_info (ssa, &min, &max);
+ return irange (kind, type, min, max);
+}
+
+// This function returns a range for tree node EXPR in R. Return
+// false if ranges are not supported.
+
+bool
+get_tree_range (irange &r, tree expr)
+{
+ tree type;
+ switch (TREE_CODE (expr))
+ {
+ case INTEGER_CST:
+ if (!TREE_OVERFLOW_P (expr))
+ r = irange (expr, expr);
+ else
+ // If we encounter an overflow, simply punt and drop to varying
+ // since we hvae no idea how it will be used.
+ r.set_varying (TREE_TYPE (expr));
+ return true;
+
+ case SSA_NAME:
+ if (irange::supports_ssa_p (expr))
+ {
+ r = range_from_ssa (expr);
+ return true;
+ }
+ break;
+
+ case ADDR_EXPR:
+ {
+ // handle &var which can show up in phi arguments
+ bool ov;
+ type = TREE_TYPE (expr);
+ if (irange::supports_type_p (type))
+ {
+ if (tree_single_nonzero_warnv_p (expr, &ov))
+ r = range_nonzero (type);
+ else
+ r.set_varying (type);
+ return true;
+ }
+ break;
+ }
+
+ default:
+ if (TYPE_P (expr))
+ type = expr;
+ else
+ type = TREE_TYPE (expr);
+ if (irange::supports_type_p (type))
+ {
+ // Set to range for this type.
+ r.set_varying (type);
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+// Same but perform substitution of NAME with RANGE_OF_NAME if expr
+// happens to match it.
static bool
get_tree_range (irange &r, tree expr, tree name, irange *range_of_name)
diff --git a/gcc/ssa-range-gori.h b/gcc/ssa-range-gori.h
index e98b309..080564b 100644
--- a/gcc/ssa-range-gori.h
+++ b/gcc/ssa-range-gori.h
@@ -186,6 +186,7 @@ private:
irange m_bool_one; /* Boolean true cached. */
};
-
+bool get_tree_range (irange &r, tree expr);
+irange range_from_ssa (tree ssa);
#endif // GCC_SSA_RANGE_GORI_H
diff --git a/gcc/ssa-range.h b/gcc/ssa-range.h
index 44201a0..80ce3f6 100644
--- a/gcc/ssa-range.h
+++ b/gcc/ssa-range.h
@@ -28,7 +28,6 @@ along with GCC; see the file COPYING3. If not see
extern gimple_stmt_iterator gsi_outgoing_range_stmt (basic_block bb);
extern gimple *gimple_outgoing_range_stmt_p (basic_block bb);
extern gimple *gimple_outgoing_edge_range_p (irange &r, edge e);
-extern bool get_tree_range (irange &r, tree expr);
// This is the basic range generator interface.
//
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index b186c25..1d4fe3b 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -22,8 +22,8 @@ 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.
+// Set to one if irange is a standalone class, or zero if irange is
+// just value_range_base underneath.
#define USE_IRANGE 1
#if USE_IRANGE
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 0d80f1e..d0e2583 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -1754,8 +1754,7 @@ range_misc::adjust_range_with_loop (irange &ir, struct loop *loop,
/* Like in PR19590, scev can return a constant function. */
if (is_gimple_min_invariant (chrec))
{
- extern bool get_tree_range (irange &r, tree expr);
- get_tree_range (ir, chrec);
+ ir = irange (chrec, chrec);
return;
}