@@ -378,7 +378,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
bitpos += ptr_bitpos;
if (TREE_CODE (exp) == MEM_REF
|| TREE_CODE (exp) == TARGET_MEM_REF)
- bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
+ bitpos += mem_ref_offset_as_double (exp).low * BITS_PER_UNIT;
}
}
else if (TREE_CODE (exp) == STRING_CST)
@@ -8784,12 +8784,12 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (! operand_equal_p (TREE_OPERAND (src_base, 0),
TREE_OPERAND (dest_base, 0), 0))
return NULL_TREE;
- off = mem_ref_offset (src_base) +
+ off = mem_ref_offset_as_double (src_base) +
double_int::from_shwi (src_offset);
if (!off.fits_shwi ())
return NULL_TREE;
src_offset = off.low;
- off = mem_ref_offset (dest_base) +
+ off = mem_ref_offset_as_double (dest_base) +
double_int::from_shwi (dest_offset);
if (!off.fits_shwi ())
return NULL_TREE;
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "vecprim.h"
#include "double-int.h"
+#include "wide-int.h"
#include "bitmap.h"
#include "sbitmap.h"
@@ -288,6 +289,7 @@ void estimate_numbers_of_iterations_loop (struct loop *);
void record_niter_bound (struct loop *, double_int, bool, bool);
bool estimated_loop_iterations (struct loop *, double_int *);
bool max_loop_iterations (struct loop *, double_int *);
+bool max_loop_iterations (struct loop *, wide_int *, int, int);
HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
HOST_WIDE_INT max_loop_iterations_int (struct loop *);
bool max_stmt_executions (struct loop *, double_int *);
@@ -6678,7 +6678,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
tree off = TREE_OPERAND (exp, 1);
if (!integer_zerop (off))
{
- double_int boff, coff = mem_ref_offset (exp);
+ double_int boff, coff = mem_ref_offset_as_double (exp);
boff = coff.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -9533,7 +9533,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
might end up in a register. */
if (mem_ref_refers_to_non_mem_p (exp))
{
- HOST_WIDE_INT offset = mem_ref_offset (exp).low;
+ HOST_WIDE_INT offset = mem_ref_offset_as_double (exp).low;
tree bit_offset;
tree bftype;
base = TREE_OPERAND (base, 0);
@@ -9577,8 +9577,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = memory_address_addr_space (address_mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
{
- wide_int wi = wide_int::from_double_int
- (mem_ref_offset (exp), address_mode);
+ wide_int wi = mem_ref_offset (exp);
rtx off = immed_wide_int_const (wi, address_mode);
op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
}
@@ -2688,7 +2688,7 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
{
if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
return NULL_TREE;
- *bit_offset += (mem_ref_offset (base).low
+ *bit_offset += (mem_ref_offset_as_double (base).low
* BITS_PER_UNIT);
}
@@ -557,7 +557,7 @@ restructure_reference (tree *pbase, tree *poffset, double_int *pindex,
return false;
t1 = TREE_OPERAND (base, 0);
- c1 = mem_ref_offset (base);
+ c1 = mem_ref_offset_as_double (base);
type = TREE_TYPE (TREE_OPERAND (base, 1));
mult_op0 = TREE_OPERAND (offset, 0);
@@ -933,7 +933,7 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
|| max_size == -1
|| max_size != size)
return;
- offset += mem_ref_offset (base).low * BITS_PER_UNIT;
+ offset += mem_ref_offset_as_double (base).low * BITS_PER_UNIT;
ssa = TREE_OPERAND (base, 0);
if (TREE_CODE (ssa) != SSA_NAME
|| !SSA_NAME_IS_DEFAULT_DEF (ssa)
@@ -988,7 +988,7 @@ get_ancestor_addr_info (gimple assign, tree *obj_p, HOST_WIDE_INT *offset)
|| TREE_CODE (SSA_NAME_VAR (parm)) != PARM_DECL)
return NULL_TREE;
- *offset += mem_ref_offset (expr).low * BITS_PER_UNIT;
+ *offset += mem_ref_offset_as_double (expr).low * BITS_PER_UNIT;
*obj_p = obj;
return expr;
}
@@ -720,7 +720,7 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
{
- double_int moff = mem_ref_offset (base);
+ double_int moff = mem_ref_offset_as_double (base);
tree mofft = double_int_to_tree (sizetype, moff);
if (!poffset)
poffset = mofft;
@@ -552,7 +552,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
else
{
- double_int off = mem_ref_offset (exp);
+ double_int off = mem_ref_offset_as_double (exp);
off = off.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -583,7 +583,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
exp = TREE_OPERAND (TMR_BASE (exp), 0);
else
{
- double_int off = mem_ref_offset (exp);
+ double_int off = mem_ref_offset_as_double (exp);
off = off.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -1269,7 +1269,7 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
{
if (!integer_zerop (TREE_OPERAND (exp, 1)))
{
- double_int off = mem_ref_offset (exp);
+ double_int off = mem_ref_offset_as_double (exp);
gcc_assert (off.high == -1 || off.high == 0);
byte_offset += off.to_shwi ();
}
@@ -1292,7 +1292,7 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
return NULL_TREE;
if (!integer_zerop (TMR_OFFSET (exp)))
{
- double_int off = mem_ref_offset (exp);
+ double_int off = mem_ref_offset_as_double (exp);
gcc_assert (off.high == -1 || off.high == 0);
byte_offset += off.to_shwi ();
}
@@ -142,7 +142,7 @@ compute_object_offset (const_tree expr, const_tree var)
case MEM_REF:
gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
- return double_int_to_tree (sizetype, mem_ref_offset (expr));
+ return double_int_to_tree (sizetype, mem_ref_offset_as_double (expr));
default:
return error_mark_node;
@@ -192,7 +192,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
}
if (sz != unknown[object_size_type])
{
- double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset (pt_var);
+ double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset_as_double (pt_var);
if (dsz.is_negative ())
sz = 0;
else if (dsz.fits_uhwi ())
@@ -4304,7 +4304,7 @@ sra_ipa_modify_expr (tree *expr, bool convert,
if (TREE_CODE (base) == MEM_REF)
{
- offset += mem_ref_offset (base).low * BITS_PER_UNIT;
+ offset += mem_ref_offset_as_double (base).low * BITS_PER_UNIT;
base = TREE_OPERAND (base, 0);
}
@@ -869,8 +869,8 @@ copy_ref_info (tree new_ref, tree old_ref)
&& (tree_to_shwi (TMR_STEP (new_ref))
< align)))))
{
- unsigned int inc = (mem_ref_offset (old_ref)
- - mem_ref_offset (new_ref)).low;
+ unsigned int inc = (mem_ref_offset_as_double (old_ref)
+ - mem_ref_offset_as_double (new_ref)).low;
adjust_ptr_info_misalignment (new_pi, inc);
}
else
@@ -755,7 +755,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
/* The offset embedded in MEM_REFs can be negative. Bias them
so that the resulting offset adjustment is positive. */
- moff = mem_ref_offset (base1);
+ moff = mem_ref_offset_as_double (base1);
moff = moff.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -833,7 +833,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
if (TREE_CODE (dbase2) == MEM_REF
|| TREE_CODE (dbase2) == TARGET_MEM_REF)
{
- double_int moff = mem_ref_offset (dbase2);
+ double_int moff = mem_ref_offset_as_double (dbase2);
moff = moff.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -929,7 +929,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
double_int moff;
/* The offset embedded in MEM_REFs can be negative. Bias them
so that the resulting offset adjustment is positive. */
- moff = mem_ref_offset (base1);
+ moff = mem_ref_offset_as_double (base1);
moff = moff.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -937,7 +937,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
offset2 += (-moff).low;
else
offset1 += moff.low;
- moff = mem_ref_offset (base2);
+ moff = mem_ref_offset_as_double (base2);
moff = moff.alshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT);
@@ -799,12 +799,12 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
&def_rhs_offset)))
{
- double_int off = mem_ref_offset (lhs);
+ double_int off = mem_ref_offset_as_double (lhs);
tree new_ptr;
off += double_int::from_shwi (def_rhs_offset);
if (TREE_CODE (def_rhs_base) == MEM_REF)
{
- off += mem_ref_offset (def_rhs_base);
+ off += mem_ref_offset_as_double (def_rhs_base);
new_ptr = TREE_OPERAND (def_rhs_base, 0);
}
else
@@ -883,12 +883,12 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0),
&def_rhs_offset)))
{
- double_int off = mem_ref_offset (rhs);
+ double_int off = mem_ref_offset_as_double (rhs);
tree new_ptr;
off += double_int::from_shwi (def_rhs_offset);
if (TREE_CODE (def_rhs_base) == MEM_REF)
{
- off += mem_ref_offset (def_rhs_base);
+ off += mem_ref_offset_as_double (def_rhs_base);
new_ptr = TREE_OPERAND (def_rhs_base, 0);
}
else
@@ -1352,7 +1352,7 @@ constant_pointer_difference (tree p1, tree p2)
p = TREE_OPERAND (q, 0);
off = size_binop (PLUS_EXPR, off,
double_int_to_tree (sizetype,
- mem_ref_offset (q)));
+ mem_ref_offset_as_double (q)));
}
else
{
@@ -3035,6 +3035,23 @@ max_loop_iterations (struct loop *loop, double_int *nit)
return true;
}
+/* Sets NIT to an upper bound for the maximum number of executions of the
+ latch of the LOOP. If we have no reliable estimate, the function returns
+ false, otherwise returns true. */
+
+bool
+max_loop_iterations (struct loop *loop, wide_int *nit,
+ int bitsize, int precision)
+{
+ estimate_numbers_of_iterations_loop (loop);
+ if (!loop->any_upper_bound)
+ return false;
+
+ *nit = wide_int::from_double_int (loop->nb_iterations_upper_bound,
+ bitsize, precision);
+ return true;
+}
+
/* Similar to estimated_loop_iterations, but returns the estimate only
if it fits to HOST_WIDE_INT. If this is not the case, or the estimate
on the number of iterations of LOOP could not be derived, returns -1. */
@@ -702,7 +702,7 @@ jump_function_from_stmt (tree *arg, gimple stmt)
&offset);
if (tem
&& TREE_CODE (tem) == MEM_REF
- && (mem_ref_offset (tem) + double_int::from_shwi (offset)).is_zero ())
+ && (mem_ref_offset_as_double (tem) + double_int::from_shwi (offset)).is_zero ())
{
*arg = TREE_OPERAND (tem, 0);
return true;
@@ -1124,7 +1124,7 @@ vn_reference_maybe_forwprop_address (VEC (vn_reference_op_s, heap) **ops,
return;
off += double_int::from_shwi (addr_offset);
- off += mem_ref_offset (addr_base);
+ off += mem_ref_offset_as_double (addr_base);
op->op0 = TREE_OPERAND (addr_base, 0);
}
else
@@ -1833,9 +1833,9 @@ non_rewritable_mem_ref_base (tree ref)
|| TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
&& useless_type_conversion_p (TREE_TYPE (base),
TREE_TYPE (TREE_TYPE (decl)))
- && mem_ref_offset (base).fits_uhwi ()
+ && mem_ref_offset_as_double (base).fits_uhwi ()
&& tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (decl)))
- .ugt (mem_ref_offset (base))
+ .ugt (mem_ref_offset_as_double (base))
&& multiple_of_p (sizetype, TREE_OPERAND (base, 1),
TYPE_SIZE_UNIT (TREE_TYPE (base))))
return NULL_TREE;
@@ -2730,7 +2730,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep,
{
if (off == NULL_TREE)
{
- double_int moff = mem_ref_offset (base);
+ double_int moff = mem_ref_offset_as_double (base);
off = double_int_to_tree (sizetype, moff);
}
else
@@ -80,6 +80,12 @@ typedef struct value_range_d value_range_t;
for still active basic-blocks. */
static sbitmap *live;
+/* The largest precision and bitsize used in any code in this
+ function. We use these to determine the value of infinity for
+ doing infinite precision math. */
+static int largest_precision;
+static int largest_bitsize;
+
/* Return true if the SSA name NAME is live on the edge E. */
static bool
@@ -387,6 +393,15 @@ nonnull_arg_p (const_tree arg)
return false;
}
+/* Convert a cst to an infinitely sized wide_interger. Infinite is
+ defined to be that largest type seen in this function. */
+static wide_int
+tree_to_infinite_wide_int (const_tree cst)
+{
+ wide_int result = wide_int::from_tree_as_infinite_precision
+ (cst, largest_bitsize, largest_precision);
+ return result;
+}
/* Set value range VR to VR_UNDEFINED. */
@@ -967,7 +982,7 @@ gimple_assign_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
}
}
-/* Return true if return value of call STMT is know to be non-negative.
+/* Return true if return value of call STMT is known to be non-negative.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/
@@ -987,7 +1002,7 @@ gimple_call_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
strict_overflow_p);
}
-/* Return true if STMT is know to to compute a non-negative value.
+/* Return true if STMT is known to to compute a non-negative value.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/
@@ -1006,7 +1021,7 @@ gimple_stmt_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
}
}
-/* Return true if the result of assignment STMT is know to be non-zero.
+/* Return true if the result of assignment STMT is known to be non-zero.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/
@@ -1040,7 +1055,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
}
}
-/* Return true if STMT is know to to compute a non-zero value.
+/* Return true if STMT is known to to compute a non-zero value.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/
@@ -1613,10 +1628,12 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
/* Make sure to not set TREE_OVERFLOW on the final type
conversion. We are willingly interpreting large positive
unsigned values as negative singed values here. */
- min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min),
- 0, false);
- max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max),
- 0, false);
+ min = wide_int_to_infinite_tree (TREE_TYPE (var),
+ tree_to_infinite_wide_int (min),
+ largest_precision);
+ max = wide_int_to_infinite_tree (TREE_TYPE (var),
+ tree_to_infinite_wide_int (max),
+ largest_precision);
/* We can transform a max, min range to an anti-range or
vice-versa. Use set_and_canonicalize_value_range which does
@@ -1962,7 +1979,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
}
-/* For range VR compute two double_int bitmasks. In *MAY_BE_NONZERO
+/* For range VR compute two wide_int bitmasks. In *MAY_BE_NONZERO
bitmask if some bit is unset, it means for all numbers in the range
the bit is 0, otherwise it might be 0 or 1. In *MUST_BE_NONZERO
bitmask if some bit is set, it means for all numbers in the range
@@ -1970,11 +1987,11 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
static bool
zero_nonzero_bits_from_vr (value_range_t *vr,
- double_int *may_be_nonzero,
- double_int *must_be_nonzero)
+ wide_int *may_be_nonzero,
+ wide_int *must_be_nonzero)
{
- *may_be_nonzero = double_int_minus_one;
- *must_be_nonzero = double_int_zero;
+ *may_be_nonzero = wide_int::minus_one (largest_bitsize, largest_precision);
+ *must_be_nonzero = wide_int::zero (largest_bitsize, largest_precision);
if (!range_int_cst_p (vr)
|| TREE_OVERFLOW (vr->min)
|| TREE_OVERFLOW (vr->max))
@@ -1982,34 +1999,24 @@ zero_nonzero_bits_from_vr (value_range_t *vr,
if (range_int_cst_singleton_p (vr))
{
- *may_be_nonzero = tree_to_double_int (vr->min);
+ *may_be_nonzero = tree_to_infinite_wide_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)
{
- double_int dmin = tree_to_double_int (vr->min);
- double_int dmax = tree_to_double_int (vr->max);
- double_int xor_mask = dmin ^ dmax;
+ wide_int dmin = tree_to_infinite_wide_int (vr->min);
+ wide_int dmax = tree_to_infinite_wide_int (vr->max);
+ wide_int xor_mask = dmin ^ dmax;
*may_be_nonzero = dmin | dmax;
*must_be_nonzero = dmin & dmax;
- if (xor_mask.high != 0)
+ if (!xor_mask.zero_p ())
{
- 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;
+ wide_int mask = wide_int::mask (xor_mask.floor_log2 (),
+ false, largest_bitsize,
+ largest_precision);
+ *may_be_nonzero = (*may_be_nonzero) | mask;
+ *must_be_nonzero = (*must_be_nonzero).and_not (mask);
}
}
@@ -2042,15 +2049,21 @@ ranges_from_anti_range (value_range_t *ar,
vr0->type = VR_RANGE;
vr0->min = vrp_val_min (type);
vr0->max
- = double_int_to_tree (type,
- tree_to_double_int (ar->min) - double_int_one);
+ = wide_int_to_infinite_tree (type,
+ tree_to_infinite_wide_int (ar->min)
+ - wide_int::one (largest_bitsize,
+ largest_precision),
+ largest_precision);
}
if (!vrp_val_is_max (ar->max))
{
vr1->type = VR_RANGE;
vr1->min
- = double_int_to_tree (type,
- tree_to_double_int (ar->max) + double_int_one);
+ = wide_int_to_infinite_tree (type,
+ tree_to_infinite_wide_int (ar->max)
+ + wide_int::one (largest_bitsize,
+ largest_precision),
+ largest_precision);
vr1->max = vrp_val_max (type);
}
if (vr0->type == VR_UNDEFINED)
@@ -2216,28 +2229,6 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
set_value_range (vr, type, min, max, NULL);
}
-/* Some quadruple precision helpers. */
-static int
-quad_int_cmp (double_int l0, double_int h0,
- double_int l1, double_int h1, bool uns)
-{
- int c = h0.cmp (h1, uns);
- if (c != 0) return c;
- return l0.ucmp (l1);
-}
-
-static void
-quad_int_pair_sort (double_int *l0, double_int *h0,
- double_int *l1, double_int *h1, bool uns)
-{
- if (quad_int_cmp (*l0, *h0, *l1, *h1, uns) > 0)
- {
- double_int tmp;
- tmp = *l0; *l0 = *l1; *l1 = tmp;
- tmp = *h0; *h0 = *h1; *h1 = tmp;
- }
-}
-
/* Extract range information from a binary operation CODE based on
the ranges of each of its operands, *VR0 and *VR1 with resulting
type EXPR_TYPE. The resulting range is stored in *VR. */
@@ -2252,6 +2243,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
enum value_range_type type;
tree min = NULL_TREE, max = NULL_TREE;
int cmp;
+ wide_int::SignOp sgn = TYPE_UNSIGNED (expr_type)
+ ? wide_int::UNSIGNED : wide_int::UNSIGNED;
if (!INTEGRAL_TYPE_P (expr_type)
&& !POINTER_TYPE_P (expr_type))
@@ -2407,32 +2400,34 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* 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)
- && range_int_cst_p (&vr1)
- /* We need as many bits as the possibly unsigned inputs. */
- && TYPE_PRECISION (expr_type) <= HOST_BITS_PER_DOUBLE_INT)
- {
- double_int min0 = tree_to_double_int (vr0.min);
- double_int max0 = tree_to_double_int (vr0.max);
- double_int min1 = tree_to_double_int (vr1.min);
- double_int max1 = tree_to_double_int (vr1.max);
- bool uns = TYPE_UNSIGNED (expr_type);
- double_int type_min
- = double_int::min_value (TYPE_PRECISION (expr_type), uns);
- double_int type_max
- = double_int::max_value (TYPE_PRECISION (expr_type), uns);
- double_int dmin, dmax;
+ && range_int_cst_p (&vr1))
+ {
+ wide_int min0 = tree_to_infinite_wide_int (vr0.min);
+ wide_int max0 = tree_to_infinite_wide_int (vr0.max);
+ wide_int min1 = tree_to_infinite_wide_int (vr1.min);
+ wide_int max1 = tree_to_infinite_wide_int (vr1.max);
+ wide_int::SignOp uns = TYPE_UNSIGNED (expr_type)
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+ wide_int type_min = wide_int::min_value (expr_type)
+ .force_to_size (largest_bitsize, largest_precision, uns)
+ .ext (TYPE_PRECISION (expr_type), uns);
+ wide_int type_max = wide_int::max_value (expr_type)
+ .force_to_size (largest_bitsize, largest_precision, uns)
+ .ext (TYPE_PRECISION (expr_type), wide_int::UNSIGNED);
+ wide_int dmin, dmax;
int min_ovf = 0;
int max_ovf = 0;
+ wide_int zero = wide_int::zero (largest_bitsize, largest_precision);
if (code == PLUS_EXPR)
{
dmin = min0 + min1;
dmax = max0 + max1;
- /* Check for overflow in double_int. */
- if (min1.cmp (double_int_zero, uns) != dmin.cmp (min0, uns))
+ /* Check for overflow in wide_int. */
+ if (min1.cmp (zero, uns) != dmin.cmp (min0, uns))
min_ovf = min0.cmp (dmin, uns);
- if (max1.cmp (double_int_zero, uns) != dmax.cmp (max0, uns))
+ if (max1.cmp (zero, uns) != dmax.cmp (max0, uns))
max_ovf = max0.cmp (dmax, uns);
}
else /* if (code == MINUS_EXPR) */
@@ -2440,9 +2435,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
dmin = min0 - max1;
dmax = max0 - min1;
- if (double_int_zero.cmp (max1, uns) != dmin.cmp (min0, uns))
+ if (zero.cmp (max1, uns) != dmin.cmp (min0, uns))
min_ovf = min0.cmp (max1, uns);
- if (double_int_zero.cmp (min1, uns) != dmax.cmp (max0, uns))
+ if (zero.cmp (min1, uns) != dmax.cmp (max0, uns))
max_ovf = max0.cmp (min1, uns);
}
@@ -2451,9 +2446,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
if (!TYPE_OVERFLOW_WRAPS (expr_type))
{
if (vrp_val_min (expr_type))
- type_min = tree_to_double_int (vrp_val_min (expr_type));
+ type_min = tree_to_infinite_wide_int (vrp_val_min (expr_type));
if (vrp_val_max (expr_type))
- type_max = tree_to_double_int (vrp_val_max (expr_type));
+ type_max = tree_to_infinite_wide_int (vrp_val_max (expr_type));
}
/* Check for type overflow. */
@@ -2476,19 +2471,16 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
{
/* If overflow wraps, truncate the values and adjust the
range kind and bounds appropriately. */
- double_int tmin
- = dmin.ext (TYPE_PRECISION (expr_type), uns);
- double_int tmax
- = dmax.ext (TYPE_PRECISION (expr_type), uns);
+ wide_int tmin = dmin.ext (TYPE_PRECISION (expr_type), uns);
+ wide_int tmax = dmax.ext (TYPE_PRECISION (expr_type), uns);
if (min_ovf == max_ovf)
{
/* No overflow or both overflow or underflow. The
range kind stays VR_RANGE. */
- min = double_int_to_tree (expr_type, tmin);
- max = double_int_to_tree (expr_type, tmax);
+ min = wide_int_to_infinite_tree (expr_type, tmin, largest_precision);
+ max = wide_int_to_infinite_tree (expr_type, tmax, largest_precision);
}
- else if (min_ovf == -1
- && max_ovf == 1)
+ else if (min_ovf == -1 && max_ovf == 1)
{
/* Underflow and overflow, drop to VR_VARYING. */
set_value_range_to_varying (vr);
@@ -2499,26 +2491,30 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* Min underflow or max overflow. The range kind
changes to VR_ANTI_RANGE. */
bool covers = false;
- double_int tem = tmin;
+ wide_int tem = tmin;
gcc_assert ((min_ovf == -1 && max_ovf == 0)
|| (max_ovf == 1 && min_ovf == 0));
type = VR_ANTI_RANGE;
- tmin = tmax + double_int_one;
- if (tmin.cmp (tmax, uns) < 0)
+ tmin = tmax + wide_int::one (largest_bitsize,
+ largest_precision);
+ if (tmin.lt_p (tmax, uns))
covers = true;
- tmax = tem + double_int_minus_one;
- if (tmax.cmp (tem, uns) > 0)
+ tmax = tem + wide_int::minus_one (largest_bitsize,
+ largest_precision);
+ if (tmax.gt_p (tem, uns))
covers = true;
/* If the anti-range would cover nothing, drop to varying.
Likewise if the anti-range bounds are outside of the
types values. */
- if (covers || tmin.cmp (tmax, uns) > 0)
+ if (covers || tmin.gt_p (tmax, uns))
{
set_value_range_to_varying (vr);
return;
}
- min = double_int_to_tree (expr_type, tmin);
- max = double_int_to_tree (expr_type, tmax);
+ min = wide_int_to_infinite_tree (expr_type, tmin,
+ largest_precision);
+ max = wide_int_to_infinite_tree (expr_type, tmax,
+ largest_precision);
}
}
else
@@ -2531,7 +2527,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& supports_overflow_infinity (expr_type))
min = negative_overflow_infinity (expr_type);
else
- min = double_int_to_tree (expr_type, type_min);
+ min = wide_int_to_infinite_tree (expr_type, type_min,
+ largest_precision);
}
else if (min_ovf == 1)
{
@@ -2539,10 +2536,12 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& supports_overflow_infinity (expr_type))
min = positive_overflow_infinity (expr_type);
else
- min = double_int_to_tree (expr_type, type_max);
+ min = wide_int_to_infinite_tree (expr_type, type_max,
+ largest_precision);
}
else
- min = double_int_to_tree (expr_type, dmin);
+ min = wide_int_to_infinite_tree (expr_type, dmin,
+ largest_precision);
if (max_ovf == -1)
{
@@ -2550,7 +2549,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& supports_overflow_infinity (expr_type))
max = negative_overflow_infinity (expr_type);
else
- max = double_int_to_tree (expr_type, type_min);
+ max = wide_int_to_infinite_tree (expr_type, type_min,
+ largest_precision);
}
else if (max_ovf == 1)
{
@@ -2558,10 +2558,12 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& supports_overflow_infinity (expr_type))
max = positive_overflow_infinity (expr_type);
else
- max = double_int_to_tree (expr_type, type_max);
+ max = wide_int_to_infinite_tree (expr_type, type_max,
+ largest_precision);
}
else
- max = double_int_to_tree (expr_type, dmax);
+ max = wide_int_to_infinite_tree (expr_type, dmax,
+ largest_precision);
}
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
@@ -2624,92 +2626,133 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& range_int_cst_p (&vr1)
&& TYPE_OVERFLOW_WRAPS (expr_type))
{
- double_int min0, max0, min1, max1, sizem1, size;
- double_int prod0l, prod0h, prod1l, prod1h,
- prod2l, prod2h, prod3l, prod3h;
- bool uns0, uns1, uns;
-
- sizem1 = double_int::max_value (TYPE_PRECISION (expr_type), true);
- size = sizem1 + double_int_one;
+ wide_int min0, max0, min1, max1, sizem1, size;
+ wide_int prod0, prod1, prod2, prod3;
+ wide_int::SignOp uns0, uns1, uns;
+
+ /* The largest_precision and the largest_bitsize are already
+ twice the size of the largest type that has been seen in
+ this function. We do not need to multiply them by a
+ factor of two again to do this analysis. So we trim them
+ down to the size of the largest types seen and then we
+ will fix things up at the end. */
+
+ int bs2 = largest_bitsize*2;
+ int prec2 = largest_precision*2;
+
+ /* Use the mode here to force the unsigned max value. */
+ sizem1 = wide_int::max_value (TYPE_MODE (expr_type), wide_int::UNSIGNED)
+ .force_to_size (largest_bitsize, largest_precision, wide_int::UNSIGNED)
+ .zext (TYPE_PRECISION (expr_type));
+ size = sizem1 + wide_int::one (largest_bitsize, largest_precision);
+
+ uns0 = TYPE_UNSIGNED (expr_type)
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+
+ min0 = tree_to_infinite_wide_int (vr0.min)
+ .force_to_size (largest_bitsize, largest_precision, uns0);
+ max0 = tree_to_infinite_wide_int (vr0.max)
+ .force_to_size (largest_bitsize, largest_precision, uns0);
+ min1 = tree_to_infinite_wide_int (vr1.min)
+ .force_to_size (largest_bitsize, largest_precision, uns0);
+ max1 = tree_to_infinite_wide_int (vr1.max)
+ .force_to_size (largest_bitsize, largest_precision, uns0);
- min0 = tree_to_double_int (vr0.min);
- max0 = tree_to_double_int (vr0.max);
- min1 = tree_to_double_int (vr1.min);
- max1 = tree_to_double_int (vr1.max);
-
- uns0 = TYPE_UNSIGNED (expr_type);
uns1 = uns0;
/* Canonicalize the intervals. */
if (TYPE_UNSIGNED (expr_type))
{
- double_int min2 = size - min0;
- if (min2.cmp (max0, true) < 0)
+ wide_int min2 = size - min0;
+ if (min2.ltu_p (max0))
{
- min0 = -min2;
- max0 -= size;
- uns0 = false;
+ min0 = min2.neg ();
+ max0 = max0 - size;
+ uns0 = wide_int::SIGNED;
}
min2 = size - min1;
- if (min2.cmp (max1, true) < 0)
+ if (min2.ltu_p (max1))
{
- min1 = -min2;
- max1 -= size;
- uns1 = false;
+ min1 = min2.neg();
+ max1 = max1 - size;
+ uns1 = wide_int::SIGNED;
}
}
- uns = uns0 & uns1;
-
- bool overflow;
- prod0l = min0.wide_mul_with_sign (min1, true, &prod0h, &overflow);
- if (!uns0 && min0.is_negative ())
- prod0h -= min1;
- if (!uns1 && min1.is_negative ())
- prod0h -= min0;
-
- prod1l = min0.wide_mul_with_sign (max1, true, &prod1h, &overflow);
- if (!uns0 && min0.is_negative ())
- prod1h -= max1;
- if (!uns1 && max1.is_negative ())
- prod1h -= min0;
-
- prod2l = max0.wide_mul_with_sign (min1, true, &prod2h, &overflow);
- if (!uns0 && max0.is_negative ())
- prod2h -= min1;
- if (!uns1 && min1.is_negative ())
- prod2h -= max0;
-
- prod3l = max0.wide_mul_with_sign (max1, true, &prod3h, &overflow);
- if (!uns0 && max0.is_negative ())
- prod3h -= max1;
- if (!uns1 && max1.is_negative ())
- prod3h -= max0;
-
- /* Sort the 4 products. */
- quad_int_pair_sort (&prod0l, &prod0h, &prod3l, &prod3h, uns);
- quad_int_pair_sort (&prod1l, &prod1h, &prod2l, &prod2h, uns);
- quad_int_pair_sort (&prod0l, &prod0h, &prod1l, &prod1h, uns);
- quad_int_pair_sort (&prod2l, &prod2h, &prod3l, &prod3h, uns);
- /* Max - min. */
- if (prod0l.is_zero ())
+ uns = ((uns0 == wide_int::UNSIGNED) & (uns1 == wide_int::UNSIGNED))
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+
+ prod0 = min0.umul_full (min1);
+ if (uns0 == wide_int::SIGNED && min0.neg_p ())
+ prod0 = prod0 - min1.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+ if (uns1 == wide_int::SIGNED && min1.neg_p ())
+ prod0 = prod0 - min0.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+
+ prod1 = min0.umul_full (max1);
+ if (uns0 == wide_int::SIGNED && min0.neg_p ())
+ prod1 = prod1 - max1.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+ if (uns1 == wide_int::SIGNED && max1.neg_p ())
+ prod1 = prod1 - min0.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+
+ prod2 = max0.umul_full (min1);
+ if (uns0 == wide_int::SIGNED && max0.neg_p ())
+ prod2 = prod2 - min1.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+ if (uns1 == wide_int::SIGNED && min1.neg_p ())
+ prod2 = prod2 - max0.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+
+ prod3 = max0.umul_full (max1);
+ if (uns0 == wide_int::SIGNED && max0.neg_p ())
+ prod3 = prod3 - max1.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+ if (uns1 == wide_int::SIGNED && max1.neg_p ())
+ prod3 = prod3 - max0.lshift (largest_precision, wide_int::NONE,
+ bs2, prec2);
+
+ /* Sort the 4 products so that min is in prod0 and max is in
+ prod3. */
+
+ /* min0min1 > max0max1 */
+ if (!prod0.lt_p (prod3, uns))
{
- prod1l = double_int_zero;
- prod1h = -prod0h;
+ wide_int tmp = prod0;
+ prod0 = prod3;
+ prod3 = tmp;
}
- else
+
+ /* min0max1 > max0min1 */
+ if (!prod1.lt_p (prod2, uns))
{
- prod1l = -prod0l;
- prod1h = ~prod0h;
+ wide_int tmp = prod1;
+ prod1 = prod2;
+ prod2 = tmp;
}
- prod2l = prod3l + prod1l;
- prod2h = prod3h + prod1h;
- if (prod2l.ult (prod3l))
- prod2h += double_int_one; /* carry */
- if (!prod2h.is_zero ()
- || prod2l.cmp (sizem1, true) >= 0)
+ if (!prod0.lt_p (prod1, uns))
+ {
+ wide_int tmp = prod0;
+ prod0 = prod1;
+ prod1 = tmp;
+ }
+
+ if (!prod2.lt_p (prod3, uns))
+ {
+ wide_int tmp = prod2;
+ prod2 = prod3;
+ prod3 = tmp;
+ }
+
+ /* Max - min. */
+ prod2 = prod3 - prod0;
+ if (sizem1.force_to_size (bs2, prec2,
+ wide_int::UNSIGNED)
+ .ltu_p (prod2))
{
/* the range covers all values. */
set_value_range_to_varying (vr);
@@ -2718,8 +2761,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* The following should handle the wrapping and selecting
VR_ANTI_RANGE for us. */
- min = double_int_to_tree (expr_type, prod0l);
- max = double_int_to_tree (expr_type, prod3l);
+ min = wide_int_to_infinite_tree (expr_type, prod0,
+ prec2);
+ max = wide_int_to_infinite_tree (expr_type, prod3,
+ prec2);
set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
return;
}
@@ -2766,11 +2811,11 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
bool saved_flag_wrapv;
value_range_t vr1p = VR_INITIALIZER;
vr1p.type = VR_RANGE;
- vr1p.min
- = double_int_to_tree (expr_type,
- double_int_one
- .llshift (tree_to_shwi (vr1.min),
- TYPE_PRECISION (expr_type)));
+ vr1p.min = wide_int_to_infinite_tree
+ (expr_type,
+ wide_int::set_bit_in_zero (tree_to_uhwi (vr1.min),
+ largest_bitsize, largest_precision),
+ largest_precision);
vr1p.max = vr1p.min;
/* We have to use a wrapping multiply though as signed overflow
on lshifts is implementation defined in C89. */
@@ -2787,7 +2832,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
int prec = TYPE_PRECISION (expr_type);
int overflow_pos = prec;
int bound_shift;
- double_int bound, complement, low_bound, high_bound;
+ wide_int bound, complement, low_bound, high_bound;
bool uns = TYPE_UNSIGNED (expr_type);
bool in_bounds = false;
@@ -2800,21 +2845,23 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
zero, which means vr1 is a singleton range of zero, which
means it should be handled by the previous LSHIFT_EXPR
if-clause. */
- bound = double_int_one.llshift (bound_shift, prec);
- complement = ~(bound - double_int_one);
+ bound = wide_int::set_bit_in_zero (bound_shift,
+ largest_bitsize,
+ largest_precision);
+ complement = bound.neg ();
if (uns)
{
low_bound = bound;
high_bound = complement.zext (prec);
- if (tree_to_double_int (vr0.max).ult (low_bound))
+ if (tree_to_infinite_wide_int (vr0.max).ltu_p (low_bound))
{
/* [5, 6] << [1, 2] == [10, 24]. */
/* We're shifting out only zeroes, the value increases
monotonically. */
in_bounds = true;
}
- else if (high_bound.ult (tree_to_double_int (vr0.min)))
+ else if (high_bound.ltu_p (tree_to_infinite_wide_int (vr0.min)))
{
/* [0xffffff00, 0xffffffff] << [1, 2]
== [0xfffffc00, 0xfffffffe]. */
@@ -2828,8 +2875,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
/* [-1, 1] << [1, 2] == [-4, 4]. */
low_bound = complement.sext (prec);
high_bound = bound;
- if (tree_to_double_int (vr0.max).slt (high_bound)
- && low_bound.slt (tree_to_double_int (vr0.min)))
+ if (tree_to_infinite_wide_int (vr0.max).lts_p (high_bound)
+ && low_bound.lts_p (tree_to_infinite_wide_int (vr0.min)))
{
/* For non-negative numbers, we're shifting out only
zeroes, the value increases monotonically.
@@ -2965,8 +3012,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
{
bool int_cst_range0, int_cst_range1;
- double_int may_be_nonzero0, may_be_nonzero1;
- double_int must_be_nonzero0, must_be_nonzero1;
+ wide_int may_be_nonzero0, may_be_nonzero1;
+ wide_int must_be_nonzero0, must_be_nonzero1;
int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0,
&must_be_nonzero0);
@@ -2976,10 +3023,13 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
type = VR_RANGE;
if (code == BIT_AND_EXPR)
{
- double_int dmax;
- min = double_int_to_tree (expr_type,
- must_be_nonzero0 & must_be_nonzero1);
+ wide_int dmax;
+
+ min = wide_int_to_infinite_tree (expr_type,
+ must_be_nonzero0 & must_be_nonzero1,
+ largest_precision);
dmax = 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. */
@@ -2987,27 +3037,26 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& tree_int_cst_sgn (vr0.max) < 0
&& tree_int_cst_sgn (vr1.max) < 0)
{
- dmax = dmax.min (tree_to_double_int (vr0.max),
- TYPE_UNSIGNED (expr_type));
- dmax = dmax.min (tree_to_double_int (vr1.max),
- TYPE_UNSIGNED (expr_type));
+ dmax = dmax.min (tree_to_infinite_wide_int (vr0.max), sgn);
+ dmax = dmax.min (tree_to_infinite_wide_int (vr1.max), sgn);
}
/* 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 = dmax.min (tree_to_double_int (vr0.max),
- TYPE_UNSIGNED (expr_type));
+ dmax = dmax.min (tree_to_infinite_wide_int (vr0.max), sgn);
+
if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
- dmax = dmax.min (tree_to_double_int (vr1.max),
- TYPE_UNSIGNED (expr_type));
- max = double_int_to_tree (expr_type, dmax);
+ dmax = dmax.min (tree_to_infinite_wide_int (vr1.max), sgn);
+ max = wide_int_to_infinite_tree (expr_type, dmax,
+ largest_precision);
}
else if (code == BIT_IOR_EXPR)
{
- double_int dmin;
- max = double_int_to_tree (expr_type,
- may_be_nonzero0 | may_be_nonzero1);
+ wide_int dmin;
+ max = wide_int_to_infinite_tree (expr_type,
+ may_be_nonzero0 | may_be_nonzero1,
+ largest_precision);
dmin = 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
@@ -3016,35 +3065,35 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
&& tree_int_cst_sgn (vr0.min) >= 0
&& tree_int_cst_sgn (vr1.min) >= 0)
{
- dmin = dmin.max (tree_to_double_int (vr0.min),
- TYPE_UNSIGNED (expr_type));
- dmin = dmin.max (tree_to_double_int (vr1.min),
- TYPE_UNSIGNED (expr_type));
+ dmin = dmin.max (tree_to_infinite_wide_int (vr0.min), sgn);
+ dmin = dmin.max (tree_to_infinite_wide_int (vr1.min), sgn);
}
/* 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 = dmin.max (tree_to_double_int (vr0.min),
- TYPE_UNSIGNED (expr_type));
+ dmin = dmin.max (tree_to_infinite_wide_int (vr0.min), sgn);
if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
- dmin = dmin.max (tree_to_double_int (vr1.min),
- TYPE_UNSIGNED (expr_type));
- min = double_int_to_tree (expr_type, dmin);
+ dmin = dmin.max (tree_to_infinite_wide_int (vr1.min), sgn);
+ min = wide_int_to_infinite_tree (expr_type, dmin,
+ largest_precision);
}
else if (code == BIT_XOR_EXPR)
{
- double_int result_zero_bits, result_one_bits;
- result_zero_bits = (must_be_nonzero0 & must_be_nonzero1)
- | ~(may_be_nonzero0 | may_be_nonzero1);
- result_one_bits = must_be_nonzero0.and_not (may_be_nonzero1)
- | must_be_nonzero1.and_not (may_be_nonzero0);
- max = double_int_to_tree (expr_type, ~result_zero_bits);
- min = double_int_to_tree (expr_type, result_one_bits);
+ wide_int result_zero_bits, result_one_bits;
+ result_zero_bits
+ = (must_be_nonzero0 & must_be_nonzero1).or_not
+ (may_be_nonzero0 | may_be_nonzero1);
+ result_one_bits
+ = must_be_nonzero0.and_not (may_be_nonzero1)
+ | must_be_nonzero1.and_not (may_be_nonzero0);
+ max = wide_int_to_infinite_tree (expr_type, ~result_zero_bits,
+ largest_precision);
+ min = wide_int_to_infinite_tree (expr_type, result_one_bits,
+ largest_precision);
/* 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)
+ if (tree_int_cst_sgn (min) < 0 || tree_int_cst_sgn (max) >= 0)
;
else
max = min = NULL_TREE;
@@ -3252,18 +3301,27 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
size_int (TYPE_PRECISION (outer_type)))))))
{
tree new_min, new_max;
+ wide_int::SignOp inner_type_sgn =
+ TYPE_UNSIGNED (inner_type) ? wide_int::UNSIGNED : wide_int::SIGNED;
+ /* We want to extend these from the inner type to the outer
+ type using the signedness of the inner type but the
+ precision of the outer type. */
if (is_overflow_infinity (vr0.min))
new_min = negative_overflow_infinity (outer_type);
else
- new_min = force_fit_type_double (outer_type,
- tree_to_double_int (vr0.min),
- 0, false);
+ new_min = wide_int_to_infinite_tree
+ (outer_type,
+ tree_to_infinite_wide_int (vr0.min)
+ .ext (TYPE_PRECISION (outer_type), inner_type_sgn),
+ largest_precision);
if (is_overflow_infinity (vr0.max))
new_max = positive_overflow_infinity (outer_type);
else
- new_max = force_fit_type_double (outer_type,
- tree_to_double_int (vr0.max),
- 0, false);
+ new_max = wide_int_to_infinite_tree
+ (outer_type,
+ tree_to_infinite_wide_int (vr0.max)
+ .ext (TYPE_PRECISION (outer_type), inner_type_sgn),
+ largest_precision);
set_and_canonicalize_value_range (vr, vr0.type,
new_min, new_max, NULL);
return;
@@ -3660,30 +3718,33 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
&& (TREE_CODE (init) != SSA_NAME
|| get_value_range (init)->type == VR_RANGE))
{
- double_int nit;
+ wide_int nit;
+ wide_int wstep = tree_to_infinite_wide_int (step);
/* We are only entering here for loop header PHI nodes, so using
the number of latch executions is the correct thing to use. */
- if (max_loop_iterations (loop, &nit))
+ if (max_loop_iterations (loop, &nit,
+ wstep.get_bitsize (), wstep.get_precision()))
{
value_range_t maxvr = VR_INITIALIZER;
- double_int dtmp;
- bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step));
+ wide_int dtmp;
+ wide_int::SignOp uns = TYPE_UNSIGNED (TREE_TYPE (step))
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
bool overflow = false;
- dtmp = tree_to_double_int (step)
- .mul_with_sign (nit, unsigned_p, &overflow);
+ dtmp = wstep.mul (nit, uns, &overflow);
/* If the multiplication overflowed we can't do a meaningful
adjustment. Likewise if the result doesn't fit in the type
of the induction variable. For a signed type we have to
check whether the result has the expected signedness which
is that of the step as number of iterations is unsigned. */
if (!overflow
- && double_int_fits_to_tree_p (TREE_TYPE (init), dtmp)
- && (unsigned_p
- || ((dtmp.high ^ TREE_INT_CST_HIGH (step)) >= 0)))
+ && dtmp.fits_to_tree_p (TREE_TYPE (init))
+ && (TYPE_UNSIGNED (TREE_TYPE (step))
+ || (dtmp.neg_p () == tree_int_cst_sign_bit (step))))
{
- tem = double_int_to_tree (TREE_TYPE (init), dtmp);
+ tem = wide_int_to_infinite_tree (TREE_TYPE (init), dtmp,
+ largest_precision);
extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
TREE_TYPE (init), init, tem);
/* Likewise if the addition did. */
@@ -4404,9 +4465,9 @@ register_new_assert_for (tree name, tree expr,
machinery. */
if (TREE_CODE (val) == INTEGER_CST
&& TREE_OVERFLOW (val))
- val = build_int_cst_wide (TREE_TYPE (val),
- TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
-
+ val = wide_int_to_infinite_tree
+ (TREE_TYPE (val), tree_to_infinite_wide_int (val), largest_precision);
+
/* The new assertion A will be inserted at BB or E. We need to
determine if the new location is dominated by a previously
registered location for A. If we are doing an edge insertion,
@@ -4558,23 +4619,27 @@ extract_code_and_val_from_cond_with_ops (tree name, enum tree_code cond_code,
(to transform signed values into unsigned) and at the end xor
SGNBIT back. */
-static double_int
-masked_increment (double_int val, double_int mask, double_int sgnbit,
- unsigned int prec)
+static wide_int
+masked_increment (const wide_int &val_in, const wide_int &mask_in,
+ const wide_int &sgnbit, const_tree type)
{
- double_int bit = double_int_one, res;
+ wide_int val = val_in.zext (TYPE_PRECISION (type));
+ wide_int mask = mask_in.zext (TYPE_PRECISION (type));
+ wide_int one = wide_int::one (largest_bitsize, largest_precision);
+ wide_int bit = one, res;
+ unsigned int prec = TYPE_PRECISION (type);
unsigned int i;
- val ^= sgnbit;
- for (i = 0; i < prec; i++, bit += bit)
+ val = val ^ sgnbit;
+ for (i = 0; i < prec; i++, bit = bit + bit)
{
res = mask;
- if ((res & bit).is_zero ())
+ if ((res & bit).zero_p())
continue;
- res = bit - double_int_one;
+ res = bit - one;
res = (val + bit).and_not (res);
- res &= mask;
- if (res.ugt (val))
+ res = res & mask;
+ if (res.gtu_p (val))
return res ^ sgnbit;
}
return val ^ sgnbit;
@@ -4710,8 +4775,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
gimple def_stmt = SSA_NAME_DEF_STMT (name);
tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
tree val2 = NULL_TREE;
- double_int mask = double_int_zero;
- unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
+ tree ntype = TREE_TYPE (val);
+ unsigned int prec = TYPE_PRECISION (ntype);
+ wide_int mask = wide_int::zero (largest_bitsize, largest_precision);
+
+ /* Add asserts for NAME cmp CST and NAME being defined
+ as NAME = (int) NAME2. */
unsigned int nprec = prec;
enum tree_code rhs_code = ERROR_MARK;
@@ -4780,12 +4849,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
&& tree_fits_uhwi_p (cst2)
&& INTEGRAL_TYPE_P (TREE_TYPE (name2))
&& IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
- && prec <= HOST_BITS_PER_DOUBLE_INT
&& prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))
&& live_on_edge (e, name2)
&& !has_single_use (name2))
{
- mask = double_int::mask (tree_to_uhwi (cst2));
+ mask = wide_int::mask (tree_to_uhwi (cst2), false,
+ largest_bitsize, largest_precision);
val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
}
}
@@ -4808,20 +4877,26 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
val2 = fold_convert (type, val2);
}
tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), tmp, val2);
- new_val = double_int_to_tree (TREE_TYPE (tmp), mask);
+ new_val = wide_int_to_infinite_tree (TREE_TYPE (tmp), mask,
+ largest_precision);
new_comp_code = comp_code == EQ_EXPR ? LE_EXPR : GT_EXPR;
}
else if (comp_code == LT_EXPR || comp_code == GE_EXPR)
new_val = val2;
else
{
- double_int maxval
- = double_int::max_value (prec, TYPE_UNSIGNED (TREE_TYPE (val)));
- mask |= tree_to_double_int (val2);
+ wide_int::SignOp uns = TYPE_UNSIGNED (TREE_TYPE (val))
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+
+ wide_int maxval = wide_int::max_value (TREE_TYPE (val))
+ .force_to_size (largest_bitsize, largest_precision, uns)
+ .ext (TYPE_PRECISION (TREE_TYPE (val)), wide_int::UNSIGNED);
+ mask = tree_to_infinite_wide_int (val2) | mask;
if (mask == maxval)
new_val = NULL_TREE;
else
- new_val = double_int_to_tree (TREE_TYPE (val2), mask);
+ new_val = wide_int_to_infinite_tree (TREE_TYPE (val2), mask,
+ largest_precision);
}
if (new_val)
@@ -4867,13 +4942,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
else
{
cst2 = TYPE_MAX_VALUE (TREE_TYPE (val));
- nprec = TYPE_PRECISION (TREE_TYPE (name2));
+ ntype = TREE_TYPE (name2);
+ nprec = TYPE_PRECISION (ntype);
}
if (TREE_CODE (name2) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (name2))
&& TREE_CODE (cst2) == INTEGER_CST
&& !integer_zerop (cst2)
- && nprec <= HOST_BITS_PER_DOUBLE_INT
&& (nprec > 1
|| TYPE_UNSIGNED (TREE_TYPE (val))))
{
@@ -4896,17 +4971,19 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
}
if (names[0] || names[1])
{
- double_int minv, maxv = double_int_zero, valv, cst2v;
- double_int tem, sgnbit;
+ wide_int minv, valv, cst2v;
+ wide_int zero = wide_int::zero (largest_bitsize, largest_precision);
+ wide_int maxv = zero;
+ wide_int tem, sgnbit;
bool valid_p = false, valn = false, cst2n = false;
enum tree_code ccode = comp_code;
- valv = tree_to_double_int (val).zext (nprec);
- cst2v = tree_to_double_int (cst2).zext (nprec);
+ valv = tree_to_infinite_wide_int (val).zext (nprec);
+ cst2v = tree_to_infinite_wide_int (cst2).zext (nprec);
if (!TYPE_UNSIGNED (TREE_TYPE (val)))
{
- valn = valv.sext (nprec).is_negative ();
- cst2n = cst2v.sext (nprec).is_negative ();
+ valn = valv.sext (nprec).neg_p ();
+ cst2n = cst2v.sext (nprec).neg_p ();
}
/* If CST2 doesn't have most significant bit set,
but VAL is negative, we have comparison like
@@ -4914,9 +4991,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
if (!cst2n && valn)
ccode = ERROR_MARK;
if (cst2n)
- sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
+ sgnbit = wide_int::set_bit_in_zero (nprec - 1,
+ largest_bitsize,
+ largest_precision);
else
- sgnbit = double_int_zero;
+ sgnbit = zero;
minv = valv & cst2v;
switch (ccode)
{
@@ -4925,34 +5004,35 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
(should be equal to VAL, otherwise we probably should
have folded the comparison into false) and
maximum unsigned value is VAL | ~CST2. */
- maxv = valv | ~cst2v;
+ maxv = valv.or_not (cst2v);
maxv = maxv.zext (nprec);
valid_p = true;
break;
case NE_EXPR:
- tem = valv | ~cst2v;
+ tem = valv.or_not (cst2v);
tem = tem.zext (nprec);
/* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U. */
- if (valv.is_zero ())
+ if (valv.zero_p ())
{
cst2n = false;
- sgnbit = double_int_zero;
+ sgnbit = zero;
goto gt_expr;
}
/* If (VAL | ~CST2) is all ones, handle it as
(X & CST2) < VAL. */
- if (tem == double_int::mask (nprec))
+ if (tem == wide_int::mask (nprec, false,
+ largest_bitsize, largest_precision))
{
cst2n = false;
valn = false;
- sgnbit = double_int_zero;
+ sgnbit = zero;
goto lt_expr;
}
- if (!cst2n
- && cst2v.sext (nprec).is_negative ())
- sgnbit
- = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
- if (!sgnbit.is_zero ())
+ if (!cst2n && cst2v.sext (nprec).neg_p ())
+ sgnbit = wide_int::set_bit_in_zero (nprec - 1,
+ largest_bitsize,
+ largest_precision);
+ if (!sgnbit.zero_p ())
{
if (valv == sgnbit)
{
@@ -4960,13 +5040,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
valn = true;
goto gt_expr;
}
- if (tem == double_int::mask (nprec - 1))
+ if (tem == wide_int::mask (nprec - 1, false,
+ largest_bitsize,
+ largest_precision))
{
cst2n = true;
goto lt_expr;
}
if (!cst2n)
- sgnbit = double_int_zero;
+ sgnbit = zero;
}
break;
case GE_EXPR:
@@ -4979,11 +5061,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
{
/* If (VAL & CST2) != VAL, X & CST2 can't be equal to
VAL. */
- minv = masked_increment (valv, cst2v, sgnbit, nprec);
+ minv = masked_increment (valv, cst2v, sgnbit, ntype);
if (minv == valv)
break;
}
- maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+ maxv = wide_int::mask (nprec - (cst2n ? 1 : 0), false,
+ largest_bitsize, largest_precision);
valid_p = true;
break;
case GT_EXPR:
@@ -4991,10 +5074,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
/* Find out smallest MINV where MINV > VAL
&& (MINV & CST2) == MINV, if any. If VAL is signed and
CST2 has MSB set, compute it biased by 1 << (nprec - 1). */
- minv = masked_increment (valv, cst2v, sgnbit, nprec);
+ minv = masked_increment (valv, cst2v, sgnbit, ntype);
if (minv == valv)
break;
- maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
+ maxv = wide_int::mask (nprec - (cst2n ? 1 : 0), false,
+ largest_bitsize, largest_precision);
valid_p = true;
break;
case LE_EXPR:
@@ -5010,12 +5094,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
maxv = valv;
else
{
- maxv = masked_increment (valv, cst2v, sgnbit, nprec);
+ maxv = masked_increment (valv, cst2v, sgnbit, ntype);
if (maxv == valv)
break;
- maxv -= double_int_one;
+ maxv = maxv - wide_int::one (largest_bitsize,
+ largest_precision);
}
- maxv |= ~cst2v;
+ maxv = maxv.or_not (cst2v);
maxv = maxv.zext (nprec);
minv = sgnbit;
valid_p = true;
@@ -5038,12 +5123,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
}
else
{
- maxv = masked_increment (valv, cst2v, sgnbit, nprec);
+ maxv = masked_increment (valv, cst2v, sgnbit, ntype);
if (maxv == valv)
break;
}
- maxv -= double_int_one;
- maxv |= ~cst2v;
+ maxv = maxv - wide_int::one (largest_bitsize,
+ largest_precision);
+ maxv = maxv.or_not (cst2v);
maxv = maxv.zext (nprec);
minv = sgnbit;
valid_p = true;
@@ -5052,7 +5138,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
break;
}
if (valid_p
- && (maxv - minv).zext (nprec) != double_int::mask (nprec))
+ && (maxv - minv).zext (nprec)
+ != wide_int::mask (nprec, false,
+ largest_bitsize, largest_precision))
{
tree tmp, new_val, type;
int i;
@@ -5060,7 +5148,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
for (i = 0; i < 2; i++)
if (names[i])
{
- double_int maxv2 = maxv;
+ wide_int maxv2 = maxv;
tmp = names[i];
type = TREE_TYPE (names[i]);
if (!TYPE_UNSIGNED (type))
@@ -5068,13 +5156,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
type = build_nonstandard_integer_type (nprec, 1);
tmp = build1 (NOP_EXPR, type, names[i]);
}
- if (!minv.is_zero ())
+ if (!minv.zero_p ())
{
tmp = build2 (PLUS_EXPR, type, tmp,
- double_int_to_tree (type, -minv));
+ wide_int_to_infinite_tree
+ (type, minv.neg (), largest_precision));
maxv2 = maxv - minv;
}
- new_val = double_int_to_tree (type, maxv2);
+ new_val = wide_int_to_infinite_tree (type, maxv2,
+ largest_precision);
if (dump_file)
{
@@ -5994,7 +6084,7 @@ search_for_addr_array (tree t, location_t location)
{
tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
tree low_bound, up_bound, el_sz;
- double_int idx;
+ wide_int idx;
if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
|| !TYPE_DOMAIN (TREE_TYPE (tem)))
@@ -6011,17 +6101,19 @@ search_for_addr_array (tree t, location_t location)
|| TREE_CODE (el_sz) != INTEGER_CST)
return;
- idx = mem_ref_offset (t);
- idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
- if (idx.slt (double_int_zero))
+ idx = mem_ref_offset (t).force_to_size (largest_bitsize,
+ largest_precision,
+ wide_int::SIGNED);
+ idx = idx.sdiv_trunc (tree_to_infinite_wide_int (el_sz));
+ if (idx.lts_p (0))
{
warning_at (location, OPT_Warray_bounds,
"array subscript is below array bounds");
TREE_NO_WARNING (t) = 1;
}
- else if (idx.sgt (tree_to_double_int (up_bound)
- - tree_to_double_int (low_bound)
- + double_int_one))
+ else if (idx.gts_p (tree_to_infinite_wide_int (up_bound)
+ - tree_to_infinite_wide_int (low_bound)
+ + wide_int::one (largest_bitsize, largest_precision)))
{
warning_at (location, OPT_Warray_bounds,
"array subscript is above array bounds");
@@ -6188,6 +6280,78 @@ remove_range_assertions (void)
}
+/* Return true if STMT is interesting for VRP and initialize
+ largest_bitsize and largest_precision. */
+
+static void
+look_for_largest (gimple stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ tree res = gimple_phi_result (stmt);
+ tree type = TREE_TYPE (res);
+
+ if (!virtual_operand_p (res)
+ && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+ {
+ largest_bitsize = MAX (largest_bitsize,
+ GET_MODE_BITSIZE (TYPE_MODE (type)));
+ largest_precision = MAX (largest_precision, TYPE_PRECISION (type));
+ }
+ }
+ else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
+ {
+ tree lhs = gimple_get_lhs (stmt);
+
+ /* In general, assignments with virtual operands are not useful
+ for deriving ranges, with the obvious exception of calls to
+ builtin functions. */
+ if (lhs && TREE_CODE (lhs) == SSA_NAME
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && ((is_gimple_call (stmt)
+ && gimple_call_fndecl (stmt) != NULL_TREE
+ && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
+ || !gimple_vuse (stmt)))
+ {
+ tree type = TREE_TYPE (lhs);
+ largest_bitsize = MAX (largest_bitsize,
+ GET_MODE_BITSIZE (TYPE_MODE (type)));
+ largest_precision = MAX (largest_precision, TYPE_PRECISION (type));
+ }
+ }
+}
+
+
+/* Find the largest integer types. */
+
+static void
+largest_initialize (void)
+{
+ basic_block bb;
+
+ largest_bitsize = GET_MODE_BITSIZE (word_mode);
+ largest_precision = GET_MODE_PRECISION (word_mode);
+
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator si;
+
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ look_for_largest (gsi_stmt (si));
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ look_for_largest (gsi_stmt (si));
+ }
+
+ /* We need to leave enough space so that we can see some bits above
+ the largest precision. */
+ largest_bitsize *= 2;
+ largest_bitsize = MIN (largest_bitsize, MAX_BITSIZE_MODE_ANY_INT);
+ largest_precision *= 2;
+ largest_precision = MIN (largest_precision, MAX_BITSIZE_MODE_ANY_INT);
+}
+
/* Return true if STMT is interesting for VRP. */
static bool
@@ -8256,9 +8420,9 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
tree op = NULL_TREE;
value_range_t vr0 = VR_INITIALIZER;
value_range_t vr1 = VR_INITIALIZER;
- double_int may_be_nonzero0, may_be_nonzero1;
- double_int must_be_nonzero0, must_be_nonzero1;
- double_int mask;
+ wide_int may_be_nonzero0, may_be_nonzero1;
+ wide_int must_be_nonzero0, must_be_nonzero1;
+ wide_int mask;
if (TREE_CODE (op0) == SSA_NAME)
vr0 = *(get_value_range (op0));
@@ -8283,13 +8447,13 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
{
case BIT_AND_EXPR:
mask = may_be_nonzero0.and_not (must_be_nonzero1);
- if (mask.is_zero ())
+ if (mask.zero_p ())
{
op = op0;
break;
}
mask = may_be_nonzero1.and_not (must_be_nonzero0);
- if (mask.is_zero ())
+ if (mask.zero_p ())
{
op = op1;
break;
@@ -8297,13 +8461,13 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
break;
case BIT_IOR_EXPR:
mask = may_be_nonzero0.and_not (must_be_nonzero1);
- if (mask.is_zero ())
+ if (mask.zero_p ())
{
op = op1;
break;
}
mask = may_be_nonzero1.and_not (must_be_nonzero0);
- if (mask.is_zero ())
+ if (mask.zero_p ())
{
op = op0;
break;
@@ -8573,15 +8737,18 @@ simplify_switch_using_ranges (gimple stmt)
static bool
simplify_conversion_using_ranges (gimple stmt)
{
- tree innerop, middleop, finaltype;
+ tree innerop, middleop;
+ tree middle_type, final_type;
gimple def_stmt;
value_range_t *innervr;
- bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
+ bool inner_unsigned_p;
unsigned inner_prec, middle_prec, final_prec;
- double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
+ wide_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
+ tree inner_type;
+ wide_int::SignOp inner_uns;
- finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
- if (!INTEGRAL_TYPE_P (finaltype))
+ final_type = TREE_TYPE (gimple_assign_lhs (stmt));
+ if (!INTEGRAL_TYPE_P (final_type))
return false;
middleop = gimple_assign_rhs1 (stmt);
def_stmt = SSA_NAME_DEF_STMT (middleop);
@@ -8601,43 +8768,48 @@ simplify_conversion_using_ranges (gimple stmt)
/* Simulate the conversion chain to check if the result is equal if
the middle conversion is removed. */
- innermin = tree_to_double_int (innervr->min);
- innermax = tree_to_double_int (innervr->max);
-
- inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
- middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
- final_prec = TYPE_PRECISION (finaltype);
-
+ innermin = tree_to_infinite_wide_int (innervr->min);
+ innermax = tree_to_infinite_wide_int (innervr->max);
+
+ inner_type = TREE_TYPE (innerop);
+ inner_prec = TYPE_PRECISION (inner_type);
+ middle_type = TREE_TYPE (middleop);
+ middle_prec = TYPE_PRECISION (middle_type);
+ final_prec = TYPE_PRECISION (final_type);
+
/* If the first conversion is not injective, the second must not
be widening. */
- if ((innermax - innermin).ugt (double_int::mask (middle_prec))
+ if ((innermax - innermin).gtu_p (wide_int::mask (middle_prec, false,
+ largest_bitsize,
+ largest_precision))
&& middle_prec < final_prec)
return false;
/* We also want a medium value so that we can track the effect that
narrowing conversions with sign change have. */
inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
+ inner_uns = inner_unsigned_p ? wide_int::UNSIGNED : wide_int::SIGNED;
if (inner_unsigned_p)
- innermed = double_int::mask (inner_prec).lrshift (1, inner_prec);
+ innermed = wide_int::mask (inner_prec - 1, false,
+ largest_bitsize, largest_precision);
else
- innermed = double_int_zero;
- if (innermin.cmp (innermed, inner_unsigned_p) >= 0
- || innermed.cmp (innermax, inner_unsigned_p) >= 0)
+ innermed = wide_int::zero (largest_bitsize, largest_precision);
+
+ if ((!innermin.lt_p (innermed, inner_uns))
+ || !innermed.lt_p (innermax, inner_uns))
innermed = innermin;
- middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
- middlemin = innermin.ext (middle_prec, middle_unsigned_p);
- middlemed = innermed.ext (middle_prec, middle_unsigned_p);
- middlemax = innermax.ext (middle_prec, middle_unsigned_p);
+ middlemin = innermin.ext (middle_type);
+ middlemed = innermed.ext (middle_type);
+ middlemax = innermax.ext (middle_type);
/* Require that the final conversion applied to both the original
and the intermediate range produces the same result. */
- final_unsigned_p = TYPE_UNSIGNED (finaltype);
- if (middlemin.ext (final_prec, final_unsigned_p)
- != innermin.ext (final_prec, final_unsigned_p)
- || middlemed.ext (final_prec, final_unsigned_p)
- != innermed.ext (final_prec, final_unsigned_p)
- || middlemax.ext (final_prec, final_unsigned_p)
- != innermax.ext (final_prec, final_unsigned_p))
+ if (middlemin.ext (final_type)
+ != innermin.ext (final_type)
+ || middlemed.ext (final_type)
+ != innermed.ext (final_type)
+ || middlemax.ext (final_type)
+ != innermax.ext (final_type))
return false;
gimple_assign_set_rhs1 (stmt, innerop);
@@ -8646,14 +8818,14 @@ simplify_conversion_using_ranges (gimple stmt)
}
/* Return whether the value range *VR fits in an integer type specified
- by PRECISION and UNSIGNED_P. */
+ by PRECISION. The operand is assumed to be signed. */
static bool
-range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
+range_fits_type_p (value_range_t *vr, unsigned precision)
{
tree src_type;
unsigned src_precision;
- double_int tem;
+ wide_int tem;
/* We can only handle integral and pointer types. */
src_type = TREE_TYPE (vr->min);
@@ -8665,7 +8837,7 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
if (src_precision < precision
|| (src_precision == precision
- && TYPE_UNSIGNED (src_type) == unsigned_p))
+ && !TYPE_UNSIGNED (src_type)))
return true;
/* Now we can only handle ranges with constant bounds. */
@@ -8674,19 +8846,13 @@ range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
|| TREE_CODE (vr->max) != INTEGER_CST)
return false;
- /* For precision-preserving sign-changes the MSB of the double-int
- has to be clear. */
- if (src_precision == precision
- && (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
- return false;
-
/* Then we can perform the conversion on both ends and compare
the result for equality. */
- tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
- if (tree_to_double_int (vr->min) != tem)
+ tem = tree_to_infinite_wide_int (vr->min).sext (precision);
+ if (tree_to_infinite_wide_int (vr->min) != tem)
return false;
- tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
- if (tree_to_double_int (vr->max) != tem)
+ tem = tree_to_infinite_wide_int (vr->max).sext (precision);
+ if (tree_to_infinite_wide_int (vr->max) != tem)
return false;
return true;
@@ -8715,7 +8881,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
&& (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0)
!= CODE_FOR_nothing)
&& range_fits_type_p (vr, GET_MODE_PRECISION
- (TYPE_MODE (TREE_TYPE (rhs1))), 0))
+ (TYPE_MODE (TREE_TYPE (rhs1)))))
mode = TYPE_MODE (TREE_TYPE (rhs1));
/* If we can do the conversion in the current input mode do nothing. */
else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)),
@@ -8732,7 +8898,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
or if the value-range does not fit in the signed type
try with a wider mode. */
if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing
- && range_fits_type_p (vr, GET_MODE_PRECISION (mode), 0))
+ && range_fits_type_p (vr, GET_MODE_PRECISION (mode)))
break;
mode = GET_MODE_WIDER_MODE (mode);
@@ -9152,6 +9318,7 @@ execute_vrp (void)
loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
scev_initialize ();
+ largest_initialize ();
insert_range_assertions ();
@@ -1074,15 +1074,27 @@ double_int_to_tree (tree type, double_int cst)
tree
wide_int_to_tree (tree type, const wide_int &cst)
{
- wide_int v;
+ wide_int v = cst.force_to_size ((const_tree)type);
+
+ return build_int_cst_wide (type, v.elt (0), v.elt (1));
+}
- gcc_assert (cst.get_len () <= 2);
- if (TYPE_UNSIGNED (type))
- v = cst.zext (TYPE_PRECISION (type));
- else
- v = cst.sext (TYPE_PRECISION (type));
+/* Constructs tree in type TYPE from with value given by CST.
+ Signedness of CST is assumed to be the same as the signedness of
+ TYPE. The number is represented in an infinite filed of PREC bits.
+ This number should be twice the sized of the largest integer mode
+ in the function being compiled. */
- return build_int_cst_wide (type, v.elt (0), v.elt (1));
+tree
+wide_int_to_infinite_tree (tree type, const wide_int &cst, unsigned int prec)
+{
+ wide_int::SignOp sgn = TYPE_UNSIGNED (type)
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+ wide_int v = cst.ext (TYPE_PRECISION (type), sgn);
+ HOST_WIDE_INT e1 = (prec <= HOST_BITS_PER_WIDE_INT)
+ ? v.elt (0) >> (HOST_BITS_PER_WIDE_INT - 1) : v.elt (1);
+
+ return build_int_cst_wide (type, v.elt (0), e1);
}
/* Return 0 or -1 depending on the sign of the cst. */
@@ -1265,6 +1277,61 @@ force_fit_type_double (tree type, double_int cst, int overflowable,
return double_int_to_tree (type, cst);
}
+/* We force the wide_int CST to the range of the type TYPE by sign or
+ zero extending it. OVERFLOWABLE indicates if we are interested in
+ overflow of the value, when >0 we are only interested in signed
+ overflow, for <0 we are interested in any overflow. OVERFLOWED
+ indicates whether overflow has already occurred. CONST_OVERFLOWED
+ indicates whether constant overflow has already occurred. We force
+ T's value to be within range of T's type (by setting to 0 or 1 all
+ the bits outside the type's range). We set TREE_OVERFLOWED if,
+ OVERFLOWED is nonzero,
+ or OVERFLOWABLE is >0 and signed overflow occurs
+ or OVERFLOWABLE is <0 and any overflow occurs
+ We return a new tree node for the extended wide_int. The node
+ is shared if no overflow flags are set. */
+
+
+tree
+force_fit_type_wide (tree type, const wide_int &cst, int overflowable,
+ bool overflowed)
+{
+ /* Size types *are* sign extended. */
+ bool sign_extended_type = !TYPE_UNSIGNED (type);
+
+ /* If we need to set overflow flags, return a new unshared node. */
+ if (overflowed || !cst.fits_to_tree_p (type))
+ {
+ if (overflowed
+ || overflowable < 0
+ || (overflowable > 0 && sign_extended_type))
+ {
+#ifdef NEW_REP_FOR_INT_CST
+ wide_int::SignOp uns = TYPE_UNSIGNED (type)
+ ? wide_int::UNSIGNED : wide_int::SIGNED;
+ const wide_int &r = cst.ext (TYPE_PRECISION (type), uns);
+ tree t = make_int_cst (r.get_len ());
+ int i;
+
+ for (i = 0; i < r.get_len (); ++i)
+ TREE_INT_CST_ELT (t, i) = r.elt (i);
+#else
+ tree t = make_node (INTEGER_CST);
+ double_int d = double_int::from_pair (cst.elt (1), cst.elt(0));
+
+ TREE_INT_CST (t) = d.ext (TYPE_PRECISION (type),
+ !sign_extended_type);
+#endif
+ TREE_TYPE (t) = type;
+ TREE_OVERFLOW (t) = 1;
+ return t;
+ }
+ }
+
+ /* Else build a shared node. */
+ return wide_int_to_tree (type, cst);
+}
+
/* These are the hash table functions for the hash table of INTEGER_CST
nodes of a sizetype. */
@@ -1293,6 +1360,7 @@ int_cst_hash_eq (const void *x, const void *y)
&& TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
}
+
/* Create an INT_CST node of TYPE and value HI:LOW.
The returned node is always shared. For small integers we use a
per-type vector cache, for larger ones we use a single hash table. */
@@ -4130,12 +4198,21 @@ build_simple_mem_ref_loc (location_t loc, tree ptr)
/* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T. */
double_int
-mem_ref_offset (const_tree t)
+mem_ref_offset_as_double (const_tree t)
{
tree toff = TREE_OPERAND (t, 1);
return tree_to_double_int (toff).sext (TYPE_PRECISION (TREE_TYPE (toff)));
}
+/* Return the constant offset of a MEM_REF or TARGET_MEM_REF tree T. */
+
+wide_int
+mem_ref_offset (const_tree t)
+{
+ tree toff = TREE_OPERAND (t, 1);
+ return wide_int::from_tree (toff);
+}
+
/* Return the pointer-type relevant for TBAA purposes from the
gimple memory reference tree T. This is the type to be used for
the offset operand of MEM_REF or TARGET_MEM_REF replacements of T. */
@@ -5835,7 +5835,7 @@ extern tree fold_indirect_ref_loc (location_t, tree);
extern tree build_simple_mem_ref_loc (location_t, tree);
#define build_simple_mem_ref(T)\
build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
-extern double_int mem_ref_offset (const_tree);
+extern double_int mem_ref_offset_as_double (const_tree);
extern tree reference_alias_ptr_type (const_tree);
extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
extern tree constant_boolean_node (bool, tree);
@@ -2583,7 +2583,7 @@ decode_addr_const (tree exp, struct addr_const *value)
else if (TREE_CODE (target) == MEM_REF
&& TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR)
{
- offset += mem_ref_offset (target).low;
+ offset += mem_ref_offset_as_double (target).low;
target = TREE_OPERAND (TREE_OPERAND (target, 0), 0);
}
else if (TREE_CODE (target) == INDIRECT_REF