the bit is 1, otherwise it might be 0 or 1. */
static bool
-zero_nonzero_bits_from_vr (value_range_t *vr, double_int *may_be_nonzero,
+zero_nonzero_bits_from_vr (value_range_t *vr,
+ double_int *may_be_nonzero,
double_int *must_be_nonzero)
{
- may_be_nonzero->low = ALL_ONES;
- may_be_nonzero->high = ALL_ONES;
- must_be_nonzero->low = 0;
- must_be_nonzero->high = 0;
- if (range_int_cst_p (vr))
+ *may_be_nonzero = double_int_minus_one;
+ *must_be_nonzero = double_int_zero;
+ if (!range_int_cst_p (vr))
+ return false;
+
+ if (range_int_cst_singleton_p (vr))
+ {
+ *may_be_nonzero = tree_to_double_int (vr->min);
+ *must_be_nonzero = *may_be_nonzero;
+ }
+ else if (tree_int_cst_sgn (vr->min) >= 0
+ || tree_int_cst_sgn (vr->max) < 0)
{
- if (range_int_cst_singleton_p (vr))
+ double_int dmin = tree_to_double_int (vr->min);
+ double_int dmax = tree_to_double_int (vr->max);
+ double_int xor_mask = double_int_xor (dmin, dmax);
+ *may_be_nonzero = double_int_ior (dmin, dmax);
+ *must_be_nonzero = double_int_and (dmin, dmax);
+ if (xor_mask.high != 0)
{
- *may_be_nonzero = tree_to_double_int (vr->min);
- *must_be_nonzero = *may_be_nonzero;
+ unsigned HOST_WIDE_INT mask
+ = ((unsigned HOST_WIDE_INT) 1
+ << floor_log2 (xor_mask.high)) - 1;
+ may_be_nonzero->low = ALL_ONES;
+ may_be_nonzero->high |= mask;
+ must_be_nonzero->low = 0;
+ must_be_nonzero->high &= ~mask;
}
- else if (tree_int_cst_sgn (vr->min) >= 0)
+ else if (xor_mask.low != 0)
{
- double_int dmin = tree_to_double_int (vr->min);
- double_int dmax = tree_to_double_int (vr->max);
- double_int xor_mask = double_int_xor (dmin, dmax);
- *may_be_nonzero = double_int_ior (dmin, dmax);
- *must_be_nonzero = double_int_and (dmin, dmax);
- if (xor_mask.high != 0)
- {
- unsigned HOST_WIDE_INT mask
- = ((unsigned HOST_WIDE_INT) 1
- << floor_log2 (xor_mask.high)) - 1;
- may_be_nonzero->low = ALL_ONES;
- may_be_nonzero->high |= mask;
- must_be_nonzero->low = 0;
- must_be_nonzero->high &= ~mask;
- }
- else if (xor_mask.low != 0)
- {
- unsigned HOST_WIDE_INT mask
- = ((unsigned HOST_WIDE_INT) 1
- << floor_log2 (xor_mask.low)) - 1;
- may_be_nonzero->low |= mask;
- must_be_nonzero->low &= ~mask;
- }
+ unsigned HOST_WIDE_INT mask
+ = ((unsigned HOST_WIDE_INT) 1
+ << floor_log2 (xor_mask.low)) - 1;
+ may_be_nonzero->low |= mask;
+ must_be_nonzero->low &= ~mask;
}
- return true;
}
- return false;
+
+ return true;
}
type = VR_RANGE;
if (code == BIT_AND_EXPR)
{
+ double_int dmax;
min = double_int_to_tree (expr_type,
double_int_and (must_be_nonzero0,
must_be_nonzero1));
- max = double_int_to_tree (expr_type,
- double_int_and (may_be_nonzero0,
- may_be_nonzero1));
- if (tree_int_cst_sgn (min) < 0)
- min = NULL_TREE;
- if (tree_int_cst_sgn (max) < 0)
- max = NULL_TREE;
- if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
+ dmax = double_int_and (may_be_nonzero0, may_be_nonzero1);
+ /* If both input ranges contain only negative values we can
+ truncate the result range maximum to the minimum of the
+ input range maxima. */
+ if (int_cst_range0 && int_cst_range1
+ && tree_int_cst_sgn (vr0.max) < 0
+ && tree_int_cst_sgn (vr1.max) < 0)
{
- if (min == NULL_TREE)
- min = build_int_cst (expr_type, 0);
- if (max == NULL_TREE || tree_int_cst_lt (vr0.max, max))
- max = vr0.max;
+ dmax = double_int_min (dmax, tree_to_double_int (vr0.max),
+ TYPE_UNSIGNED (expr_type));
+ dmax = double_int_min (dmax, tree_to_double_int (vr1.max),
+ TYPE_UNSIGNED (expr_type));
}
+ /* If either input range contains only non-negative values
+ we can truncate the result range maximum to the respective
+ maximum of the input range. */
+ if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
+ dmax = double_int_min (dmax, tree_to_double_int (vr0.max),
+ TYPE_UNSIGNED (expr_type));
if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
- {
- if (min == NULL_TREE)
- min = build_int_cst (expr_type, 0);
- if (max == NULL_TREE || tree_int_cst_lt (vr1.max, max))
- max = vr1.max;
- }
+ dmax = double_int_min (dmax, tree_to_double_int (vr1.max),
+ TYPE_UNSIGNED (expr_type));
+ max = double_int_to_tree (expr_type, dmax);
}
else if (code == BIT_IOR_EXPR)
{
- min = double_int_to_tree (expr_type,
- double_int_ior (must_be_nonzero0,
- must_be_nonzero1));
+ double_int dmin;
max = double_int_to_tree (expr_type,
double_int_ior (may_be_nonzero0,
may_be_nonzero1));
- if (tree_int_cst_sgn (max) < 0)
- max = NULL_TREE;
- if (int_cst_range0)
+ dmin = double_int_ior (must_be_nonzero0, must_be_nonzero1);
+ /* If the input ranges contain only positive values we can
+ truncate the minimum of the result range to the maximum
+ of the input range minima. */
+ if (int_cst_range0 && int_cst_range1
+ && tree_int_cst_sgn (vr0.min) >= 0
+ && tree_int_cst_sgn (vr1.min) >= 0)
{
- if (tree_int_cst_sgn (min) < 0)
- min = vr0.min;
- else
- min = vrp_int_const_binop (MAX_EXPR, min, vr0.min);
+ dmin = double_int_max (dmin, tree_to_double_int (vr0.min),
+ TYPE_UNSIGNED (expr_type));
+ dmin = double_int_max (dmin, tree_to_double_int (vr1.min),
+ TYPE_UNSIGNED (expr_type));
}
- if (int_cst_range1)
- min = vrp_int_const_binop (MAX_EXPR, min, vr1.min);
+ /* If either input range contains only negative values
+ we can truncate the minimum of the result range to the
+ respective minimum range. */
+ if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
+ dmin = double_int_max (dmin, tree_to_double_int (vr0.min),
+ TYPE_UNSIGNED (expr_type));
+ if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
+ dmin = double_int_max (dmin, tree_to_double_int (vr1.min),
+ TYPE_UNSIGNED (expr_type));
+ min = double_int_to_tree (expr_type, dmin);
}
else if (code == BIT_XOR_EXPR)
{
max = double_int_to_tree (expr_type,
double_int_not (result_zero_bits));
min = double_int_to_tree (expr_type, result_one_bits);
- /* Return a [min, max] range if we know the
- result range is either positive or negative. */
- if (tree_int_cst_sgn (max) >= 0)
- /* The range is bound by a lower value of 0. */;
- else if (tree_int_cst_sgn (min) < 0)
- /* The range is bound by an upper value of -1. */;
+ /* If the range has all positive or all negative values the
+ result is better than VARYING. */
+ if (tree_int_cst_sgn (min) < 0
+ || tree_int_cst_sgn (max) >= 0)
+ ;
else
- /* We don't know whether the sign bit is set or not. */
max = min = NULL_TREE;
}
else