Freeing a spare-bit to store wrapped attribute by going back to representing VR_ANTI_RANGE as [max + 1, min - 1] in SSA_NAME.
Thanks, Kugan gcc/ChangeLog: 2015-01-16 Kugan Vivekanandarajah <kug...@linaro.org> * tree-ssanames.c (set_range_info): Change range info representation and represent VR_ANTI_RANGE as [max + 1, min - 1]. (get_range_info): Likewise. (set_nonzero_bits): Likewise. (duplicate_ssa_name_range_info): Likewise. * tree-ssanames.h (set_range_info): Change prototype. (get_range_info): Likewise. (set_nonzero_bits): Likewise. (duplicate_ssa_name_range_info): Likewise. * tree-vrp.c (remove_range_assertions): Use new representation. (vrp_finalize): Likewise.
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 9c39f65..744dc43 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -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; } diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index a7eeb8f..0d4b212 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -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 *, diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 2e0b158..9b7695d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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. */