@@ -916,7 +916,11 @@ ccp_finalize (void)
unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
wide_int nonzero_bits = wide_int::from (val->mask, precision,
UNSIGNED) | val->value;
- nonzero_bits &= get_nonzero_bits (name);
+ wide_int nonzero_bits_name = get_nonzero_bits (name);
+ if (precision != nonzero_bits_name.get_precision ())
+ nonzero_bits = wi::shwi (*nonzero_bits.get_val (),
+ nonzero_bits_name.get_precision ());
+ nonzero_bits &= nonzero_bits_name;
set_nonzero_bits (name, nonzero_bits);
}
}
@@ -1852,6 +1856,8 @@ evaluate_stmt (gimple stmt)
{
tree lhs = gimple_get_lhs (stmt);
wide_int nonzero_bits = get_nonzero_bits (lhs);
+ if (TYPE_PRECISION (TREE_TYPE (lhs)) != nonzero_bits.get_precision ())
+ nonzero_bits = wide_int_to_tree (TREE_TYPE (lhs), nonzero_bits);
if (nonzero_bits != -1)
{
if (!is_constant)
@@ -192,7 +192,7 @@ set_range_info (tree name, enum value_range_type range_type,
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));
+ unsigned int precision = min.get_precision ();
/* Allocate if not available. */
if (ri == NULL)
@@ -204,6 +204,15 @@ set_range_info (tree name, enum value_range_type range_type,
SSA_NAME_RANGE_INFO (name) = ri;
ri->set_nonzero_bits (wi::shwi (-1, precision));
}
+ else if (ri->get_min ().get_precision () != precision)
+ {
+ size_t size = (sizeof (range_info_def)
+ + trailing_wide_ints <3>::extra_size (precision));
+ ri = static_cast<range_info_def *> (ggc_realloc (ri, size));
+ ri->ints.set_precision (precision);
+ SSA_NAME_RANGE_INFO (name) = ri;
+ ri->set_nonzero_bits (wi::shwi (-1, precision));
+ }
/* Record the range type. */
if (SSA_NAME_RANGE_TYPE (name) != range_type)
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "tree-ssa-threadedge.h"
#include "wide-int.h"
+#include "langhooks.h"
@@ -424,6 +425,23 @@ set_value_range_to_varying (value_range_t *vr)
bitmap_clear (vr->equiv);
}
+/* Normalize min and max to promoted_type if their precision differs. */
+
+static void
+normalize_int_cst_precision (tree *min, tree *max)
+{
+ if (TREE_CODE (*min) != INTEGER_CST
+ || TREE_CODE (*max) != INTEGER_CST)
+ return;
+ if (TYPE_PRECISION (TREE_TYPE (*min)) != TYPE_PRECISION (TREE_TYPE (*max)))
+ {
+ tree type = TREE_TYPE (*min);
+ if (TYPE_PRECISION (TREE_TYPE (*min)) < TYPE_PRECISION (TREE_TYPE (*max)))
+ type = TREE_TYPE (*max);
+ *min = wide_int_to_tree (type, *min);
+ *max = wide_int_to_tree (type, *max);
+ }
+}
/* Set value range VR to {T, MIN, MAX, EQUIV}. */
@@ -438,6 +456,8 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
int cmp;
gcc_assert (min && max);
+ gcc_assert (TYPE_PRECISION (TREE_TYPE (min))
+ == TYPE_PRECISION (TREE_TYPE (max)));
gcc_assert ((!TREE_OVERFLOW_P (min) || is_overflow_infinity (min))
&& (!TREE_OVERFLOW_P (max) || is_overflow_infinity (max)));
@@ -597,6 +617,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
return;
}
+ if (min != NULL_TREE && max != NULL_TREE)
+ normalize_int_cst_precision (&min, &max);
set_value_range (vr, t, min, max, equiv);
}
@@ -951,6 +973,66 @@ usable_range_p (value_range_t *vr, bool *strict_overflow_p)
return true;
}
+/* Return the promoted type as defined by PROMOTE_MODE of the target. */
+
+static tree
+promoted_type (tree type)
+{
+#ifdef PROMOTE_MODE
+ tree new_type;
+ if (!POINTER_TYPE_P (type)
+ && (TREE_CODE (type) != ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (type))
+ {
+ enum machine_mode mode = TYPE_MODE (type);
+ int uns = TYPE_SIGN (type);
+ PROMOTE_MODE (mode, uns, type);
+ uns = TYPE_SIGN (type);
+ new_type = lang_hooks.types.type_for_mode (mode, uns);
+ if (TYPE_PRECISION (new_type) > TYPE_PRECISION (type))
+ type = new_type;
+ }
+#endif
+ return type;
+}
+
+/* Promote VRO to promoted_type if their precision differ and
+ return the new type. */
+
+static tree
+promote_unary_vr (tree type, value_range_t *vr0)
+{
+ tree expr_type = type;
+
+ if (!range_int_cst_p (vr0))
+ return expr_type;
+ if ((TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->min)))
+ || (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->max))))
+ {
+ expr_type = promoted_type (type);
+ vr0->min = wide_int_to_tree (expr_type, vr0->min);
+ vr0->max = wide_int_to_tree (expr_type, vr0->max);
+ }
+ return expr_type;
+}
+
+/* Promote VRO and VR1 to promoted_type if their precision differ and
+ return the new type. */
+
+static tree
+promote_binary_vr (tree type, value_range_t *vr0, value_range_t *vr1)
+{
+ tree expr_type0 = promote_unary_vr (type, vr0);
+ tree expr_type1 = promote_unary_vr (type, vr1);
+
+ if (TYPE_PRECISION (expr_type0) == TYPE_PRECISION (expr_type1))
+ return expr_type0;
+ if (TYPE_PRECISION (expr_type0) < TYPE_PRECISION (expr_type1))
+ return promote_unary_vr (expr_type1, vr0);
+ else
+ return promote_unary_vr (expr_type0, vr1);
+}
+
/* Return true if the result of assignment STMT is know to be non-negative.
If the return value is based on the assumption that signed overflow is
@@ -1741,6 +1823,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
TREE_NO_WARNING (max) = 1;
}
+ normalize_int_cst_precision (&min, &max);
set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
}
}
@@ -1781,6 +1864,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
TREE_NO_WARNING (min) = 1;
}
+ normalize_int_cst_precision (&min, &max);
set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
}
}
@@ -2376,6 +2460,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
range and see what we end up with. */
if (code == PLUS_EXPR || code == MINUS_EXPR)
{
+ /* If any of the value range is in promoted type, promote them all
+ including the type. */
+ expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
/* If we have a PLUS_EXPR with two VR_RANGE integer constant
ranges compute the precise range for such case if possible. */
if (range_int_cst_p (&vr0)
@@ -2562,6 +2649,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
else if (code == MIN_EXPR
|| code == MAX_EXPR)
{
+ /* If any of the value range is in promoted type, promote them all
+ including the type. */
+ expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
if (vr0.type == VR_RANGE
&& !symbolic_range_p (&vr0))
{
@@ -2625,6 +2715,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
<wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> > vrp_int_cst;
vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
vrp_int size = sizem1 + 1;
+ vrp_int type_min = vrp_int_cst (TYPE_MIN_VALUE (expr_type));
+ vrp_int type_max = vrp_int_cst (TYPE_MAX_VALUE (expr_type));
/* Extend the values using the sign of the result to PREC2.
From here on out, everthing is just signed math no matter
@@ -2697,8 +2789,17 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* The following should handle the wrapping and selecting
VR_ANTI_RANGE for us. */
- min = wide_int_to_tree (expr_type, prod0);
- max = wide_int_to_tree (expr_type, prod3);
+ if (wi::lts_p (prod0, type_min)
+ || wi::gts_p (prod3, type_max))
+ {
+ min = wide_int_to_tree (promoted_type (expr_type), prod0);
+ max = wide_int_to_tree (promoted_type (expr_type), prod3);
+ }
+ else
+ {
+ 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);
return;
}
@@ -2724,6 +2825,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
else if (code == RSHIFT_EXPR
|| code == LSHIFT_EXPR)
{
+ /* If value range is in promoted type, promote the type as well. */
+ expr_type = promote_unary_vr (expr_type, &vr0);
/* If we have a RSHIFT_EXPR with any shift values outside [0..prec-1],
then drop to VR_VARYING. Outside of this range we get undefined
behavior from the shift operation. We cannot even trust
@@ -2946,6 +3049,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
wide_int may_be_nonzero0, may_be_nonzero1;
wide_int must_be_nonzero0, must_be_nonzero1;
+ /* If any of the value range is in promoted type, promote them all
+ including the type. */
+ expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
&may_be_nonzero0,
&must_be_nonzero0);
@@ -3224,14 +3330,22 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
tree new_min, new_max;
if (is_overflow_infinity (vr0.min))
new_min = negative_overflow_infinity (outer_type);
- else
+ else if (int_fits_type_p (vr0.min, outer_type))
new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
0, false);
+ else
+ new_min = force_fit_type (promoted_type (outer_type),
+ wi::to_widest (vr0.min),
+ 0, false);
if (is_overflow_infinity (vr0.max))
new_max = positive_overflow_infinity (outer_type);
- else
+ else if (int_fits_type_p (vr0.min, outer_type))
new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
0, false);
+ else
+ new_max = force_fit_type (promoted_type (outer_type),
+ wi::to_widest (vr0.max),
+ 0, false);
set_and_canonicalize_value_range (vr, vr0.type,
new_min, new_max, NULL);
return;
@@ -3940,6 +4054,8 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
&& is_positive_overflow_infinity (max)))
return;
+ if (min != NULL_TREE && max != NULL_TREE)
+ normalize_int_cst_precision (&min, &max);
set_value_range (vr, VR_RANGE, min, max, vr->equiv);
}
@@ -6668,6 +6784,8 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
else
extract_range_from_assignment (&new_vr, stmt);
+ if (range_int_cst_p (&new_vr))
+ normalize_int_cst_precision (&new_vr.min, &new_vr.max);
if (update_value_range (lhs, &new_vr))
{
*output_p = lhs;
@@ -8399,6 +8517,8 @@ vrp_visit_phi_node (gimple phi)
/* If the new range is different than the previous value, keep
iterating. */
update_range:
+ if (range_int_cst_p (&vr_result))
+ normalize_int_cst_precision (&vr_result.min, &vr_result.max);
if (update_value_range (lhs, &vr_result))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -8655,9 +8775,19 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
&must_be_nonzero0))
return false;
- if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+ if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr1, &may_be_nonzero1,
&must_be_nonzero1))
return false;
+ if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero0.get_precision ())
+ {
+ may_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), may_be_nonzero0);
+ must_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), must_be_nonzero0);
+ }
+ if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero1.get_precision ())
+ {
+ may_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), may_be_nonzero0);
+ must_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), must_be_nonzero0);
+ }
switch (gimple_assign_rhs_code (stmt))
{
@@ -8752,9 +8882,9 @@ test_for_singularity (enum tree_code cond_code, tree op0,
if (min && max)
{
if (compare_values (vr->min, min) == 1)
- min = vr->min;
+ min = wide_int_to_tree (TREE_TYPE (op0), vr->min);
if (compare_values (vr->max, max) == -1)
- max = vr->max;
+ max = wide_int_to_tree (TREE_TYPE (op0), vr->max);
/* If the new min/max values have converged to a single value,
then there is only one value which can satisfy the condition,
@@ -9474,7 +9604,7 @@ simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
{
extract_range_from_assignment (&new_vr, stmt);
if (range_int_cst_singleton_p (&new_vr))
- return new_vr.min;
+ return wide_int_to_tree (TREE_TYPE (lhs), new_vr.min);
}
}