diff mbox series

Clean up irange self tests.

Message ID 20201109143827.616223-1-aldyh@redhat.com
State New
Headers show
Series Clean up irange self tests. | expand

Commit Message

Aldy Hernandez Nov. 9, 2020, 2:38 p.m. UTC
Currently we have all the irange and range-op tests in range-op.cc.
This patch splits them up into the appropriate file (irange
tests in value-range.cc and range-op tests in range-op.cc).  The patch
also splits up the tests themselves by functionality.  It's not perfect,
but significantly better than the mess we had.

Andrew, does this split look good to you?

If so, I'll push once bootstrap passes.
Aldy

gcc/ChangeLog:

	* function-tests.c (test_ranges): Call range_op_tests.
	* range-op.cc (build_range3): Move to value-range.cc.
	(range3_tests): Same.
	(int_range_max_tests): Same.
	(multi_precision_range_tests): Same.
	(range_tests): Same.
	(operator_tests): Split up...
	(range_op_tests): Split up...
	(range_op_cast_tests): ...here.
	(range_op_lshift_tests): ...here.
	(range_op_rshift_tests): ...here.
	(range_op_bitwise_and_tests): ...here.
	* selftest.h (range_op_tests): New.
	* value-range.cc (build_range3): New.
	(range_tests_irange3): New.
	(range_tests_int_range_max): New.
	(range_tests_legacy): New.
	(range_tests_misc): New.
	(range_tests): New.
---
 gcc/function-tests.c |   1 +
 gcc/range-op.cc      | 643 ++++++++++---------------------------------
 gcc/selftest.h       |   1 +
 gcc/value-range.cc   | 380 +++++++++++++++++++++++++
 4 files changed, 532 insertions(+), 493 deletions(-)

Comments

Andrew MacLeod Nov. 9, 2020, 2:42 p.m. UTC | #1
On 11/9/20 9:38 AM, Aldy Hernandez wrote:
> Currently we have all the irange and range-op tests in range-op.cc.
> This patch splits them up into the appropriate file (irange
> tests in value-range.cc and range-op tests in range-op.cc).  The patch
> also splits up the tests themselves by functionality.  It's not perfect,
> but significantly better than the mess we had.
>
> Andrew, does this split look good to you?

OK.
  I always thought it was a little weird that the range tests were in 
the range-ops file anyway :-)
>
> If so, I'll push once bootstrap passes.
> Aldy
>
> gcc/ChangeLog:
>
> 	* function-tests.c (test_ranges): Call range_op_tests.
> 	* range-op.cc (build_range3): Move to value-range.cc.
> 	(range3_tests): Same.
> 	(int_range_max_tests): Same.
> 	(multi_precision_range_tests): Same.
> 	(range_tests): Same.
> 	(operator_tests): Split up...
> 	(range_op_tests): Split up...
> 	(range_op_cast_tests): ...here.
> 	(range_op_lshift_tests): ...here.
> 	(range_op_rshift_tests): ...here.
> 	(range_op_bitwise_and_tests): ...here.
> 	* selftest.h (range_op_tests): New.
> 	* value-range.cc (build_range3): New.
> 	(range_tests_irange3): New.
> 	(range_tests_int_range_max): New.
> 	(range_tests_legacy): New.
> 	(range_tests_misc): New.
> 	(range_tests): New.
> ---
>
Aldy Hernandez Nov. 9, 2020, 2:44 p.m. UTC | #2
Yes, it was leftover from the original irange work years ago.

Aldy

On Mon, Nov 9, 2020 at 3:42 PM Andrew MacLeod <amacleod@redhat.com> wrote:
>
> On 11/9/20 9:38 AM, Aldy Hernandez wrote:
> > Currently we have all the irange and range-op tests in range-op.cc.
> > This patch splits them up into the appropriate file (irange
> > tests in value-range.cc and range-op tests in range-op.cc).  The patch
> > also splits up the tests themselves by functionality.  It's not perfect,
> > but significantly better than the mess we had.
> >
> > Andrew, does this split look good to you?
>
> OK.
>   I always thought it was a little weird that the range tests were in
> the range-ops file anyway :-)
> >
> > If so, I'll push once bootstrap passes.
> > Aldy
> >
> > gcc/ChangeLog:
> >
> >       * function-tests.c (test_ranges): Call range_op_tests.
> >       * range-op.cc (build_range3): Move to value-range.cc.
> >       (range3_tests): Same.
> >       (int_range_max_tests): Same.
> >       (multi_precision_range_tests): Same.
> >       (range_tests): Same.
> >       (operator_tests): Split up...
> >       (range_op_tests): Split up...
> >       (range_op_cast_tests): ...here.
> >       (range_op_lshift_tests): ...here.
> >       (range_op_rshift_tests): ...here.
> >       (range_op_bitwise_and_tests): ...here.
> >       * selftest.h (range_op_tests): New.
> >       * value-range.cc (build_range3): New.
> >       (range_tests_irange3): New.
> >       (range_tests_int_range_max): New.
> >       (range_tests_legacy): New.
> >       (range_tests_misc): New.
> >       (range_tests): New.
> > ---
> >
>
diff mbox series

Patch

diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index 65364588734..92f1acf780e 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -580,6 +580,7 @@  test_ranges ()
   function *fun = DECL_STRUCT_FUNCTION (fndecl);
   push_cfun (fun);
   range_tests ();
+  range_op_tests ();
   pop_cfun ();
 }
 
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index f38f02e8d27..bbb2a61ae35 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3361,7 +3361,6 @@  range_cast (irange &r, tree type)
 
 #if CHECKING_P
 #include "selftest.h"
-#include "stor-layout.h"
 
 namespace selftest
 {
@@ -3369,413 +3368,21 @@  namespace selftest
 #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))
-
-static int_range<3>
-build_range3 (int a, int b, int c, int d, int e, int f)
-{
-  int_range<3> i1 (INT (a), INT (b));
-  int_range<3> i2 (INT (c), INT (d));
-  int_range<3> i3 (INT (e), INT (f));
-  i1.union_ (i2);
-  i1.union_ (i3);
-  return i1;
-}
-
-static void
-range3_tests ()
-{
-  typedef int_range<3> int_range3;
-  int_range3 r0, r1, r2;
-  int_range3 i1, i2, i3;
-
-  // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
-  r0 = int_range3 (INT (10), INT (20));
-  r1 = int_range3 (INT (5), INT (8));
-  r0.union_ (r1);
-  r1 = int_range3 (INT (1), INT (3));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20));
-
-  // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
-  r1 = int_range3 (INT (-5), INT (0));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20));
-
-  // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
-  r1 = int_range3 (INT (50), INT (60));
-  r0 = int_range3 (INT (10), INT (20));
-  r0.union_ (int_range3 (INT (30), INT (40)));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == build_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 = int_range3 (INT (70), INT (80));
-  r0.union_ (r1);
-
-  r2 = build_range3 (10, 20, 30, 40, 50, 60);
-  r2.union_ (int_range3 (INT (70), INT (80)));
-  ASSERT_TRUE (r0 == r2);
-
-  // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (6), INT (35));
-  r0.union_ (r1);
-  r1 = int_range3 (INT (6), INT (40));
-  r1.union_ (int_range3 (INT (50), INT (60)));
-  ASSERT_TRUE (r0 == r1);
-
-  // [10,20][30,40][50,60] U [6,60] => [6,60].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (6), INT (60));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60)));
-
-  // [10,20][30,40][50,60] U [6,70] => [6,70].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (6), INT (70));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70)));
-
-  // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (35), INT (70));
-  r0.union_ (r1);
-  r1 = int_range3 (INT (10), INT (20));
-  r1.union_ (int_range3 (INT (30), INT (70)));
-  ASSERT_TRUE (r0 == r1);
-
-  // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (15), INT (35));
-  r0.union_ (r1);
-  r1 = int_range3 (INT (10), INT (40));
-  r1.union_ (int_range3 (INT (50), INT (60)));
-  ASSERT_TRUE (r0 == r1);
-
-  // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
-  r0 = build_range3 (10, 20, 30, 40, 50, 60);
-  r1 = int_range3 (INT (35), INT (35));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
-}
-
-static void
-int_range_max_tests ()
-{
-  int_range_max big;
-  unsigned int nrange;
-
-  // Build a huge multi-range range.
-  for (nrange = 0; nrange < 50; ++nrange)
-    {
-      int_range<1> tmp (INT (nrange*10), INT (nrange*10 + 5));
-      big.union_ (tmp);
-    }
-  ASSERT_TRUE (big.num_pairs () == nrange);
-
-  // Verify that we can copy it without loosing precision.
-  int_range_max copy (big);
-  ASSERT_TRUE (copy.num_pairs () == nrange);
-
-  // Inverting it should produce one more sub-range.
-  big.invert ();
-  ASSERT_TRUE (big.num_pairs () == nrange + 1);
-
-  int_range<1> tmp (INT (5), INT (37));
-  big.intersect (tmp);
-  ASSERT_TRUE (big.num_pairs () == 4);
-
-  // Test that [10,10][20,20] does NOT contain 15.
-  {
-    int_range_max i1 (build_int_cst (integer_type_node, 10),
-		      build_int_cst (integer_type_node, 10));
-    int_range_max i2 (build_int_cst (integer_type_node, 20),
-		      build_int_cst (integer_type_node, 20));
-    i1.union_ (i2);
-    ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15)));
-  }
-
-}
-
-static void
-multi_precision_range_tests ()
-{
-  // Test truncating copy to int_range<1>.
-  int_range<3> big = build_range3 (10, 20, 30, 40, 50, 60);
-  int_range<1> small = big;
-  ASSERT_TRUE (small == int_range<1> (INT (10), INT (60)));
-
-  // Test truncating copy to int_range<2>.
-  int_range<2> medium = big;
-  ASSERT_TRUE (!medium.undefined_p ());
-
-  // Test that a truncating copy of [MIN,20][22,40][80,MAX]
-  // ends up as a conservative anti-range of ~[21,21].
-  big = int_range<3> (vrp_val_min (integer_type_node), INT (20));
-  big.union_ (int_range<1> (INT (22), INT (40)));
-  big.union_ (int_range<1> (INT (80), vrp_val_max (integer_type_node)));
-  small = big;
-  ASSERT_TRUE (small == int_range<1> (INT (21), INT (21), VR_ANTI_RANGE));
-
-  // Copying a legacy symbolic to an int_range should normalize the
-  // symbolic at copy time.
-  {
-    tree ssa = make_ssa_name (integer_type_node);
-    value_range legacy_range (ssa, INT (25));
-    int_range<2> copy = legacy_range;
-    ASSERT_TRUE (copy == int_range<2>  (vrp_val_min (integer_type_node),
-					INT (25)));
-
-    // Test that copying ~[abc_23, abc_23] to a multi-range yields varying.
-    legacy_range = value_range (ssa, ssa, VR_ANTI_RANGE);
-    copy = legacy_range;
-    ASSERT_TRUE (copy.varying_p ());
-  }
-
-  range3_tests ();
-}
+#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N))
 
 static void
-operator_tests ()
-{
-  tree min = vrp_val_min (integer_type_node);
-  tree max = vrp_val_max (integer_type_node);
-  tree tiny = fold_build2 (PLUS_EXPR, integer_type_node, min,
-			   build_one_cst (integer_type_node));
-  int_range_max res;
-  int_range_max i1 (tiny, max);
-  int_range_max i2 (build_int_cst (integer_type_node, 255),
-		    build_int_cst (integer_type_node, 255));
-
-  // [MIN+1, MAX] = OP1 & 255: OP1 is VARYING
-  op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
-  ASSERT_TRUE (res == int_range<1> (integer_type_node));
-
-  // VARYING = OP1 & 255: OP1 is VARYING
-  i1 = int_range<1> (integer_type_node);
-  op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
-  ASSERT_TRUE (res == int_range<1> (integer_type_node));
-
-  // Test that 0x808.... & 0x8.... still contains 0x8....
-  // for a large set of numbers.
-  {
-    tree big_type = long_long_unsigned_type_node;
-    // big_num = 0x808,0000,0000,0000
-    tree big_num = fold_build2 (LSHIFT_EXPR, big_type,
-				build_int_cst (big_type, 0x808),
-				build_int_cst (big_type, 48));
-    op_bitwise_and.fold_range (res, big_type,
-			       int_range <1> (big_type),
-			       int_range <1> (big_num, big_num));
-    // val = 0x8,0000,0000,0000
-    tree val = fold_build2 (LSHIFT_EXPR, big_type,
-			    build_int_cst (big_type, 0x8),
-			    build_int_cst (big_type, 48));
-    ASSERT_TRUE (res.contains_p (val));
-  }
-
-  // unsigned: [3, MAX] = OP1 >> 1
-  {
-    int_range_max lhs (build_int_cst (unsigned_type_node, 3),
-		       TYPE_MAX_VALUE (unsigned_type_node));
-    int_range_max one (build_one_cst (unsigned_type_node),
-		       build_one_cst (unsigned_type_node));
-    int_range_max op1;
-    op_rshift.op1_range (op1, unsigned_type_node, lhs, one);
-    ASSERT_FALSE (op1.contains_p (UINT (3)));
-  }
-
-  // signed: [3, MAX] = OP1 >> 1
-  {
-    int_range_max lhs (INT (3), TYPE_MAX_VALUE (integer_type_node));
-    int_range_max one (INT (1), INT (1));
-    int_range_max op1;
-    op_rshift.op1_range (op1, integer_type_node, lhs, one);
-    ASSERT_FALSE (op1.contains_p (INT (-2)));
-  }
-
-  // This is impossible, so OP1 should be [].
-  // signed: [MIN, MIN] = OP1 >> 1
-  {
-    int_range_max lhs (TYPE_MIN_VALUE (integer_type_node),
-		       TYPE_MIN_VALUE (integer_type_node));
-    int_range_max one (INT (1), INT (1));
-    int_range_max op1;
-    op_rshift.op1_range (op1, integer_type_node, lhs, one);
-    ASSERT_TRUE (op1.undefined_p ());
-  }
-
-  // signed: ~[-1] = OP1 >> 31
-  if (TYPE_PRECISION (integer_type_node) > 31)
-    {
-      int_range_max lhs (INT (-1), INT (-1), VR_ANTI_RANGE);
-      int_range_max shift (INT (31), INT (31));
-      int_range_max op1;
-      op_rshift.op1_range (op1, integer_type_node, lhs, shift);
-      int_range_max negatives = range_negatives (integer_type_node);
-      negatives.intersect (op1);
-      ASSERT_TRUE (negatives.undefined_p ());
-    }
-
-  if (TYPE_PRECISION (unsigned_type_node) > 31)
-    {
-      // unsigned VARYING = op1 << 1 should be VARYING.
-      int_range<2> lhs (unsigned_type_node);
-      int_range<2> shift (INT (1), INT (1));
-      int_range_max op1;
-      op_lshift.op1_range (op1, unsigned_type_node, lhs, shift);
-      ASSERT_TRUE (op1.varying_p ());
-
-      // 0 = op1 << 1  should be [0,0], [0x8000000, 0x8000000].
-      int_range<2> zero (UINT (0), UINT (0));
-      op_lshift.op1_range (op1, unsigned_type_node, zero, shift);
-      ASSERT_TRUE (op1.num_pairs () == 2);
-      // Remove the [0,0] range.
-      op1.intersect (zero);
-      ASSERT_TRUE (op1.num_pairs () == 1);
-      //  op1 << 1   should be [0x8000,0x8000] << 1,
-      //  which should result in [0,0].
-      int_range_max result;
-      op_lshift.fold_range (result, unsigned_type_node, op1, shift);
-      ASSERT_TRUE (result == zero);
-    }
-  // signed VARYING = op1 << 1 should be VARYING.
-  if (TYPE_PRECISION (integer_type_node) > 31)
-    {
-      // unsigned VARYING = op1 << 1  hould be VARYING.
-      int_range<2> lhs (integer_type_node);
-      int_range<2> shift (INT (1), INT (1));
-      int_range_max op1;
-      op_lshift.op1_range (op1, integer_type_node, lhs, shift);
-      ASSERT_TRUE (op1.varying_p ());
-
-      //  0 = op1 << 1  should be [0,0], [0x8000000, 0x8000000].
-      int_range<2> zero (INT (0), INT (0));
-      op_lshift.op1_range (op1, integer_type_node, zero, shift);
-      ASSERT_TRUE (op1.num_pairs () == 2);
-      // Remove the [0,0] range.
-      op1.intersect (zero);
-      ASSERT_TRUE (op1.num_pairs () == 1);
-      //  op1 << 1   shuould be [0x8000,0x8000] << 1,
-      //  which should result in [0,0].
-      int_range_max result;
-      op_lshift.fold_range (result, unsigned_type_node, op1, shift);
-      ASSERT_TRUE (result == zero);
-    }
-}
-
-// Run all of the selftests within this file.
-
-void
-range_tests ()
+range_op_cast_tests ()
 {
-  tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
-  int_range<1> i1, i2, i3;
-  int_range<1> r0, r1, rold;
-
-  // Test 1-bit signed integer union.
-  // [-1,-1] U [0,0] = VARYING.
-  tree one_bit_type = build_nonstandard_integer_type (1, 0);
-  tree one_bit_min = vrp_val_min (one_bit_type);
-  tree one_bit_max = vrp_val_max (one_bit_type);
-  {
-    int_range<2> min (one_bit_min, one_bit_min);
-    int_range<2> max (one_bit_max, one_bit_max);
-    max.union_ (min);
-    ASSERT_TRUE (max.varying_p ());
-  }
-
-  // Test inversion of 1-bit signed integers.
-  {
-    int_range<2> min (one_bit_min, one_bit_min);
-    int_range<2> max (one_bit_max, one_bit_max);
-    int_range<2> t;
-    t = min;
-    t.invert ();
-    ASSERT_TRUE (t == max);
-    t = max;
-    t.invert ();
-    ASSERT_TRUE (t == min);
-  }
-
-  // Test that NOT(255) is [0..254] in 8-bit land.
-  int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE);
-  ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)));
-
-  // Test that NOT(0) is [1..255] in 8-bit land.
-  int_range<1> not_zero = range_nonzero (unsigned_char_type_node);
-  ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255)));
-
-  // Check that [0,127][0x..ffffff80,0x..ffffff]
-  //  => ~[128, 0x..ffffff7f].
-  r0 = int_range<1> (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 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff]
-  // r0 = [0,127][0x..ffffff80,0x..fffffff].
-  r0.union_ (r1);
-  // r1 = [128, 0x..ffffff7f].
-  r1 = int_range<1> (UINT128(128),
-		     fold_build2 (MINUS_EXPR, u128_type,
-				  build_minus_one_cst (u128_type),
-				  UINT128(128)));
-  r0.invert ();
-  ASSERT_TRUE (r0 == r1);
-
+  int_range<1> r0, r1, r2, rold;
   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 ());
 
+  // If a range is in any way outside of the range for the converted
+  // to range, default to the range for the new type.
   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 = int_range<1> (UINT (0), UINT (5));
-  r0.invert ();
-  ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint));
-
-  // Check that ~[10,MAX] => [0,9] for unsigned int.
-  r0 = int_range<1> (UINT(10), maxuint);
-  r0.invert ();
-  ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9)));
-
-  // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
-  r0 = int_range<1> (UINT128 (0), UINT128 (5), VR_ANTI_RANGE);
-  r1 = int_range<1> (UINT128(6), build_minus_one_cst (u128_type));
-  ASSERT_TRUE (r0 == r1);
-
-  // Check that [~5] is really [-MIN,4][6,MAX].
-  r0 = int_range<1> (INT (5), INT (5), VR_ANTI_RANGE);
-  r1 = int_range<1> (minint, INT (4));
-  r1.union_ (int_range<1> (INT (6), maxint));
-  ASSERT_FALSE (r1.undefined_p ());
-  ASSERT_TRUE (r0 == r1);
-
-  r1 = int_range<1> (INT (5), INT (5));
-  int_range<1> r2 (r1);
-  ASSERT_TRUE (r1 == r2);
-
-  r1 = int_range<1> (INT (5), INT (10));
-
-  r1 = int_range<1> (integer_type_node,
-		     wi::to_wide (INT (5)), wi::to_wide (INT (10)));
-  ASSERT_TRUE (r1.contains_p (INT (7)));
-
-  r1 = int_range<1> (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.
   if (TYPE_PRECISION (TREE_TYPE (maxint))
       > TYPE_PRECISION (short_integer_type_node))
     {
@@ -3865,25 +3472,6 @@  range_tests ()
 	       TYPE_MAX_VALUE (short_unsigned_type_node));
   ASSERT_TRUE (r0 == r1);
 
-  // NOT([10,20]) ==> [-MIN,9][21,MAX].
-  r0 = r1 = int_range<1> (INT (10), INT (20));
-  r2 = int_range<1> (minint, INT(9));
-  r2.union_ (int_range<1> (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);
-
-  // Test that booleans and their inverse work as expected.
-  r0 = range_zero (boolean_type_node);
-  ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node),
-				   build_zero_cst (boolean_type_node)));
-  r0.invert ();
-  ASSERT_TRUE (r0 == int_range<1> (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.
   //
@@ -3910,84 +3498,153 @@  range_tests ()
   r2 = int_range<1> (INT (1), INT (32767));
   r1.union_ (r2);
   ASSERT_TRUE (r0 == r1);
+}
 
-  // 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);
+static void
+range_op_lshift_tests ()
+{
+  // Test that 0x808.... & 0x8.... still contains 0x8....
+  // for a large set of numbers.
+  {
+    int_range_max res;
+    tree big_type = long_long_unsigned_type_node;
+    // big_num = 0x808,0000,0000,0000
+    tree big_num = fold_build2 (LSHIFT_EXPR, big_type,
+				build_int_cst (big_type, 0x808),
+				build_int_cst (big_type, 48));
+    op_bitwise_and.fold_range (res, big_type,
+			       int_range <1> (big_type),
+			       int_range <1> (big_num, big_num));
+    // val = 0x8,0000,0000,0000
+    tree val = fold_build2 (LSHIFT_EXPR, big_type,
+			    build_int_cst (big_type, 0x8),
+			    build_int_cst (big_type, 48));
+    ASSERT_TRUE (res.contains_p (val));
+  }
 
-  // [10,20] U [15, 30] => [10, 30].
-  r0 = int_range<1> (INT (10), INT (20));
-  r1 = int_range<1> (INT (15), INT (30));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30)));
-
-  // [15,40] U [] => [15,40].
-  r0 = int_range<1> (INT (15), INT (40));
-  r1.set_undefined ();
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40)));
-
-  // [10,20] U [10,10] => [10,20].
-  r0 = int_range<1> (INT (10), INT (20));
-  r1 = int_range<1> (INT (10), INT (10));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20)));
-
-  // [10,20] U [9,9] => [9,20].
-  r0 = int_range<1> (INT (10), INT (20));
-  r1 = int_range<1> (INT (9), INT (9));
-  r0.union_ (r1);
-  ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20)));
-
-  // [10,20] ^ [15,30] => [15,20].
-  r0 = int_range<1> (INT (10), INT (20));
-  r1 = int_range<1> (INT (15), INT (30));
-  r0.intersect (r1);
-  ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20)));
-
-  // 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 zero_p().
-  r0 = int_range<1> (INT (0), INT (0));
-  ASSERT_TRUE (r0.zero_p ());
-
-  // Test nonzero_p().
-  r0 = int_range<1> (INT (0), INT (0));
-  r0.invert ();
-  ASSERT_TRUE (r0.nonzero_p ());
-
-  // test legacy interaction
-  // r0 = ~[1,1]
-  r0 = int_range<1> (UINT (1), UINT (1), VR_ANTI_RANGE);
-  // r1 = ~[3,3]
-  r1 = int_range<1> (UINT (3), UINT (3), VR_ANTI_RANGE);
-
-  // vv = [0,0][2,2][4, MAX]
-  int_range<3> vv = r0;
-  vv.intersect (r1);
-
-  ASSERT_TRUE (vv.contains_p (UINT (2)));
-  ASSERT_TRUE (vv.num_pairs () == 3);
-
-  // create r0 as legacy [1,1]
-  r0 = int_range<1> (UINT (1), UINT (1));
-  // And union it with  [0,0][2,2][4,MAX] multi range
-  r0.union_ (vv);
-  // The result should be [0,2][4,MAX], or ~[3,3]  but it must contain 2
-  ASSERT_TRUE (r0.contains_p (UINT (2)));
-
-
-  multi_precision_range_tests ();
-  int_range_max_tests ();
-  operator_tests ();
+  if (TYPE_PRECISION (unsigned_type_node) > 31)
+    {
+      // unsigned VARYING = op1 << 1 should be VARYING.
+      int_range<2> lhs (unsigned_type_node);
+      int_range<2> shift (INT (1), INT (1));
+      int_range_max op1;
+      op_lshift.op1_range (op1, unsigned_type_node, lhs, shift);
+      ASSERT_TRUE (op1.varying_p ());
+
+      // 0 = op1 << 1  should be [0,0], [0x8000000, 0x8000000].
+      int_range<2> zero (UINT (0), UINT (0));
+      op_lshift.op1_range (op1, unsigned_type_node, zero, shift);
+      ASSERT_TRUE (op1.num_pairs () == 2);
+      // Remove the [0,0] range.
+      op1.intersect (zero);
+      ASSERT_TRUE (op1.num_pairs () == 1);
+      //  op1 << 1   should be [0x8000,0x8000] << 1,
+      //  which should result in [0,0].
+      int_range_max result;
+      op_lshift.fold_range (result, unsigned_type_node, op1, shift);
+      ASSERT_TRUE (result == zero);
+    }
+  // signed VARYING = op1 << 1 should be VARYING.
+  if (TYPE_PRECISION (integer_type_node) > 31)
+    {
+      // unsigned VARYING = op1 << 1  hould be VARYING.
+      int_range<2> lhs (integer_type_node);
+      int_range<2> shift (INT (1), INT (1));
+      int_range_max op1;
+      op_lshift.op1_range (op1, integer_type_node, lhs, shift);
+      ASSERT_TRUE (op1.varying_p ());
+
+      //  0 = op1 << 1  should be [0,0], [0x8000000, 0x8000000].
+      int_range<2> zero (INT (0), INT (0));
+      op_lshift.op1_range (op1, integer_type_node, zero, shift);
+      ASSERT_TRUE (op1.num_pairs () == 2);
+      // Remove the [0,0] range.
+      op1.intersect (zero);
+      ASSERT_TRUE (op1.num_pairs () == 1);
+      //  op1 << 1   shuould be [0x8000,0x8000] << 1,
+      //  which should result in [0,0].
+      int_range_max result;
+      op_lshift.fold_range (result, unsigned_type_node, op1, shift);
+      ASSERT_TRUE (result == zero);
+    }
+}
+
+static void
+range_op_rshift_tests ()
+{
+  // unsigned: [3, MAX] = OP1 >> 1
+  {
+    int_range_max lhs (build_int_cst (unsigned_type_node, 3),
+		       TYPE_MAX_VALUE (unsigned_type_node));
+    int_range_max one (build_one_cst (unsigned_type_node),
+		       build_one_cst (unsigned_type_node));
+    int_range_max op1;
+    op_rshift.op1_range (op1, unsigned_type_node, lhs, one);
+    ASSERT_FALSE (op1.contains_p (UINT (3)));
+  }
+
+  // signed: [3, MAX] = OP1 >> 1
+  {
+    int_range_max lhs (INT (3), TYPE_MAX_VALUE (integer_type_node));
+    int_range_max one (INT (1), INT (1));
+    int_range_max op1;
+    op_rshift.op1_range (op1, integer_type_node, lhs, one);
+    ASSERT_FALSE (op1.contains_p (INT (-2)));
+  }
+
+  // This is impossible, so OP1 should be [].
+  // signed: [MIN, MIN] = OP1 >> 1
+  {
+    int_range_max lhs (TYPE_MIN_VALUE (integer_type_node),
+		       TYPE_MIN_VALUE (integer_type_node));
+    int_range_max one (INT (1), INT (1));
+    int_range_max op1;
+    op_rshift.op1_range (op1, integer_type_node, lhs, one);
+    ASSERT_TRUE (op1.undefined_p ());
+  }
+
+  // signed: ~[-1] = OP1 >> 31
+  if (TYPE_PRECISION (integer_type_node) > 31)
+    {
+      int_range_max lhs (INT (-1), INT (-1), VR_ANTI_RANGE);
+      int_range_max shift (INT (31), INT (31));
+      int_range_max op1;
+      op_rshift.op1_range (op1, integer_type_node, lhs, shift);
+      int_range_max negatives = range_negatives (integer_type_node);
+      negatives.intersect (op1);
+      ASSERT_TRUE (negatives.undefined_p ());
+    }
+}
+
+static void
+range_op_bitwise_and_tests ()
+{
+  int_range_max res;
+  tree min = vrp_val_min (integer_type_node);
+  tree max = vrp_val_max (integer_type_node);
+  tree tiny = fold_build2 (PLUS_EXPR, integer_type_node, min,
+			   build_one_cst (integer_type_node));
+  int_range_max i1 (tiny, max);
+  int_range_max i2 (build_int_cst (integer_type_node, 255),
+		    build_int_cst (integer_type_node, 255));
+
+  // [MIN+1, MAX] = OP1 & 255: OP1 is VARYING
+  op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
+  ASSERT_TRUE (res == int_range<1> (integer_type_node));
+
+  // VARYING = OP1 & 255: OP1 is VARYING
+  i1 = int_range<1> (integer_type_node);
+  op_bitwise_and.op1_range (res, integer_type_node, i1, i2);
+  ASSERT_TRUE (res == int_range<1> (integer_type_node));
+}
+
+void
+range_op_tests ()
+{
+  range_op_rshift_tests ();
+  range_op_lshift_tests ();
+  range_op_bitwise_and_tests ();
+  range_op_cast_tests ();
 }
 
 } // namespace selftest
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 6c6c7f28675..963e074b4d2 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -248,6 +248,7 @@  extern void ordered_hash_map_tests_cc_tests ();
 extern void predict_c_tests ();
 extern void pretty_print_c_tests ();
 extern void range_tests ();
+extern void range_op_tests ();
 extern void read_rtl_function_c_tests ();
 extern void rtl_tests_c_tests ();
 extern void sbitmap_c_tests ();
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 5827e812216..1ce928b9d97 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2090,3 +2090,383 @@  DEFINE_INT_RANGE_INSTANCE(2)
 DEFINE_INT_RANGE_INSTANCE(3)
 DEFINE_INT_RANGE_INSTANCE(255)
 DEFINE_INT_RANGE_GC_STUBS(1)
+
+#if CHECKING_P
+#include "selftest.h"
+
+namespace selftest
+{
+#define INT(N) build_int_cst (integer_type_node, (N))
+#define UINT(N) build_int_cstu (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))
+
+static int_range<3>
+build_range3 (int a, int b, int c, int d, int e, int f)
+{
+  int_range<3> i1 (INT (a), INT (b));
+  int_range<3> i2 (INT (c), INT (d));
+  int_range<3> i3 (INT (e), INT (f));
+  i1.union_ (i2);
+  i1.union_ (i3);
+  return i1;
+}
+
+static void
+range_tests_irange3 ()
+{
+  typedef int_range<3> int_range3;
+  int_range3 r0, r1, r2;
+  int_range3 i1, i2, i3;
+
+  // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
+  r0 = int_range3 (INT (10), INT (20));
+  r1 = int_range3 (INT (5), INT (8));
+  r0.union_ (r1);
+  r1 = int_range3 (INT (1), INT (3));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20));
+
+  // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
+  r1 = int_range3 (INT (-5), INT (0));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20));
+
+  // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
+  r1 = int_range3 (INT (50), INT (60));
+  r0 = int_range3 (INT (10), INT (20));
+  r0.union_ (int_range3 (INT (30), INT (40)));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == build_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 = int_range3 (INT (70), INT (80));
+  r0.union_ (r1);
+
+  r2 = build_range3 (10, 20, 30, 40, 50, 60);
+  r2.union_ (int_range3 (INT (70), INT (80)));
+  ASSERT_TRUE (r0 == r2);
+
+  // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (6), INT (35));
+  r0.union_ (r1);
+  r1 = int_range3 (INT (6), INT (40));
+  r1.union_ (int_range3 (INT (50), INT (60)));
+  ASSERT_TRUE (r0 == r1);
+
+  // [10,20][30,40][50,60] U [6,60] => [6,60].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (6), INT (60));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60)));
+
+  // [10,20][30,40][50,60] U [6,70] => [6,70].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (6), INT (70));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70)));
+
+  // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (35), INT (70));
+  r0.union_ (r1);
+  r1 = int_range3 (INT (10), INT (20));
+  r1.union_ (int_range3 (INT (30), INT (70)));
+  ASSERT_TRUE (r0 == r1);
+
+  // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (15), INT (35));
+  r0.union_ (r1);
+  r1 = int_range3 (INT (10), INT (40));
+  r1.union_ (int_range3 (INT (50), INT (60)));
+  ASSERT_TRUE (r0 == r1);
+
+  // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
+  r0 = build_range3 (10, 20, 30, 40, 50, 60);
+  r1 = int_range3 (INT (35), INT (35));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
+}
+
+static void
+range_tests_int_range_max ()
+{
+  int_range_max big;
+  unsigned int nrange;
+
+  // Build a huge multi-range range.
+  for (nrange = 0; nrange < 50; ++nrange)
+    {
+      int_range<1> tmp (INT (nrange*10), INT (nrange*10 + 5));
+      big.union_ (tmp);
+    }
+  ASSERT_TRUE (big.num_pairs () == nrange);
+
+  // Verify that we can copy it without loosing precision.
+  int_range_max copy (big);
+  ASSERT_TRUE (copy.num_pairs () == nrange);
+
+  // Inverting it should produce one more sub-range.
+  big.invert ();
+  ASSERT_TRUE (big.num_pairs () == nrange + 1);
+
+  int_range<1> tmp (INT (5), INT (37));
+  big.intersect (tmp);
+  ASSERT_TRUE (big.num_pairs () == 4);
+
+  // Test that [10,10][20,20] does NOT contain 15.
+  {
+    int_range_max i1 (build_int_cst (integer_type_node, 10),
+		      build_int_cst (integer_type_node, 10));
+    int_range_max i2 (build_int_cst (integer_type_node, 20),
+		      build_int_cst (integer_type_node, 20));
+    i1.union_ (i2);
+    ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15)));
+  }
+}
+
+static void
+range_tests_legacy ()
+{
+  // Test truncating copy to int_range<1>.
+  int_range<3> big = build_range3 (10, 20, 30, 40, 50, 60);
+  int_range<1> small = big;
+  ASSERT_TRUE (small == int_range<1> (INT (10), INT (60)));
+
+  // Test truncating copy to int_range<2>.
+  int_range<2> medium = big;
+  ASSERT_TRUE (!medium.undefined_p ());
+
+  // Test that a truncating copy of [MIN,20][22,40][80,MAX]
+  // ends up as a conservative anti-range of ~[21,21].
+  big = int_range<3> (vrp_val_min (integer_type_node), INT (20));
+  big.union_ (int_range<1> (INT (22), INT (40)));
+  big.union_ (int_range<1> (INT (80), vrp_val_max (integer_type_node)));
+  small = big;
+  ASSERT_TRUE (small == int_range<1> (INT (21), INT (21), VR_ANTI_RANGE));
+
+  // Copying a legacy symbolic to an int_range should normalize the
+  // symbolic at copy time.
+  {
+    tree ssa = make_ssa_name (integer_type_node);
+    value_range legacy_range (ssa, INT (25));
+    int_range<2> copy = legacy_range;
+    ASSERT_TRUE (copy == int_range<2>  (vrp_val_min (integer_type_node),
+					INT (25)));
+
+    // Test that copying ~[abc_23, abc_23] to a multi-range yields varying.
+    legacy_range = value_range (ssa, ssa, VR_ANTI_RANGE);
+    copy = legacy_range;
+    ASSERT_TRUE (copy.varying_p ());
+  }
+}
+
+static void
+range_tests_misc ()
+{
+  tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
+  int_range<1> i1, i2, i3;
+  int_range<1> r0, r1, rold;
+
+  // Test 1-bit signed integer union.
+  // [-1,-1] U [0,0] = VARYING.
+  tree one_bit_type = build_nonstandard_integer_type (1, 0);
+  tree one_bit_min = vrp_val_min (one_bit_type);
+  tree one_bit_max = vrp_val_max (one_bit_type);
+  {
+    int_range<2> min (one_bit_min, one_bit_min);
+    int_range<2> max (one_bit_max, one_bit_max);
+    max.union_ (min);
+    ASSERT_TRUE (max.varying_p ());
+  }
+
+  // Test inversion of 1-bit signed integers.
+  {
+    int_range<2> min (one_bit_min, one_bit_min);
+    int_range<2> max (one_bit_max, one_bit_max);
+    int_range<2> t;
+    t = min;
+    t.invert ();
+    ASSERT_TRUE (t == max);
+    t = max;
+    t.invert ();
+    ASSERT_TRUE (t == min);
+  }
+
+  // Test that NOT(255) is [0..254] in 8-bit land.
+  int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE);
+  ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)));
+
+  // Test that NOT(0) is [1..255] in 8-bit land.
+  int_range<1> not_zero = range_nonzero (unsigned_char_type_node);
+  ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255)));
+
+  // Check that [0,127][0x..ffffff80,0x..ffffff]
+  //  => ~[128, 0x..ffffff7f].
+  r0 = int_range<1> (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 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff]
+  // r0 = [0,127][0x..ffffff80,0x..fffffff].
+  r0.union_ (r1);
+  // r1 = [128, 0x..ffffff7f].
+  r1 = int_range<1> (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);
+
+  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 = int_range<1> (UINT (0), UINT (5));
+  r0.invert ();
+  ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint));
+
+  // Check that ~[10,MAX] => [0,9] for unsigned int.
+  r0 = int_range<1> (UINT(10), maxuint);
+  r0.invert ();
+  ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9)));
+
+  // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
+  r0 = int_range<1> (UINT128 (0), UINT128 (5), VR_ANTI_RANGE);
+  r1 = int_range<1> (UINT128(6), build_minus_one_cst (u128_type));
+  ASSERT_TRUE (r0 == r1);
+
+  // Check that [~5] is really [-MIN,4][6,MAX].
+  r0 = int_range<1> (INT (5), INT (5), VR_ANTI_RANGE);
+  r1 = int_range<1> (minint, INT (4));
+  r1.union_ (int_range<1> (INT (6), maxint));
+  ASSERT_FALSE (r1.undefined_p ());
+  ASSERT_TRUE (r0 == r1);
+
+  r1 = int_range<1> (INT (5), INT (5));
+  int_range<1> r2 (r1);
+  ASSERT_TRUE (r1 == r2);
+
+  r1 = int_range<1> (INT (5), INT (10));
+
+  r1 = int_range<1> (integer_type_node,
+		     wi::to_wide (INT (5)), wi::to_wide (INT (10)));
+  ASSERT_TRUE (r1.contains_p (INT (7)));
+
+  r1 = int_range<1> (SCHAR (0), SCHAR (20));
+  ASSERT_TRUE (r1.contains_p (SCHAR(15)));
+  ASSERT_FALSE (r1.contains_p (SCHAR(300)));
+
+  // NOT([10,20]) ==> [-MIN,9][21,MAX].
+  r0 = r1 = int_range<1> (INT (10), INT (20));
+  r2 = int_range<1> (minint, INT(9));
+  r2.union_ (int_range<1> (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);
+
+  // Test that booleans and their inverse work as expected.
+  r0 = range_zero (boolean_type_node);
+  ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node),
+				   build_zero_cst (boolean_type_node)));
+  r0.invert ();
+  ASSERT_TRUE (r0 == int_range<1> (build_one_cst (boolean_type_node),
+				   build_one_cst (boolean_type_node)));
+
+  // 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);
+
+  // [10,20] U [15, 30] => [10, 30].
+  r0 = int_range<1> (INT (10), INT (20));
+  r1 = int_range<1> (INT (15), INT (30));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30)));
+
+  // [15,40] U [] => [15,40].
+  r0 = int_range<1> (INT (15), INT (40));
+  r1.set_undefined ();
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40)));
+
+  // [10,20] U [10,10] => [10,20].
+  r0 = int_range<1> (INT (10), INT (20));
+  r1 = int_range<1> (INT (10), INT (10));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20)));
+
+  // [10,20] U [9,9] => [9,20].
+  r0 = int_range<1> (INT (10), INT (20));
+  r1 = int_range<1> (INT (9), INT (9));
+  r0.union_ (r1);
+  ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20)));
+
+  // [10,20] ^ [15,30] => [15,20].
+  r0 = int_range<1> (INT (10), INT (20));
+  r1 = int_range<1> (INT (15), INT (30));
+  r0.intersect (r1);
+  ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20)));
+
+  // 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 zero_p().
+  r0 = int_range<1> (INT (0), INT (0));
+  ASSERT_TRUE (r0.zero_p ());
+
+  // Test nonzero_p().
+  r0 = int_range<1> (INT (0), INT (0));
+  r0.invert ();
+  ASSERT_TRUE (r0.nonzero_p ());
+
+  // test legacy interaction
+  // r0 = ~[1,1]
+  r0 = int_range<1> (UINT (1), UINT (1), VR_ANTI_RANGE);
+  // r1 = ~[3,3]
+  r1 = int_range<1> (UINT (3), UINT (3), VR_ANTI_RANGE);
+
+  // vv = [0,0][2,2][4, MAX]
+  int_range<3> vv = r0;
+  vv.intersect (r1);
+
+  ASSERT_TRUE (vv.contains_p (UINT (2)));
+  ASSERT_TRUE (vv.num_pairs () == 3);
+
+  // create r0 as legacy [1,1]
+  r0 = int_range<1> (UINT (1), UINT (1));
+  // And union it with  [0,0][2,2][4,MAX] multi range
+  r0.union_ (vv);
+  // The result should be [0,2][4,MAX], or ~[3,3]  but it must contain 2
+  ASSERT_TRUE (r0.contains_p (UINT (2)));
+}
+
+void
+range_tests ()
+{
+  range_tests_legacy ();
+  range_tests_irange3 ();
+  range_tests_int_range_max ();
+  range_tests_misc ();
+}
+
+} // namespace selftest
+
+#endif // CHECKING_P