[gcc/devel/ranger] Fix operator_rshift::op1_range to work better with signed types.

Aldy Hernandez aldyh@gcc.gnu.org
Tue Jun 9 08:23:02 GMT 2020


https://gcc.gnu.org/g:df663310eec78e530cb3360434791352139f496f

commit df663310eec78e530cb3360434791352139f496f
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Tue Jun 9 07:49:32 2020 +0200

    Fix operator_rshift::op1_range to work better with signed types.
    
    We do this by discarding impossible ranges from the incoming LHS.

Diff:
---
 gcc/range-op.cc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 70904677225..b3fb57f9e77 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1602,9 +1602,14 @@ operator_rshift::op1_range (irange &r,
   tree shift;
   if (op2.singleton_p (&shift))
     {
+      // Folding the original operation may discard some impossible
+      // ranges from the LHS.
+      widest_irange lhs_refined;
+      op_rshift.fold_range (lhs_refined, type, value_range (type), op2);
+      lhs_refined.intersect (lhs);
       widest_irange shift_range (shift, shift);
       widest_irange lb, ub;
-      op_lshift.fold_range (lb, type, lhs, shift_range);
+      op_lshift.fold_range (lb, type, lhs_refined, shift_range);
       //    LHS
       // 0000 0111 = OP1 >> 3
       //
@@ -1621,7 +1626,7 @@ operator_rshift::op1_range (irange &r,
       r = lb;
       r.union_ (ub);
 
-      if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+      if (!lhs_refined.contains_p (build_zero_cst (type)))
 	{
 	  mask_range.invert ();
 	  r.intersect (mask_range);
@@ -3479,6 +3484,48 @@ operator_tests ()
 			    build_int_cst (big_type, 48));
     ASSERT_TRUE (res.contains_p (val));
   }
+
+  // unsigned: [3, MAX] = OP1 >> 1
+  {
+    widest_irange lhs (build_int_cst (unsigned_type_node, 3),
+		       TYPE_MAX_VALUE (unsigned_type_node));
+    widest_irange one (build_one_cst (unsigned_type_node),
+		       build_one_cst (unsigned_type_node));
+    widest_irange op1;
+    op_rshift.op1_range (op1, unsigned_type_node, lhs, one);
+    ASSERT_FALSE (op1.contains_p (UINT (3)));
+  }
+
+  // signed: [3, MAX] = OP1 >> 1
+  {
+    widest_irange lhs (INT (3), TYPE_MAX_VALUE (integer_type_node));
+    widest_irange one (INT (1), INT (1));
+    widest_irange 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
+  {
+    widest_irange lhs (TYPE_MIN_VALUE (integer_type_node),
+		       TYPE_MIN_VALUE (integer_type_node));
+    widest_irange one (INT (1), INT (1));
+    widest_irange op1;
+    op_rshift.op1_range (op1, integer_type_node, lhs, one);
+    ASSERT_TRUE (op1.undefined_p ());
+  }
+
+  // signed: ~[-1] = OP1 >> 31
+  {
+    widest_irange lhs (INT (-1), INT (-1), VR_ANTI_RANGE);
+    widest_irange shift (INT (31), INT (31));
+    widest_irange op1;
+    op_rshift.op1_range (op1, integer_type_node, lhs, shift);
+    widest_irange negatives = range_negatives (integer_type_node);
+    negatives.intersect (op1);
+    ASSERT_TRUE (negatives.undefined_p ());
+  }
 }
 
 // Run all of the selftests within this file.


More information about the Gcc-cvs mailing list