Denormalize VR_VARYING to VR_RANGE before passing it to set_range_info_raw.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 29 Apr 2022 20:46:25 +0000 (22:46 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Sun, 1 May 2022 12:18:06 +0000 (14:18 +0200)
We are ICEing in set_range_info_raw because value_range_kind cannot be
VR_VARYING, since SSA_NAME_RANGE_TYPE can only hold VR_RANGE /
VR_ANTI_RANGE.  Most of the time setting a VR_VARYING as a global
range makes no sense.  However, we can have a range spanning the
entire domain (VR_RANGE of [MIN,MAX] which is essentially a
VR_VARYING), if the nonzero bits are set.

This was working before because set_range_info_raw allows setting
VR_RANGE of [MIN, MAX].  However, when going through an irange, we
normalize this to a VR_VARYING, thus causing the ICE.  It's
interesting that other calls to set_range_info with an irange haven't
triggered this.

One solution would be to just ignore VR_VARYING and bail, since
set_range_info* is really an update of the current range semantic
wise.  After all, we keep the nonzero bits which provide additional
info.  But this would be a change in behavior, so not suitable until
after GCC 12 is released.  So in order to keep with current behavior
we can just denormalize the varying to VR_RANGE.

Tested on x86-64 Linux.

    PR tree-optimization/105432

gcc/ChangeLog:

* tree-ssanames.cc (set_range_info): Denormalize VR_VARYING to
VR_RANGE before passing a piecewise range to set_range_info_raw.

gcc/tree-ssanames.cc

index c957597..05536cd 100644 (file)
@@ -395,8 +395,17 @@ set_range_info (tree name, enum value_range_kind range_type,
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
 
-  /* A range of the entire domain is really no range at all.  */
   tree type = TREE_TYPE (name);
+  if (range_type == VR_VARYING)
+    {
+      /* SSA_NAME_RANGE_TYPE can only hold a VR_RANGE or
+        VR_ANTI_RANGE.  Denormalize VR_VARYING to VR_RANGE.  */
+      range_type = VR_RANGE;
+      gcc_checking_assert (min == wi::min_value (type));
+      gcc_checking_assert (max == wi::max_value (type));
+    }
+
+  /* A range of the entire domain is really no range at all.  */
   if (min == wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type))
       && max == wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
     {