===================================================================
@@ -2213,6 +2213,22 @@ extract_range_from_multiplicative_op_1 (
set_value_range (vr, type, min, max, NULL);
}
+/* vrp_int is twice as wide as anything that the target supports so it
+ can support a full width multiply. No need to add any more padding
+ for an extra sign bit because that comes with the way that
+ WIDE_INT_MAX_ELTS is defined. */
+typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION * 2) vrp_int;
+namespace wi
+{
+ generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION * 2> > to_vrp (const_tree);
+}
+
+inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> >
+wi::to_vrp (const_tree t)
+{
+ return t;
+}
+
/* 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. */
@@ -2620,22 +2636,21 @@ extract_range_from_binary_expr_1 (value_
signop sign = TYPE_SIGN (expr_type);
unsigned int prec = TYPE_PRECISION (expr_type);
- unsigned int prec2 = (prec * 2) + (sign == UNSIGNED ? 2 : 0);
if (range_int_cst_p (&vr0)
&& range_int_cst_p (&vr1)
&& TYPE_OVERFLOW_WRAPS (expr_type))
{
- wide_int sizem1 = wi::mask (prec, false, prec2);
- wide_int size = sizem1 + 1;
+ vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
+ vrp_int size = sizem1 + 1;
/* Extend the values using the sign of the result to PREC2.
From here on out, everthing is just signed math no matter
what the input types were. */
- wide_int min0 = wide_int::from (vr0.min, prec2, sign);
- wide_int max0 = wide_int::from (vr0.max, prec2, sign);
- wide_int min1 = wide_int::from (vr1.min, prec2, sign);
- wide_int max1 = wide_int::from (vr1.max, prec2, sign);
+ vrp_int min0 = wi::to_vrp (vr0.min);
+ vrp_int max0 = wi::to_vrp (vr0.max);
+ vrp_int min1 = wi::to_vrp (vr1.min);
+ vrp_int max1 = wi::to_vrp (vr1.max);
/* Canonicalize the intervals. */
if (sign == UNSIGNED)
@@ -2653,17 +2668,17 @@ extract_range_from_binary_expr_1 (value_
}
}
- wide_int prod0 = min0 * min1;
- wide_int prod1 = min0 * max1;
- wide_int prod2 = max0 * min1;
- wide_int prod3 = max0 * max1;
+ vrp_int prod0 = min0 * min1;
+ vrp_int prod1 = min0 * max1;
+ vrp_int prod2 = max0 * min1;
+ vrp_int prod3 = max0 * max1;
/* Sort the 4 products so that min is in prod0 and max is in
prod3. */
/* min0min1 > max0max1 */
if (wi::gts_p (prod0, prod3))
{
- wide_int tmp = prod3;
+ vrp_int tmp = prod3;
prod3 = prod0;
prod0 = tmp;
}
@@ -2671,21 +2686,21 @@ extract_range_from_binary_expr_1 (value_
/* min0max1 > max0min1 */
if (wi::gts_p (prod1, prod2))
{
- wide_int tmp = prod2;
+ vrp_int tmp = prod2;
prod2 = prod1;
prod1 = tmp;
}
if (wi::gts_p (prod0, prod1))
{
- wide_int tmp = prod1;
+ vrp_int tmp = prod1;
prod1 = prod0;
prod0 = tmp;
}
if (wi::gts_p (prod2, prod3))
{
- wide_int tmp = prod3;
+ vrp_int tmp = prod3;
prod3 = prod2;
prod2 = tmp;
}
===================================================================
@@ -4549,7 +4549,7 @@ namespace wi
static const unsigned int precision = N;
};
- generic_wide_int <extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
+ generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION> >
to_widest (const_tree);
generic_wide_int <extended_tree <ADDR_MAX_PRECISION> > to_offset (const_tree);
@@ -4570,7 +4570,7 @@ wi::int_traits <const_tree>::decompose (
precision);
}
-inline generic_wide_int <wi::extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
+inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION> >
wi::to_widest (const_tree t)
{
return t;
@@ -4609,7 +4609,7 @@ wi::extended_tree <N>::get_len () const
{
if (N == ADDR_MAX_PRECISION)
return TREE_INT_CST_OFFSET_NUNITS (m_t);
- else if (N == MAX_BITSIZE_MODE_ANY_INT)
+ else if (N >= WIDE_INT_MAX_PRECISION)
return TREE_INT_CST_EXT_NUNITS (m_t);
else
/* This class is designed to be used for specific output precisions
===================================================================
@@ -228,15 +228,17 @@ along with GCC; see the file COPYING3.
#endif
/* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
- early examination of the target's mode file. Thus it is safe that
- some small multiple of this number is easily larger than any number
- that that target could compute. The place in the compiler that
- currently needs the widest ints is the code that determines the
- range of a multiply. This code needs 2n + 2 bits. */
-
+ early examination of the target's mode file. The WIDE_INT_MAX_ELTS
+ can accomodate at least 1 more bit so that unsigned numbers of that
+ mode can be represented. Note that it is still possible to create
+ fixed_wide_ints that have precisions greater than
+ MAX_BITSIZE_MODE_ANY_INT. This can be useful when representing a
+ double-width multiplication result, for example. */
#define WIDE_INT_MAX_ELTS \
- ((4 * MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
- / HOST_BITS_PER_WIDE_INT)
+ (((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT - 1) \
+ / HOST_BITS_PER_WIDE_INT) + 1)
+
+#define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
/* This is the max size of any pointer on any machine. It does not
seem to be as easy to sniff this out of the machine description as
@@ -294,7 +296,7 @@ struct wide_int_storage;
typedef generic_wide_int <wide_int_storage> wide_int;
typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
-typedef FIXED_WIDE_INT (MAX_BITSIZE_MODE_ANY_INT) widest_int;
+typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int;
template <bool SE>
struct wide_int_ref_storage;