@@ -200,11 +200,10 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name NAME. */
void
-set_range_info (tree name, enum value_range_type range_type,
+set_range_info (tree name,
const wide_int_ref &min, const wide_int_ref &max)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
- gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
@@ -219,16 +218,12 @@ set_range_info (tree name, enum value_range_type range_type,
ri->set_nonzero_bits (wi::shwi (-1, precision));
}
- /* Record the range type. */
- if (SSA_NAME_RANGE_TYPE (name) != range_type)
- SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
-
/* Set the values. */
ri->set_min (min);
ri->set_max (max);
/* If it is a range, try to improve nonzero_bits from the min/max. */
- if (range_type == VR_RANGE)
+ if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) < 0)
{
wide_int xorv = ri->get_min () ^ ri->get_max ();
if (xorv != 0)
@@ -248,6 +243,7 @@ get_range_info (const_tree name, wide_int *min, wide_int *max)
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
gcc_assert (min && max);
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ value_range_type range_type;
/* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision. */
@@ -255,9 +251,22 @@ get_range_info (const_tree name, wide_int *min, wide_int *max)
> 2 * HOST_BITS_PER_WIDE_INT))
return VR_VARYING;
- *min = ri->get_min ();
- *max = ri->get_max ();
- return SSA_NAME_RANGE_TYPE (name);
+ /* If max < min, it is VR_ANTI_RANGE. */
+ if (wi::cmp (ri->get_max (), ri->get_min (), TYPE_SIGN (TREE_TYPE (name))) < 0)
+ {
+ /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1]. */
+ range_type = VR_ANTI_RANGE;
+ *min = wi::add (ri->get_max (), 1);
+ *max = wi::sub (ri->get_min (), 1);
+ }
+ else
+ {
+ /* Otherwise (when min <= max), it is VR_RANGE. */
+ range_type = VR_RANGE;
+ *min = ri->get_min ();
+ *max = ri->get_max ();
+ }
+ return range_type;
}
/* Change non-zero bits bitmask of NAME. */
@@ -267,7 +276,7 @@ set_nonzero_bits (tree name, const wide_int_ref &mask)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
if (SSA_NAME_RANGE_INFO (name) == NULL)
- set_range_info (name, VR_RANGE,
+ set_range_info (name,
TYPE_MIN_VALUE (TREE_TYPE (name)),
TYPE_MAX_VALUE (TREE_TYPE (name)));
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
@@ -495,7 +504,8 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
/* Creates a duplicate of the range_info_def at RANGE_INFO of type
RANGE_TYPE for use by the SSA name NAME. */
void
-duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
+duplicate_ssa_name_range_info (tree name,
+ enum value_range_type range_type ATTRIBUTE_UNUSED,
struct range_info_def *range_info)
{
struct range_info_def *new_range_info;
@@ -513,8 +523,6 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
memcpy (new_range_info, range_info, size);
- gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
- SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
SSA_NAME_RANGE_INFO (name) = new_range_info;
}
@@ -68,7 +68,7 @@ struct GTY ((variable_size)) range_info_def {
enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
/* Sets the value range to SSA. */
-extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
+extern void set_range_info (tree, const wide_int_ref &,
const wide_int_ref &);
/* Gets the value range from SSA. */
extern enum value_range_type get_range_info (const_tree, wide_int *,
@@ -6915,7 +6915,7 @@ remove_range_assertions (void)
&& all_imm_uses_in_stmt_or_feed_cond (var, stmt,
single_pred (bb)))
{
- set_range_info (var, SSA_NAME_RANGE_TYPE (lhs),
+ set_range_info (var,
SSA_NAME_RANGE_INFO (lhs)->get_min (),
SSA_NAME_RANGE_INFO (lhs)->get_max ());
maybe_set_nonzero_bits (bb, var);
@@ -10238,12 +10238,35 @@ vrp_finalize (void)
|| (vr_value[i]->type == VR_UNDEFINED))
continue;
- if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
- && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
- && (vr_value[i]->type == VR_RANGE
- || vr_value[i]->type == VR_ANTI_RANGE))
- set_range_info (name, vr_value[i]->type, vr_value[i]->min,
- vr_value[i]->max);
+ if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+ && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
+ && (vr_value[i]->type == VR_RANGE
+ || vr_value[i]->type == VR_ANTI_RANGE))
+ {
+ if (vr_value[i]->type == VR_RANGE)
+ set_range_info (name, vr_value[i]->min, vr_value[i]->max);
+ else if (vr_value[i]->type == VR_ANTI_RANGE)
+ {
+ /* VR_ANTI_RANGE
+ ~[min, max] is encoded compactly as
+ [max + 1, min - 1] without additional attributes.
+ When min value > max value, we know that it is
+ VR_ANTI_RANGE; it is VR_RANGE otherwise. */
+
+ if (TYPE_UNSIGNED (TREE_TYPE (name))
+ && integer_zerop (vr_value[i]->min)
+ && integer_zerop (vr_value[i]->max))
+ /* ~[0,0] anti-range is represented as range. */
+ set_range_info (name,
+ build_int_cst (TREE_TYPE (name), 1),
+ TYPE_MAXVAL (TREE_TYPE (name)));
+ else
+ set_range_info (name,
+ wi::add (vr_value[i]->max, 1),
+ wi::sub (vr_value[i]->min, 1));
+ }
+ }
+
}
/* Free allocated memory. */