wide-int branch now up for public comment and review
Richard Sandiford
rdsandiford@googlemail.com
Sat Aug 24 13:10:00 GMT 2013
Richard Sandiford <rdsandiford@googlemail.com> writes:
> I wonder how easy it would be to restrict this use of "zero precision"
> (i.e. flexible precision) to those where primitive types like "int" are
> used as template arguments to operators, and require a precision when
> constructing a wide_int. I wouldn't have expected "real" precision 0
> (from zero-width bitfields or whatever) to need any special handling
> compared to precision 1 or 2.
I tried the last bit -- requiring a precision when constructing a
wide_int -- and it seemed surprising easy. What do you think of
the attached? Most of the forced knock-on changes seem like improvements,
but the java part is a bit ugly. I also went with "wide_int (0, prec).cmp"
for now, although I'd like to add static cmp, cmps and cmpu alongside
leu_p, etc., if that's OK. It would then be possible to write
"wide_int::cmp (0, ...)" and avoid the wide_int construction altogether.
I wondered whether you might also want to get rid of the build_int_cst*
functions, but that still looks a long way off, so I hope using them in
these two places doesn't seem too bad.
This is just an incremental step. I've also only run it through a
subset of the testsuite so far, but full tests are in progress...
Thanks,
Richard
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/fold-const.c 2013-08-24 01:00:00.000000000 +0100
@@ -8865,15 +8865,16 @@ pointer_may_wrap_p (tree base, tree offs
if (bitpos < 0)
return true;
+ int precision = TYPE_PRECISION (TREE_TYPE (base));
if (offset == NULL_TREE)
- wi_offset = wide_int::zero (TYPE_PRECISION (TREE_TYPE (base)));
+ wi_offset = wide_int::zero (precision);
else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
return true;
else
wi_offset = offset;
bool overflow;
- wide_int units = wide_int::from_shwi (bitpos / BITS_PER_UNIT);
+ wide_int units = wide_int::from_shwi (bitpos / BITS_PER_UNIT, precision);
total = wi_offset.add (units, UNSIGNED, &overflow);
if (overflow)
return true;
Index: gcc/gimple-ssa-strength-reduction.c
===================================================================
--- gcc/gimple-ssa-strength-reduction.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/gimple-ssa-strength-reduction.c 2013-08-24 01:00:00.000000000 +0100
@@ -777,7 +777,6 @@ restructure_reference (tree *pbase, tree
{
tree base = *pbase, offset = *poffset;
max_wide_int index = *pindex;
- wide_int bpu = BITS_PER_UNIT;
tree mult_op0, t1, t2, type;
max_wide_int c1, c2, c3, c4;
@@ -786,7 +785,7 @@ restructure_reference (tree *pbase, tree
|| TREE_CODE (base) != MEM_REF
|| TREE_CODE (offset) != MULT_EXPR
|| TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
- || !index.umod_floor (bpu).zero_p ())
+ || !index.umod_floor (BITS_PER_UNIT).zero_p ())
return false;
t1 = TREE_OPERAND (base, 0);
@@ -822,7 +821,7 @@ restructure_reference (tree *pbase, tree
c2 = 0;
}
- c4 = index.udiv_floor (bpu);
+ c4 = index.udiv_floor (BITS_PER_UNIT);
*pbase = t1;
*poffset = fold_build2 (MULT_EXPR, sizetype, t2,
Index: gcc/java/jcf-parse.c
===================================================================
--- gcc/java/jcf-parse.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/java/jcf-parse.c 2013-08-24 01:00:00.000000000 +0100
@@ -1043,9 +1043,10 @@ get_constant (JCF *jcf, int index)
wide_int val;
num = JPOOL_UINT (jcf, index);
- val = wide_int (num).sforce_to_size (32).lshift_widen (32, 64);
+ val = wide_int::from_hwi (num, long_type_node)
+ .sforce_to_size (32).lshift_widen (32, 64);
num = JPOOL_UINT (jcf, index + 1);
- val |= wide_int (num);
+ val |= wide_int::from_hwi (num, long_type_node);
value = wide_int_to_tree (long_type_node, val);
break;
Index: gcc/loop-unroll.c
===================================================================
--- gcc/loop-unroll.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/loop-unroll.c 2013-08-24 01:00:00.000000000 +0100
@@ -816,8 +816,7 @@ unroll_loop_constant_iterations (struct
desc->niter -= exit_mod;
loop->nb_iterations_upper_bound -= exit_mod;
if (loop->any_estimate
- && wide_int (exit_mod).leu_p
- (loop->nb_iterations_estimate))
+ && wide_int::leu_p (exit_mod, loop->nb_iterations_estimate))
loop->nb_iterations_estimate -= exit_mod;
else
loop->any_estimate = false;
@@ -860,8 +859,7 @@ unroll_loop_constant_iterations (struct
desc->niter -= exit_mod + 1;
loop->nb_iterations_upper_bound -= exit_mod + 1;
if (loop->any_estimate
- && wide_int (exit_mod + 1).leu_p
- (loop->nb_iterations_estimate))
+ && wide_int::leu_p (exit_mod + 1, loop->nb_iterations_estimate))
loop->nb_iterations_estimate -= exit_mod + 1;
else
loop->any_estimate = false;
@@ -1381,7 +1379,7 @@ decide_peel_simple (struct loop *loop, i
if (estimated_loop_iterations (loop, &iterations))
{
/* TODO: unsigned/signed confusion */
- if (wide_int::from_shwi (npeel).leu_p (iterations))
+ if (wide_int::leu_p (npeel, iterations))
{
if (dump_file)
{
Index: gcc/real.c
===================================================================
--- gcc/real.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/real.c 2013-08-24 01:00:00.000000000 +0100
@@ -2401,7 +2401,7 @@ real_digit (int n)
gcc_assert (n <= 9);
if (n > 0 && num[n].cl == rvc_zero)
- real_from_integer (&num[n], VOIDmode, wide_int (n), UNSIGNED);
+ real_from_integer (&num[n], VOIDmode, n, UNSIGNED);
return &num[n];
}
Index: gcc/tree-predcom.c
===================================================================
--- gcc/tree-predcom.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree-predcom.c 2013-08-24 01:00:00.000000000 +0100
@@ -923,7 +923,7 @@ add_ref_to_chain (chain_p chain, dref re
gcc_assert (root->offset.les_p (ref->offset));
dist = ref->offset - root->offset;
- if (max_wide_int::from_uhwi (MAX_DISTANCE).leu_p (dist))
+ if (wide_int::leu_p (MAX_DISTANCE, dist))
{
free (ref);
return;
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c 2013-08-24 12:48:00.091379339 +0100
+++ gcc/tree-pretty-print.c 2013-08-24 01:00:00.000000000 +0100
@@ -1295,7 +1295,7 @@ dump_generic_node (pretty_printer *buffe
tree field, val;
bool is_struct_init = false;
bool is_array_init = false;
- wide_int curidx = 0;
+ wide_int curidx;
pp_left_brace (buffer);
if (TREE_CLOBBER_P (node))
pp_string (buffer, "CLOBBER");
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree-ssa-ccp.c 2013-08-24 01:00:00.000000000 +0100
@@ -526,7 +526,7 @@ get_value_from_alignment (tree expr)
: -1).and_not (align / BITS_PER_UNIT - 1);
val.lattice_val = val.mask.minus_one_p () ? VARYING : CONSTANT;
if (val.lattice_val == CONSTANT)
- val.value = wide_int_to_tree (type, bitpos / BITS_PER_UNIT);
+ val.value = build_int_cstu (type, bitpos / BITS_PER_UNIT);
else
val.value = NULL_TREE;
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c 2013-08-24 12:48:00.093379358 +0100
+++ gcc/tree-vrp.c 2013-08-24 01:00:00.000000000 +0100
@@ -2420,9 +2420,9 @@ extract_range_from_binary_expr_1 (value_
wmin = min0 - max1;
wmax = max0 - min1;
- if (wide_int (0).cmp (max1, sgn) != wmin.cmp (min0, sgn))
+ if (wide_int (0, prec).cmp (max1, sgn) != wmin.cmp (min0, sgn))
min_ovf = min0.cmp (max1, sgn);
- if (wide_int (0).cmp (min1, sgn) != wmax.cmp (max0, sgn))
+ if (wide_int (0, prec).cmp (min1, sgn) != wmax.cmp (max0, sgn))
max_ovf = max0.cmp (min1, sgn);
}
@@ -4911,8 +4911,8 @@ register_edge_assert_for_2 (tree name, e
gimple def_stmt = SSA_NAME_DEF_STMT (name);
tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
tree val2 = NULL_TREE;
- wide_int mask = 0;
unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
+ wide_int mask (0, prec);
unsigned int nprec = prec;
enum tree_code rhs_code = ERROR_MARK;
@@ -5101,7 +5101,7 @@ register_edge_assert_for_2 (tree name, e
}
if (names[0] || names[1])
{
- wide_int minv, maxv = 0, valv, cst2v;
+ wide_int minv, maxv, valv, cst2v;
wide_int tem, sgnbit;
bool valid_p = false, valn = false, cst2n = false;
enum tree_code ccode = comp_code;
@@ -5170,7 +5170,7 @@ register_edge_assert_for_2 (tree name, e
goto lt_expr;
}
if (!cst2n)
- sgnbit = 0;
+ sgnbit = wide_int::zero (nprec);
}
break;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c 2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree.c 2013-08-24 01:00:00.000000000 +0100
@@ -1048,13 +1048,13 @@ build_int_cst (tree type, HOST_WIDE_INT
if (!type)
type = integer_type_node;
- return wide_int_to_tree (type, low);
+ return wide_int_to_tree (type, wide_int::from_hwi (low, type));
}
/* static inline */ tree
build_int_cstu (tree type, unsigned HOST_WIDE_INT cst)
{
- return wide_int_to_tree (type, cst);
+ return wide_int_to_tree (type, wide_int::from_hwi (cst, type));
}
/* Create an INT_CST node with a LOW value sign extended to TYPE. */
@@ -1064,7 +1064,7 @@ build_int_cst_type (tree type, HOST_WIDE
{
gcc_assert (type);
- return wide_int_to_tree (type, low);
+ return wide_int_to_tree (type, wide_int::from_hwi (low, type));
}
/* Constructs tree in type TYPE from with value given by CST. Signedness
@@ -10688,7 +10688,7 @@ lower_bound_in_type (tree outer, tree in
contains all values of INNER type. In particular, both INNER
and OUTER types have zero in common. */
|| (oprec > iprec && TYPE_UNSIGNED (inner)))
- return wide_int_to_tree (outer, 0);
+ return build_int_cst (outer, 0);
else
{
/* If we are widening a signed type to another signed type, we
Index: gcc/wide-int.cc
===================================================================
--- gcc/wide-int.cc 2013-08-24 12:48:00.096379386 +0100
+++ gcc/wide-int.cc 2013-08-24 01:00:00.000000000 +0100
@@ -32,6 +32,8 @@ along with GCC; see the file COPYING3.
const int MAX_SIZE = 4 * (MAX_BITSIZE_MODE_ANY_INT / 4
+ MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT + 32);
+static const HOST_WIDE_INT zeros[WIDE_INT_MAX_ELTS] = {};
+
/*
* Internal utilities.
*/
@@ -2517,7 +2519,7 @@ wide_int_ro::divmod_internal (bool compu
{
if (top_bit_of (dividend, dividend_len, dividend_prec))
{
- u0 = sub_large (wide_int (0).val, 1,
+ u0 = sub_large (zeros, 1,
dividend_prec, dividend, dividend_len, UNSIGNED);
dividend = u0.val;
dividend_len = u0.len;
@@ -2525,7 +2527,7 @@ wide_int_ro::divmod_internal (bool compu
}
if (top_bit_of (divisor, divisor_len, divisor_prec))
{
- u1 = sub_large (wide_int (0).val, 1,
+ u1 = sub_large (zeros, 1,
divisor_prec, divisor, divisor_len, UNSIGNED);
divisor = u1.val;
divisor_len = u1.len;
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h 2013-08-24 12:14:20.979479335 +0100
+++ gcc/wide-int.h 2013-08-24 01:00:00.000000000 +0100
@@ -230,6 +230,11 @@ #define WIDE_INT_H
#define DEBUG_WIDE_INT
#endif
+/* Used for overloaded functions in which the only other acceptable
+ scalar type is const_tree. It stops a plain 0 from being treated
+ as a null tree. */
+struct never_used {};
+
/* 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
@@ -324,15 +329,16 @@ class GTY(()) wide_int_ro
public:
wide_int_ro ();
wide_int_ro (const_tree);
- wide_int_ro (HOST_WIDE_INT);
- wide_int_ro (int);
- wide_int_ro (unsigned HOST_WIDE_INT);
- wide_int_ro (unsigned int);
+ wide_int_ro (never_used *);
+ wide_int_ro (HOST_WIDE_INT, unsigned int);
+ wide_int_ro (int, unsigned int);
+ wide_int_ro (unsigned HOST_WIDE_INT, unsigned int);
+ wide_int_ro (unsigned int, unsigned int);
wide_int_ro (const rtx_mode_t &);
/* Conversions. */
- static wide_int_ro from_shwi (HOST_WIDE_INT, unsigned int = 0);
- static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, unsigned int = 0);
+ static wide_int_ro from_shwi (HOST_WIDE_INT, unsigned int);
+ static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, unsigned int);
static wide_int_ro from_hwi (HOST_WIDE_INT, const_tree);
static wide_int_ro from_shwi (HOST_WIDE_INT, enum machine_mode);
static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, enum machine_mode);
@@ -349,9 +355,11 @@ class GTY(()) wide_int_ro
static wide_int_ro max_value (unsigned int, signop, unsigned int = 0);
static wide_int_ro max_value (const_tree);
+ static wide_int_ro max_value (never_used *);
static wide_int_ro max_value (enum machine_mode, signop);
static wide_int_ro min_value (unsigned int, signop, unsigned int = 0);
static wide_int_ro min_value (const_tree);
+ static wide_int_ro min_value (never_used *);
static wide_int_ro min_value (enum machine_mode, signop);
/* Small constants. These are generally only needed in the places
@@ -842,18 +850,16 @@ class GTY(()) wide_int : public wide_int
wide_int ();
wide_int (const wide_int_ro &);
wide_int (const_tree);
- wide_int (HOST_WIDE_INT);
- wide_int (int);
- wide_int (unsigned HOST_WIDE_INT);
- wide_int (unsigned int);
+ wide_int (never_used *);
+ wide_int (HOST_WIDE_INT, unsigned int);
+ wide_int (int, unsigned int);
+ wide_int (unsigned HOST_WIDE_INT, unsigned int);
+ wide_int (unsigned int, unsigned int);
wide_int (const rtx_mode_t &);
wide_int &operator = (const wide_int_ro &);
wide_int &operator = (const_tree);
- wide_int &operator = (HOST_WIDE_INT);
- wide_int &operator = (int);
- wide_int &operator = (unsigned HOST_WIDE_INT);
- wide_int &operator = (unsigned int);
+ wide_int &operator = (never_used *);
wide_int &operator = (const rtx_mode_t &);
wide_int &operator ++ ();
@@ -904,28 +910,28 @@ inline wide_int_ro::wide_int_ro (const_t
TYPE_PRECISION (TREE_TYPE (tcst)), false);
}
-inline wide_int_ro::wide_int_ro (HOST_WIDE_INT op0)
+inline wide_int_ro::wide_int_ro (HOST_WIDE_INT op0, unsigned int prec)
{
- precision = 0;
+ precision = prec;
val[0] = op0;
len = 1;
}
-inline wide_int_ro::wide_int_ro (int op0)
+inline wide_int_ro::wide_int_ro (int op0, unsigned int prec)
{
- precision = 0;
+ precision = prec;
val[0] = op0;
len = 1;
}
-inline wide_int_ro::wide_int_ro (unsigned HOST_WIDE_INT op0)
+inline wide_int_ro::wide_int_ro (unsigned HOST_WIDE_INT op0, unsigned int prec)
{
- *this = from_uhwi (op0);
+ *this = from_uhwi (op0, prec);
}
-inline wide_int_ro::wide_int_ro (unsigned int op0)
+inline wide_int_ro::wide_int_ro (unsigned int op0, unsigned int prec)
{
- *this = from_uhwi (op0);
+ *this = from_uhwi (op0, prec);
}
inline wide_int_ro::wide_int_ro (const rtx_mode_t &op0)
@@ -2264,7 +2270,7 @@ wide_int_ro::mul_high (const T &c, signo
wide_int_ro::operator - () const
{
wide_int_ro r;
- r = wide_int_ro (0) - *this;
+ r = zero (precision) - *this;
return r;
}
@@ -2277,7 +2283,7 @@ wide_int_ro::neg (bool *overflow) const
*overflow = only_sign_bit_p ();
- return wide_int_ro (0) - *this;
+ return zero (precision) - *this;
}
/* Return THIS - C. */
@@ -3147,28 +3153,28 @@ inline wide_int::wide_int (const_tree tc
TYPE_PRECISION (TREE_TYPE (tcst)), false);
}
-inline wide_int::wide_int (HOST_WIDE_INT op0)
+inline wide_int::wide_int (HOST_WIDE_INT op0, unsigned int prec)
{
- precision = 0;
+ precision = prec;
val[0] = op0;
len = 1;
}
-inline wide_int::wide_int (int op0)
+inline wide_int::wide_int (int op0, unsigned int prec)
{
- precision = 0;
+ precision = prec;
val[0] = op0;
len = 1;
}
-inline wide_int::wide_int (unsigned HOST_WIDE_INT op0)
+inline wide_int::wide_int (unsigned HOST_WIDE_INT op0, unsigned int prec)
{
- *this = wide_int_ro::from_uhwi (op0);
+ *this = wide_int_ro::from_uhwi (op0, prec);
}
-inline wide_int::wide_int (unsigned int op0)
+inline wide_int::wide_int (unsigned int op0, unsigned int prec)
{
- *this = wide_int_ro::from_uhwi (op0);
+ *this = wide_int_ro::from_uhwi (op0, prec);
}
inline wide_int::wide_int (const rtx_mode_t &op0)
@@ -3567,31 +3573,28 @@ inline fixed_wide_int <bitsize>::fixed_w
template <int bitsize>
inline fixed_wide_int <bitsize>::fixed_wide_int (HOST_WIDE_INT op0)
- : wide_int_ro (op0)
+ : wide_int_ro (op0, bitsize)
{
- precision = bitsize;
}
template <int bitsize>
-inline fixed_wide_int <bitsize>::fixed_wide_int (int op0) : wide_int_ro (op0)
+inline fixed_wide_int <bitsize>::fixed_wide_int (int op0)
+ : wide_int_ro (op0, bitsize)
{
- precision = bitsize;
}
template <int bitsize>
inline fixed_wide_int <bitsize>::fixed_wide_int (unsigned HOST_WIDE_INT op0)
- : wide_int_ro (op0)
+ : wide_int_ro (op0, bitsize)
{
- precision = bitsize;
if (neg_p (SIGNED))
static_cast <wide_int_ro &> (*this) = zext (HOST_BITS_PER_WIDE_INT);
}
template <int bitsize>
inline fixed_wide_int <bitsize>::fixed_wide_int (unsigned int op0)
- : wide_int_ro (op0)
+ : wide_int_ro (op0, bitsize)
{
- precision = bitsize;
if (sizeof (int) == sizeof (HOST_WIDE_INT)
&& neg_p (SIGNED))
*this = zext (HOST_BITS_PER_WIDE_INT);
@@ -3661,9 +3664,7 @@ fixed_wide_int <bitsize>::operator = (co
inline fixed_wide_int <bitsize> &
fixed_wide_int <bitsize>::operator = (HOST_WIDE_INT op0)
{
- static_cast <wide_int_ro &> (*this) = op0;
- precision = bitsize;
-
+ static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
return *this;
}
@@ -3671,9 +3672,7 @@ fixed_wide_int <bitsize>::operator = (HO
inline fixed_wide_int <bitsize> &
fixed_wide_int <bitsize>::operator = (int op0)
{
- static_cast <wide_int_ro &> (*this) = op0;
- precision = bitsize;
-
+ static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
return *this;
}
@@ -3681,8 +3680,7 @@ fixed_wide_int <bitsize>::operator = (in
inline fixed_wide_int <bitsize> &
fixed_wide_int <bitsize>::operator = (unsigned HOST_WIDE_INT op0)
{
- static_cast <wide_int_ro &> (*this) = op0;
- precision = bitsize;
+ static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
/* This is logically top_bit_set_p. */
if (neg_p (SIGNED))
@@ -3695,8 +3693,7 @@ fixed_wide_int <bitsize>::operator = (un
inline fixed_wide_int <bitsize> &
fixed_wide_int <bitsize>::operator = (unsigned int op0)
{
- static_cast <wide_int_ro &> (*this) = op0;
- precision = bitsize;
+ static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
if (sizeof (int) == sizeof (HOST_WIDE_INT)
&& neg_p (SIGNED))
More information about the Gcc-patches
mailing list