Handle anti-ranges of MIN,MAX uniformly.
authorAldy Hernandez <aldyh@redhat.com>
Mon, 26 Apr 2021 17:24:09 +0000 (19:24 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Mon, 26 Apr 2021 20:28:04 +0000 (22:28 +0200)
The -fstrict-enums comment in the VR_ANTI_RANGE handling code is out
of date, as out-of-range ranges have already been handled by this
time.  I've removed it.

Furthermore, optimizing ~[MIN,MAX] as VARYING instead of UNDEFINED is
an old idiom.  I've been wanting to change it for a while, but have
only remembered late in the release cycle when it was too risky.

What I've chosen to do in this case is fall through to the code that
normalizes the range.  This will correctly turn ~[MIN,MAX] into
UNDEFINED, yet leaving things alone in the case of -fstrict-enums
where [MIN,MAX] may not necessarily include the entire range of the
underlying precision.  For example, if the domain of a strict enum is
[3,5] setting a VR_ANTI_RANGE of ~[3,5] should not cause neither
VR_UNDEFINED nor VR_VARYING, but just plain ~[3,5].

This is similar to what we do for -fstrict-enums when we set a range
of [3,5].  We leave it as a VR_RANGE, instead of upgrading it to
VR_VARYING.

gcc/ChangeLog:

* value-range.cc (irange::irange_set_1bit_anti_range): Add assert.
(irange::set): Call irange_set_1bit_anti_range for handling all
1-bit ranges.  Fall through on ~[MIN,MAX].

gcc/value-range.cc

index dc76ed7d036544ce6edb7b7b42e326e1c21f490c..2decd08d155551ec91084929a4424a6922f25af6 100644 (file)
@@ -203,6 +203,8 @@ irange::irange_set_1bit_anti_range (tree min, tree max)
   else
     {
       // The only alternative is [MIN,MAX], which is the empty range.
+      gcc_checking_assert (vrp_val_is_min (min));
+      gcc_checking_assert (vrp_val_is_max (max));
       set_undefined ();
     }
   if (flag_checking)
@@ -313,29 +315,21 @@ irange::set (tree min, tree max, value_range_kind kind)
   // Anti-ranges that can be represented as ranges should be so.
   if (kind == VR_ANTI_RANGE)
     {
-      /* For -fstrict-enums we may receive out-of-range ranges so consider
-         values < -INF and values > INF as -INF/INF as well.  */
       bool is_min = vrp_val_is_min (min);
       bool is_max = vrp_val_is_max (max);
-      tree type = TREE_TYPE (min);
 
       if (is_min && is_max)
        {
-         /* We cannot deal with empty ranges, drop to varying.
-            ???  This could be VR_UNDEFINED instead.  */
-         set_varying (type);
-         return;
+         // Fall through.  This will either be normalized as
+         // VR_UNDEFINED if the anti-range spans the entire
+         // precision, or it will remain an VR_ANTI_RANGE in the case
+         // of an -fstrict-enum where [MIN,MAX] is less than the span
+         // of underlying precision.
        }
-      else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
-              && (is_min || is_max))
+      else if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
        {
-         /* Non-empty boolean ranges can always be represented
-            as a singleton range.  */
-         if (is_min)
-           min = max = vrp_val_max (TREE_TYPE (min));
-         else
-           min = max = vrp_val_min (TREE_TYPE (min));
-         kind = VR_RANGE;
+         irange_set_1bit_anti_range (min, max);
+         return;
        }
       else if (is_min)
         {