[PATCH] Use extremes of underlying type when building VR_ANTI_RANGEs.
Aldy Hernandez
aldyh@redhat.com
Tue Nov 10 10:41:48 GMT 2020
[Andrew, this doesn't fix a PR per se. It's just something I stumbled
upon in my other -fstrict-enums fixes. It passes tests. What do you
think? Should we push it?]
Imagine an enum in an -fstrict-enums world:
enum foo { zero, one, two, three };
Building the inverse of [0,3] currently yields VARYING (instead of
[4,+INF]). This is because the setter sees 0 and 3 as the extremes of
the type, and per the current code, calculates the inverse to VARYING.
BTW, it really should be UNDEFINED, but this is legacy code I'm afraid
to touch:
if (is_min && is_max)
{
/* We cannot deal with empty ranges, drop to varying.
??? This could be VR_UNDEFINED instead. */
set_varying (type);
return;
}
However, the extremes of a VARYING are the extremes of the underlying
type ([0, 0xff..ff]), even in the presence of -fstrict-enums.
This fixes the setter to use the extremes of the underlying type.
gcc/ChangeLog:
* value-range.cc (irange::set): Use wi::{min,max}_value
instead of TYPE_{MIN,MAX}_VALUE when building anti-ranges.
(range_tests_strict_enum): New tests.
---
gcc/value-range.cc | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index f83a824a982..bbd7d69a766 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -274,11 +274,13 @@ 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);
+ unsigned prec = TYPE_PRECISION (type);
+ signop sign = TYPE_SIGN (type);
+ wide_int type_max = wi::max_value (prec, sign);
+ wide_int type_min = wi::min_value (prec, sign);
+ bool is_min = wi::to_wide (min) == type_min;
+ bool is_max = wi::to_wide (max) == type_max;
if (is_min && is_max)
{
@@ -302,14 +304,14 @@ irange::set (tree min, tree max, value_range_kind kind)
{
tree one = build_int_cst (TREE_TYPE (max), 1);
min = int_const_binop (PLUS_EXPR, max, one);
- max = vrp_val_max (TREE_TYPE (max));
+ max = wide_int_to_tree (type, type_max);
kind = VR_RANGE;
}
else if (is_max)
{
tree one = build_int_cst (TREE_TYPE (min), 1);
max = int_const_binop (MINUS_EXPR, min, one);
- min = vrp_val_min (TREE_TYPE (min));
+ min = wide_int_to_tree (type, type_min);
kind = VR_RANGE;
}
}
@@ -2276,6 +2278,19 @@ range_tests_strict_enum ()
ir1 = vr1;
ASSERT_TRUE (ir1 == vr1);
ASSERT_FALSE (ir1.varying_p ());
+
+ // Legacy inversion of [0, 3] should be [4, MAX].
+ vr1 = int_range<1> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3));
+ vr1.invert ();
+ tree type_max = wide_int_to_tree (rtype,
+ wi::max_value (TYPE_PRECISION (rtype),
+ TYPE_SIGN (rtype)));
+ ASSERT_TRUE (vr1 == int_range<1> (build_int_cstu (rtype, 4), type_max));
+
+ // Multi-range inversion of [0, 3] should be [4, MAX].
+ ir1 = int_range<2> (build_int_cstu (rtype, 0), build_int_cstu (rtype, 3));
+ ir1.invert ();
+ ASSERT_TRUE (vr1 == int_range<2> (build_int_cstu (rtype, 4), type_max));
}
static void
--
2.26.2
More information about the Gcc-patches
mailing list