I'm still thinking about this one...
Is there a subtle reason why we're avoiding unsigned truncating
conversions of the form:
[X, +INF]
If the X fits in the new type, why can't we just build [X, +INF] in the
new type? See attached patch.
If there isn't, OK for trunk?
commit b2e8c9baeeca3e321957d205b2c4c8b83b9bc754
Author: Aldy Hernandez <al...@redhat.com>
Date: Fri Sep 14 12:02:42 2018 +0200
* wide-int-range.cc (wide_int_range_convert): Allow unsigned
truncating conversions that will fit in the new type.
diff --git a/gcc/wide-int-range.cc b/gcc/wide-int-range.cc
index a85fe9f9ad7..4e323a63206 100644
--- a/gcc/wide-int-range.cc
+++ b/gcc/wide-int-range.cc
@@ -768,6 +768,24 @@ wide_int_range_convert (wide_int &min, wide_int &max,
return (!wi::eq_p (min, wi::min_value (outer_prec, outer_sign))
|| !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)));
}
+ /* Unsigned truncating conversions whose lower bound fits, but whose
+ upper bound is +INF can be handled straightforwardly. This will
+ handle things like:
+
+ [1,+INF] (i.e. ~[0,0]) from long unsigned to unsigned short
+ [1000, +INF] from long unsigned to unsigned short. */
+ if (inner_sign == UNSIGNED
+ && inner_sign == outer_sign
+ && inner_prec > outer_prec
+ && wi::le_p (vr0_min,
+ wi::mask (outer_prec, false, inner_prec),
+ UNSIGNED)
+ && vr0_max == wi::max_value (inner_prec, UNSIGNED))
+ {
+ min = wide_int::from (vr0_min, outer_prec, inner_sign);
+ max = wi::mask (outer_prec, false, outer_prec);
+ return true;
+ }
return false;
}