diff options
author | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-27 04:07:31 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2019-06-27 04:07:31 +0000 |
commit | 43e0b376cbb83c77a14be605c3858309b496d88a (patch) | |
tree | f53b38d924ac79a0320d696390fa7f908ddb40c8 | |
parent | 7b6bb739b6651354dbc7173f9758c32217a9b7d4 (diff) | |
download | gcc-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.c | 1093 | ||||
-rw-r--r-- | gcc/range.h | 7 | ||||
-rw-r--r-- | gcc/ssa-range-gori.cc | 77 | ||||
-rw-r--r-- | gcc/ssa-range-gori.h | 3 | ||||
-rw-r--r-- | gcc/ssa-range.h | 1 | ||||
-rw-r--r-- | gcc/tree-vrp.h | 4 | ||||
-rw-r--r-- | gcc/vr-values.c | 3 |
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; } |