@@ -3150,7 +3150,7 @@ determine_block_size (tree len, rtx len_rtx,
*probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
if (TREE_CODE (len) == SSA_NAME)
- range_type = get_range_info (len, &min, &max);
+ range_type = get_range_info (len, &min, &max, NULL);
if (range_type == VR_RANGE)
{
if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
@@ -1812,13 +1812,15 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
&& SSA_NAME_RANGE_INFO (node))
{
wide_int min, max, nonzero_bits;
- value_range_type range_type = get_range_info (node, &min, &max);
+ bool wrapped;
+ value_range_type range_type = get_range_info (node, &min, &max, &wrapped);
if (range_type == VR_VARYING)
pp_printf (buffer, "# RANGE VR_VARYING");
else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
{
pp_printf (buffer, "# RANGE ");
+ pp_printf (buffer, "WRAPPED = %s ", wrapped ? "true" : "false");
pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~");
pp_wide_int (buffer, min, TYPE_SIGN (TREE_TYPE (node)));
pp_printf (buffer, ", ");
@@ -262,7 +262,7 @@ get_range_pos_neg (tree arg)
if (TREE_CODE (arg) != SSA_NAME)
return 3;
wide_int arg_min, arg_max;
- while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+ while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE)
{
gimple g = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (g)
@@ -344,7 +344,7 @@ get_min_precision (tree arg, signop sign)
if (TREE_CODE (arg) != SSA_NAME)
return prec + (orig_sign != sign);
wide_int arg_min, arg_max;
- while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+ while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE)
{
gimple g = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (g)
@@ -18,6 +18,6 @@ int foo (int i, int j)
return j;
}
-/* { dg-final { scan-tree-dump "res_.: \\\[1, 1\\\]" "vrp1" } } */
+/* { dg-final { scan-tree-dump "res_.: NOWRAPP \\\[1, 1\\\]" "vrp1" } } */
/* { dg-final { scan-tree-dump-not "Threaded" "vrp1" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
@@ -574,8 +574,8 @@ fini_copy_prop (void)
&& !SSA_NAME_RANGE_INFO (copy_of[i].value)
&& var_bb == copy_of_bb)
duplicate_ssa_name_range_info (copy_of[i].value,
- SSA_NAME_RANGE_TYPE (var),
- SSA_NAME_RANGE_INFO (var));
+ SSA_NAME_RANGE_INFO (var),
+ SSA_NAME_RANGE_WRAPPED_P (var));
}
}
@@ -1245,7 +1245,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
{
tree lhs = gimple_assign_lhs (new_stmt);
SSA_NAME_RANGE_INFO (lhs) = NULL;
- SSA_NAME_ANTI_RANGE_P (lhs) = 0;
}
gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
remove_phi_node (&bsi, false);
@@ -1315,7 +1314,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
{
tree lhs = gimple_get_lhs (stmt);
SSA_NAME_RANGE_INFO (lhs) = NULL;
- SSA_NAME_ANTI_RANGE_P (lhs) = 0;
}
/* In case this is a stmt that is not unconditionally executed
when the target loop header is executed and the stmt may
@@ -165,7 +165,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
gphi_iterator gsi;
/* Either for VAR itself... */
- rtype = get_range_info (var, &minv, &maxv);
+ rtype = get_range_info (var, &minv, &maxv, NULL);
/* Or for PHI results in loop->header where VAR is used as
PHI argument from the loop preheader edge. */
for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -173,7 +173,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
gphi *phi = gsi.phi ();
wide_int minc, maxc;
if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
- && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
+ && (get_range_info (gimple_phi_result (phi), &minc, &maxc, NULL)
== VR_RANGE))
{
if (rtype != VR_RANGE)
@@ -192,7 +192,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
involved. */
if (wi::gt_p (minv, maxv, sgn))
{
- rtype = get_range_info (var, &minv, &maxv);
+ rtype = get_range_info (var, &minv, &maxv, NULL);
break;
}
}
@@ -4107,8 +4107,8 @@ eliminate_dom_walker::before_dom_children (basic_block b)
&& !SSA_NAME_RANGE_INFO (sprime)
&& b == sprime_b)
duplicate_ssa_name_range_info (sprime,
- SSA_NAME_RANGE_TYPE (lhs),
- SSA_NAME_RANGE_INFO (lhs));
+ SSA_NAME_RANGE_INFO (lhs),
+ SSA_NAME_RANGE_WRAPPED_P (lhs));
}
/* Inhibit the use of an inserted PHI on a loop header when
@@ -201,7 +201,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
void
set_range_info (tree name,
- const wide_int_ref &min, const wide_int_ref &max)
+ const wide_int_ref &min, const wide_int_ref &max, bool is_wrapped)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
@@ -221,6 +221,7 @@ set_range_info (tree name,
/* Set the values. */
ri->set_min (min);
ri->set_max (max);
+ SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped;
/* If it is a range, try to improve nonzero_bits from the min/max. */
if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) < 0)
@@ -238,7 +239,7 @@ set_range_info (tree name,
is used to determine if MIN and MAX are valid values. */
enum value_range_type
-get_range_info (const_tree name, wide_int *min, wide_int *max)
+get_range_info (const_tree name, wide_int *min, wide_int *max, bool *is_wrapped)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
gcc_assert (min && max);
@@ -266,6 +267,8 @@ get_range_info (const_tree name, wide_int *min, wide_int *max)
*min = ri->get_min ();
*max = ri->get_max ();
}
+ if (is_wrapped)
+ *is_wrapped = SSA_NAME_RANGE_WRAPPED_P (name);
return range_type;
}
@@ -278,7 +281,8 @@ set_nonzero_bits (tree name, const wide_int_ref &mask)
if (SSA_NAME_RANGE_INFO (name) == NULL)
set_range_info (name,
TYPE_MIN_VALUE (TREE_TYPE (name)),
- TYPE_MAX_VALUE (TREE_TYPE (name)));
+ TYPE_MAX_VALUE (TREE_TYPE (name)),
+ false);
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
ri->set_nonzero_bits (mask);
}
@@ -505,14 +509,13 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
RANGE_TYPE for use by the SSA name NAME. */
void
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 *range_info,
+ bool is_wrapped)
{
struct range_info_def *new_range_info;
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
gcc_assert (!SSA_NAME_RANGE_INFO (name));
- gcc_assert (!SSA_NAME_ANTI_RANGE_P (name));
if (!range_info)
return;
@@ -523,6 +526,7 @@ duplicate_ssa_name_range_info (tree name,
new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
memcpy (new_range_info, range_info, size);
+ SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped;
SSA_NAME_RANGE_INFO (name) = new_range_info;
}
@@ -547,8 +551,9 @@ duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt)
struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name);
if (old_range_info)
- duplicate_ssa_name_range_info (new_name, SSA_NAME_RANGE_TYPE (name),
- old_range_info);
+ duplicate_ssa_name_range_info (new_name,
+ old_range_info,
+ SSA_NAME_RANGE_WRAPPED_P (name));
}
return new_name;
@@ -69,10 +69,10 @@ 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, const wide_int_ref &,
- const wide_int_ref &);
+ const wide_int_ref &, bool);
/* Gets the value range from SSA. */
extern enum value_range_type get_range_info (const_tree, wide_int *,
- wide_int *);
+ wide_int *, bool *);
extern void set_nonzero_bits (tree, const wide_int_ref &);
extern wide_int get_nonzero_bits (const_tree);
extern void init_ssanames (struct function *, int);
@@ -92,8 +92,9 @@ extern struct ptr_info_def *get_ptr_info (tree);
extern tree copy_ssa_name_fn (struct function *, tree, gimple);
extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
extern tree duplicate_ssa_name_fn (struct function *, tree, gimple);
-extern void duplicate_ssa_name_range_info (tree, enum value_range_type,
- struct range_info_def *);
+extern void duplicate_ssa_name_range_info (tree,
+ struct range_info_def *,
+ bool);
extern void release_defs (gimple);
extern void replace_ssa_name_symbol (tree, tree);
@@ -2553,7 +2553,7 @@ vect_recog_divmod_pattern (vec<gimple> *stmts,
wide_int oprnd0_min, oprnd0_max;
int msb = 1;
- if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
+ if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max, NULL) == VR_RANGE)
{
if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype)))
msb = 0;
@@ -103,6 +103,9 @@ struct value_range_d
tree min;
tree max;
+ /* Set to true if values in this value range could wrapp. */
+ bool is_wrapped;
+
/* Set of SSA names whose value ranges are equivalent to this one.
This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */
bitmap equiv;
@@ -110,7 +113,7 @@ struct value_range_d
typedef struct value_range_d value_range_t;
-#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
+#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, false, NULL }
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
@@ -447,7 +450,7 @@ set_value_range_to_varying (value_range_t *vr)
static void
set_value_range (value_range_t *vr, enum value_range_type t, tree min,
- tree max, bitmap equiv)
+ tree max, bool is_wrapped, bitmap equiv)
{
#if defined ENABLE_CHECKING
/* Check the validity of the range. */
@@ -481,6 +484,7 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
vr->type = t;
vr->min = min;
vr->max = max;
+ vr->is_wrapped = is_wrapped;
/* Since updating the equivalence set involves deep copying the
bitmaps, only do it if absolutely necessary. */
@@ -509,7 +513,7 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
static void
set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
- tree min, tree max, bitmap equiv)
+ tree min, tree max, bool is_wrapped, bitmap equiv)
{
/* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
if (t == VR_UNDEFINED)
@@ -527,7 +531,7 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
if (TREE_CODE (min) != INTEGER_CST
|| TREE_CODE (max) != INTEGER_CST)
{
- set_value_range (vr, t, min, max, equiv);
+ set_value_range (vr, t, min, max, is_wrapped, equiv);
return;
}
@@ -615,7 +619,7 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
return;
}
- set_value_range (vr, t, min, max, equiv);
+ set_value_range (vr, t, min, max, is_wrapped, equiv);
}
/* Copy value range FROM into value range TO. */
@@ -623,7 +627,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
static inline void
copy_value_range (value_range_t *to, value_range_t *from)
{
- set_value_range (to, from->type, from->min, from->max, from->equiv);
+ set_value_range (to, from->type, from->min, from->max,
+ from->is_wrapped, from->equiv);
}
/* Set value range VR to a single value. This function is only called
@@ -637,7 +642,7 @@ set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv)
gcc_assert (is_gimple_min_invariant (val));
if (TREE_OVERFLOW_P (val))
val = drop_tree_overflow (val);
- set_value_range (vr, VR_RANGE, val, val, equiv);
+ set_value_range (vr, VR_RANGE, val, val, false, equiv);
}
/* Set value range VR to a non-negative range of type TYPE.
@@ -663,6 +668,7 @@ set_value_range_to_nonnegative (value_range_t *vr, tree type,
(overflow_infinity
? positive_overflow_infinity (type)
: TYPE_MAX_VALUE (type)),
+ false,
vr->equiv);
}
@@ -672,7 +678,7 @@ static inline void
set_value_range_to_nonnull (value_range_t *vr, tree type)
{
tree zero = build_int_cst (type, 0);
- set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv);
+ set_value_range (vr, VR_ANTI_RANGE, zero, zero, false, vr->equiv);
}
@@ -695,6 +701,7 @@ set_value_range_to_truthvalue (value_range_t *vr, tree type)
else
set_value_range (vr, VR_RANGE,
build_int_cst (type, 0), build_int_cst (type, 1),
+ false,
vr->equiv);
}
@@ -731,7 +738,7 @@ abs_extent_range (value_range_t *vr, tree min, tree max)
set_value_range_to_varying (vr);
return;
}
- set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
+ set_and_canonicalize_value_range (vr, VR_RANGE, min, max, false, NULL);
}
@@ -744,7 +751,7 @@ static value_range_t *
get_value_range (const_tree var)
{
static const struct value_range_d vr_const_varying
- = { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
+ = { VR_VARYING, NULL_TREE, NULL_TREE, false, NULL };
value_range_t *vr;
tree sym;
unsigned ver = SSA_NAME_VERSION (var);
@@ -842,6 +849,7 @@ update_value_range (const_tree var, value_range_t *new_vr)
is_new = old_vr->type != new_vr->type
|| !vrp_operand_equal_p (old_vr->min, new_vr->min)
|| !vrp_operand_equal_p (old_vr->max, new_vr->max)
+ || old_vr->is_wrapped != new_vr->is_wrapped
|| !vrp_bitmap_equal_p (old_vr->equiv, new_vr->equiv);
if (is_new)
@@ -856,6 +864,7 @@ update_value_range (const_tree var, value_range_t *new_vr)
set_value_range_to_varying (old_vr);
else
set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max,
+ new_vr->is_wrapped,
new_vr->equiv);
}
@@ -1745,10 +1754,10 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
this for us. */
if (cond_code == LE_EXPR)
set_and_canonicalize_value_range (vr_p, VR_RANGE,
- min, max, vr_p->equiv);
+ min, max, false, vr_p->equiv);
else if (cond_code == GT_EXPR)
set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE,
- min, max, vr_p->equiv);
+ min, max, false, vr_p->equiv);
else
gcc_unreachable ();
}
@@ -1769,7 +1778,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
max = limit;
}
- set_value_range (vr_p, range_type, min, max, vr_p->equiv);
+ set_value_range (vr_p, range_type, min, max, false, vr_p->equiv);
/* When asserting the equality VAR == LIMIT and LIMIT is another
SSA name, the new range will also inherit the equivalence set
@@ -1821,7 +1830,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
min = max = limit;
set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE,
- min, max, vr_p->equiv);
+ min, max, false, vr_p->equiv);
}
else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
{
@@ -1860,7 +1869,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
TREE_NO_WARNING (max) = 1;
}
- set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+ set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv);
}
}
else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -1900,7 +1909,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
TREE_NO_WARNING (min) = 1;
}
- set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+ set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv);
}
}
else
@@ -1932,7 +1941,7 @@ extract_range_from_ssa_name (value_range_t *vr, tree var)
if (var_vr->type != VR_VARYING)
copy_value_range (vr, var_vr);
else
- set_value_range (vr, VR_RANGE, var, var, NULL);
+ set_value_range (vr, VR_RANGE, var, var, false, NULL);
add_equivalence (&vr->equiv, var);
}
@@ -1945,11 +1954,13 @@ extract_range_from_ssa_name (value_range_t *vr, tree var)
the type does not support it. */
static tree
-vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
+vrp_int_const_binop (enum tree_code code, tree val1, tree val2, bool *is_wrapped)
{
tree res;
res = int_const_binop (code, val1, val2);
+ if (is_wrapped)
+ *is_wrapped = false;
/* If we are using unsigned arithmetic, operate symbolically
on -INF and +INF as int_const_binop only handles signed overflow. */
@@ -1993,7 +2004,10 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
else if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (val1)))
/* If the singed operation wraps then int_const_binop has done
everything we want. */
- ;
+ {
+ if (is_wrapped)
+ *is_wrapped = true;
+ }
/* Signed division of -1/0 overflows and by the time it gets here
returns NULL_TREE. */
else if (!res)
@@ -2187,6 +2201,8 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
tree min, max;
bool sop;
int cmp;
+ bool is_wrapped = false;
+ bool t_is_wrapped = false;
/* Multiplications, divisions and shifts are a bit tricky to handle,
depending on the mix of signs we have in the two ranges, we
@@ -2216,35 +2232,43 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
/* Compute the 4 cross operations. */
sop = false;
- val[0] = vrp_int_const_binop (code, vr0->min, vr1->min);
+ val[0] = vrp_int_const_binop (code, vr0->min, vr1->min, &t_is_wrapped);
if (val[0] == NULL_TREE)
sop = true;
+ if (t_is_wrapped)
+ is_wrapped = true;
if (vr1->max == vr1->min)
val[1] = NULL_TREE;
else
{
- val[1] = vrp_int_const_binop (code, vr0->min, vr1->max);
+ val[1] = vrp_int_const_binop (code, vr0->min, vr1->max, &t_is_wrapped);
if (val[1] == NULL_TREE)
sop = true;
+ if (t_is_wrapped)
+ is_wrapped = true;
}
if (vr0->max == vr0->min)
val[2] = NULL_TREE;
else
{
- val[2] = vrp_int_const_binop (code, vr0->max, vr1->min);
+ val[2] = vrp_int_const_binop (code, vr0->max, vr1->min, &t_is_wrapped);
if (val[2] == NULL_TREE)
sop = true;
+ if (t_is_wrapped)
+ is_wrapped = true;
}
if (vr0->min == vr0->max || vr1->min == vr1->max)
val[3] = NULL_TREE;
else
{
- val[3] = vrp_int_const_binop (code, vr0->max, vr1->max);
+ val[3] = vrp_int_const_binop (code, vr0->max, vr1->max, &t_is_wrapped);
if (val[3] == NULL_TREE)
sop = true;
+ if (t_is_wrapped)
+ is_wrapped = true;
}
if (sop)
@@ -2324,7 +2348,7 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
set_value_range_to_varying (vr);
}
else
- set_value_range (vr, type, min, max, NULL);
+ set_value_range (vr, type, min, max, is_wrapped, NULL);
}
/* Extract range information from a binary operation CODE based on
@@ -2341,6 +2365,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
enum value_range_type type;
tree min = NULL_TREE, max = NULL_TREE;
int cmp;
+ bool vr_is_wrapped = false;
if (!INTEGRAL_TYPE_P (expr_type)
&& !POINTER_TYPE_P (expr_type))
@@ -2640,6 +2665,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
range kind and bounds appropriately. */
wide_int tmin = wide_int::from (wmin, prec, sgn);
wide_int tmax = wide_int::from (wmax, prec, sgn);
+ vr_is_wrapped = true;
if (min_ovf == max_ovf)
{
/* No overflow or both overflow or underflow. The
@@ -2792,8 +2818,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* For operations that make the resulting range directly
proportional to the original ranges, apply the operation to
the same end of each range. */
- min = vrp_int_const_binop (code, vr0.min, vr1.min);
- max = vrp_int_const_binop (code, vr0.max, vr1.max);
+ min = vrp_int_const_binop (code, vr0.min, vr1.min, NULL);
+ max = vrp_int_const_binop (code, vr0.max, vr1.max, NULL);
}
else if (code == MIN_EXPR)
{
@@ -2917,9 +2943,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* The following should handle the wrapping and selecting
VR_ANTI_RANGE for us. */
+ vr_is_wrapped = true;
min = wide_int_to_tree (expr_type, prod0);
max = wide_int_to_tree (expr_type, prod3);
- set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
+ set_and_canonicalize_value_range (vr, VR_RANGE, min, max, vr_is_wrapped, NULL);
return;
}
@@ -3287,7 +3314,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
set_value_range_to_varying (vr);
}
else
- set_value_range (vr, type, min, max, NULL);
+ set_value_range (vr, type, min, max, vr_is_wrapped, NULL);
}
/* Extract range information from a binary expression OP0 CODE OP1 based on
@@ -3336,15 +3363,15 @@ extract_range_from_binary_expr (value_range_t *vr,
/* Try with VR0 and [-INF, OP1]. */
if (is_gimple_min_invariant (minus_p ? vr0.max : vr0.min))
- set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, NULL);
+ set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, false, NULL);
/* Try with VR0 and [OP1, +INF]. */
else if (is_gimple_min_invariant (minus_p ? vr0.min : vr0.max))
- set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), NULL);
+ set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), false, NULL);
/* Try with VR0 and [OP1, OP1]. */
else
- set_value_range (&n_vr1, VR_RANGE, op1, op1, NULL);
+ set_value_range (&n_vr1, VR_RANGE, op1, op1, false, NULL);
extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &n_vr1);
}
@@ -3360,15 +3387,15 @@ extract_range_from_binary_expr (value_range_t *vr,
/* Try with [-INF, OP0] and VR1. */
if (is_gimple_min_invariant (minus_p ? vr1.max : vr1.min))
- set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, NULL);
+ set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, false, NULL);
/* Try with [OP0, +INF] and VR1. */
else if (is_gimple_min_invariant (minus_p ? vr1.min : vr1.max))
- set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), NULL);
+ set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), false, NULL);
/* Try with [OP0, OP0] and VR1. */
else
- set_value_range (&n_vr0, VR_RANGE, op0, op0, NULL);
+ set_value_range (&n_vr0, VR_RANGE, op0, op0, false, NULL);
extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1);
}
@@ -3384,6 +3411,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
value_range_t *vr0_, tree op0_type)
{
value_range_t vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+ bool vr_is_wrapped = false;
/* VRP only operates on integral and pointer types. */
if (!(INTEGRAL_TYPE_P (op0_type)
@@ -3504,15 +3532,23 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
if (is_overflow_infinity (vr0.min))
new_min = negative_overflow_infinity (outer_type);
else
- new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
- 0, false);
+ {
+ if (!int_fits_type_p (vr0.min, outer_type))
+ vr_is_wrapped = true;
+ new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
+ 0, false);
+ }
if (is_overflow_infinity (vr0.max))
new_max = positive_overflow_infinity (outer_type);
else
- new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
- 0, false);
+ {
+ if (!int_fits_type_p (vr0.max, outer_type))
+ vr_is_wrapped = true;
+ new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
+ 0, false);
+ }
set_and_canonicalize_value_range (vr, vr0.type,
- new_min, new_max, NULL);
+ new_min, new_max, vr_is_wrapped, NULL);
return;
}
@@ -3626,6 +3662,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
anti-range. */
vr0.type = VR_RANGE;
min = build_int_cst (type, 0);
+ vr_is_wrapped = true;
if (needs_overflow_infinity (type))
{
if (supports_overflow_infinity (type))
@@ -3669,7 +3706,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
set_value_range_to_varying (vr);
}
else
- set_value_range (vr, vr0.type, min, max, NULL);
+ set_value_range (vr, vr0.type, min, max, vr_is_wrapped, NULL);
return;
}
@@ -3763,7 +3800,7 @@ extract_range_from_comparison (value_range_t *vr, enum tree_code code,
if (is_gimple_min_invariant (val))
set_value_range_to_value (vr, val, vr->equiv);
else
- set_value_range (vr, VR_RANGE, val, val, vr->equiv);
+ set_value_range (vr, VR_RANGE, val, val, false, vr->equiv);
}
else
/* The result of a comparison is always true or false. */
@@ -4060,7 +4097,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
goto bitop_builtin;
bitop_builtin:
set_value_range (vr, VR_RANGE, build_int_cst (type, mini),
- build_int_cst (type, maxi), NULL);
+ build_int_cst (type, maxi), false, NULL);
return;
default:
break;
@@ -4150,7 +4187,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
NULL);
else
set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
- build_int_cst (type, 1), NULL);
+ build_int_cst (type, 1), false, NULL);
}
else if (types_compatible_p (type, TREE_TYPE (op0))
&& types_compatible_p (type, TREE_TYPE (op1)))
@@ -4244,6 +4281,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
{
tree init, step, chrec, tmin, tmax, min, max, type, tem;
enum ev_direction dir;
+ bool t_is_wrapped = false, is_wrapped = false;
/* TODO. Don't adjust anti-ranges. An anti-range may provide
better opportunities than a regular range, but I'm not sure. */
@@ -4339,6 +4377,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
/* Likewise if the addition did. */
if (maxvr.type == VR_RANGE)
{
+ t_is_wrapped = maxvr.is_wrapped;
tmin = maxvr.min;
tmax = maxvr.max;
}
@@ -4350,6 +4389,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
{
min = tmin;
max = tmax;
+ is_wrapped = t_is_wrapped;
/* For VARYING or UNDEFINED ranges, just about anything we get
from scalar evolutions should be better. */
@@ -4403,7 +4443,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
&& is_positive_overflow_infinity (max)))
return;
- set_value_range (vr, VR_RANGE, min, max, vr->equiv);
+ set_value_range (vr, VR_RANGE, min, max, is_wrapped, vr->equiv);
}
@@ -4722,7 +4762,8 @@ dump_value_range (FILE *file, value_range_t *vr)
{
tree type = TREE_TYPE (vr->min);
- fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : "");
+ fprintf (file, "%s %s[", vr->is_wrapped ? "WRAPP" : "NOWRAPP",
+ (vr->type == VR_ANTI_RANGE) ? "~" : "");
if (is_negative_overflow_infinity (vr->min))
fprintf (file, "-INF(OVF)");
@@ -6917,7 +6958,8 @@ remove_range_assertions (void)
{
set_range_info (var,
SSA_NAME_RANGE_INFO (lhs)->get_min (),
- SSA_NAME_RANGE_INFO (lhs)->get_max ());
+ SSA_NAME_RANGE_INFO (lhs)->get_max (),
+ SSA_NAME_RANGE_WRAPPED_P (lhs));
maybe_set_nonzero_bits (bb, var);
}
}
@@ -8584,7 +8626,9 @@ vrp_intersect_ranges_1 (value_range_t *vr0, value_range_t *vr1)
/* Make sure to canonicalize the result though as the inversion of a
VR_RANGE can still be a VR_RANGE. */
set_and_canonicalize_value_range (vr0, vr0->type,
- vr0->min, vr0->max, vr0->equiv);
+ vr0->min, vr0->max,
+ vr0->is_wrapped && vr1->is_wrapped,
+ vr0->equiv);
/* If that failed, use the saved original VR0. */
if (vr0->type == VR_VARYING)
{
@@ -8635,7 +8679,7 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
if (vr0->type == VR_UNDEFINED)
{
- set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv);
+ set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->is_wrapped, vr1->equiv);
return;
}
@@ -8689,6 +8733,7 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
return;
}
set_and_canonicalize_value_range (vr0, vr0->type, vr0->min, vr0->max,
+ vr0->is_wrapped && vr1->is_wrapped,
vr0->equiv);
if (vr0->type == VR_VARYING)
return;
@@ -8747,6 +8792,7 @@ vrp_visit_phi_node (gphi *phi)
for (i = 0; i < gimple_phi_num_args (phi); i++)
{
edge e = gimple_phi_arg_edge (phi, i);
+ bool is_wrapped = false;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -8792,6 +8838,7 @@ vrp_visit_phi_node (gphi *phi)
vr_arg.type = VR_RANGE;
vr_arg.min = arg;
vr_arg.max = arg;
+ vr_arg.is_wrapped = is_wrapped;
vr_arg.equiv = NULL;
}
}
@@ -8804,6 +8851,7 @@ vrp_visit_phi_node (gphi *phi)
vr_arg.type = VR_RANGE;
vr_arg.min = arg;
vr_arg.max = arg;
+ vr_arg.is_wrapped = is_wrapped;
vr_arg.equiv = NULL;
}
@@ -10244,7 +10292,7 @@ vrp_finalize (void)
|| 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);
+ set_range_info (name, vr_value[i]->min, vr_value[i]->max, vr_value[i]->is_wrapped);
else if (vr_value[i]->type == VR_ANTI_RANGE)
{
/* VR_ANTI_RANGE
@@ -10259,11 +10307,13 @@ vrp_finalize (void)
/* ~[0,0] anti-range is represented as range. */
set_range_info (name,
build_int_cst (TREE_TYPE (name), 1),
- TYPE_MAXVAL (TREE_TYPE (name)));
+ TYPE_MAXVAL (TREE_TYPE (name)),
+ vr_value[i]->is_wrapped);
else
set_range_info (name,
wi::add (vr_value[i]->max, 1),
- wi::sub (vr_value[i]->min, 1));
+ wi::sub (vr_value[i]->min, 1),
+ vr_value[i]->is_wrapped);
}
}
@@ -1467,7 +1467,7 @@ extern void protected_set_expr_location (tree, location_t);
SSA_NAME_CHECK (N)->ssa_name.info.ptr_info
/* True if SSA_NAME_RANGE_INFO describes an anti-range. */
-#define SSA_NAME_ANTI_RANGE_P(N) \
+#define SSA_NAME_RANGE_WRAPPED_P(N) \
SSA_NAME_CHECK (N)->base.static_flag
/* The type of range described by SSA_NAME_RANGE_INFO. */