@@ -940,8 +940,14 @@ ccp_finalize (bool nonzero_p)
unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
wide_int nonzero_bits = wide_int::from (val->mask, precision,
UNSIGNED) | val->value;
+ wide_int mask = wide_int::from (val->mask, TYPE_PRECISION (TREE_TYPE (name)),
+ TYPE_SIGN (TREE_TYPE (name)));
+ wide_int ones = wi::bit_and (val->value, wi::bit_not (mask));
+ wide_int zeros = wi::bit_not (wi::bit_and (wi::bit_not (val->value),
+ wi::bit_not (mask)));
nonzero_bits &= get_nonzero_bits (name);
set_nonzero_bits (name, nonzero_bits);
+ refine_range_info (name, zeros, ones);
}
}
@@ -388,6 +388,36 @@ set_nonzero_bits (tree name, const wide_int_ref &mask)
ri->set_nonzero_bits (mask);
}
+/* Refine value range of NAME based on allways ZEROS and always ONES bits. */
+void
+refine_range_info (tree name, const wide_int_ref &zeros,
+ const wide_int_ref &ones)
+{
+ tree type = TREE_TYPE (name);
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ if (SSA_NAME_RANGE_INFO (name) == NULL)
+ set_range_info (name, VR_RANGE,
+ TYPE_MIN_VALUE (type),
+ TYPE_MAX_VALUE (type));
+
+ if (SSA_NAME_RANGE_TYPE (name) != VR_RANGE)
+ return;
+
+ wide_int min = wi::min_value (type);
+ wide_int max = wi::max_value (type);
+
+ max &= zeros;
+ max |= ones;
+ min &= zeros;
+ min |= ones;
+
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ if (wi::cmp (ri->get_min(), min, TYPE_SIGN (TREE_TYPE (name))) == -1)
+ ri->set_min (min);
+ if (wi::cmp (max, ri->get_max(), TYPE_SIGN (TREE_TYPE (name))) == -1)
+ ri->set_max (max);
+}
+
/* Return a widest_int with potentially non-zero bits in SSA_NAME
NAME, or -1 if unknown. */
@@ -74,6 +74,8 @@ extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
extern enum value_range_type get_range_info (const_tree, wide_int *,
wide_int *);
extern void set_nonzero_bits (tree, const wide_int_ref &);
+extern void refine_range_info (tree name, const wide_int_ref &zeros,
+ const wide_int_ref &ones);
extern wide_int get_nonzero_bits (const_tree);
extern bool ssa_name_has_boolean_range (tree);
extern void init_ssanames (struct function *, int);