I noticed that there were still a couple of tests for zero precision.
This patch replaces them with asserts when handling separately-supplied
precisions and simply drops them when handling existing wide_ints.
(The idea is that most code would break for zero precision wide_ints
and only asserting in some use sites would be inconsistent.)
Also, to_shwi is called either with a nonzero precision argument or
with no argument. I think it'd be clearer to split the two cases into
separate (overloaded) functions. It's also more efficient, since the
compiler doesn't know that a variable-precision argument must be nonzero.
Tested on x86_64-linux-gnu. OK to install?
Thanks,
Richard
Index: gcc/wide-int.cc
===================================================================
--- gcc/wide-int.cc 2013-12-02 20:03:50.112581766 +0000
+++ gcc/wide-int.cc 2013-12-02 20:12:22.178998274 +0000
@@ -275,9 +275,8 @@ wi::from_mpz (const_tree type, mpz_t x,
wide_int
wi::max_value (unsigned int precision, signop sgn)
{
- if (precision == 0)
- return shwi (0, precision);
- else if (sgn == UNSIGNED)
+ gcc_checking_assert (precision != 0);
+ if (sgn == UNSIGNED)
/* The unsigned max is just all ones. */
return shwi (-1, precision);
else
@@ -290,7 +289,8 @@ wi::max_value (unsigned int precision, s
wide_int
wi::min_value (unsigned int precision, signop sgn)
{
- if (precision == 0 || sgn == UNSIGNED)
+ gcc_checking_assert (precision != 0);
+ if (sgn == UNSIGNED)
return uhwi (0, precision);
else
/* The signed min is all zeros except the top bit. This must be
@@ -1487,9 +1487,6 @@ wi::popcount (const wide_int_ref &x)
unsigned int i;
int count;
- if (x.precision == 0)
- return 0;
-
/* The high order block is special if it is the last block and the
precision is not an even multiple of HOST_BITS_PER_WIDE_INT. We
have to clear out any ones above the precision before doing
@@ -2082,10 +2079,6 @@ wi::ctz (const wide_int_ref &x)
int
wi::exact_log2 (const wide_int_ref &x)
{
- /* 0-precision values can only hold 0. */
- if (x.precision == 0)
- return -1;
-
/* Reject cases where there are implicit -1 blocks above HIGH. */
if (x.len * HOST_BITS_PER_WIDE_INT < x.precision && x.sign_mask () < 0)
return -1;
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h 2013-12-02 19:52:05.424989079 +0000
+++ gcc/wide-int.h 2013-12-02 20:12:22.179998282 +0000
@@ -644,8 +644,10 @@ class GTY(()) generic_wide_int : public
generic_wide_int (const T &, unsigned int);
/* Conversions. */
- HOST_WIDE_INT to_shwi (unsigned int = 0) const;
- unsigned HOST_WIDE_INT to_uhwi (unsigned int = 0) const;
+ HOST_WIDE_INT to_shwi (unsigned int) const;
+ HOST_WIDE_INT to_shwi () const;
+ unsigned HOST_WIDE_INT to_uhwi (unsigned int) const;
+ unsigned HOST_WIDE_INT to_uhwi () const;
HOST_WIDE_INT to_short_addr () const;
/* Public accessors for the interior of a wide int. */
@@ -735,18 +737,23 @@ inline generic_wide_int <storage>::gener
inline HOST_WIDE_INT
generic_wide_int <storage>::to_shwi (unsigned int precision) const
{
- if (precision == 0)
- {
- if (is_sign_extended)
- return this->get_val ()[0];
- precision = this->get_precision ();
- }
if (precision < HOST_BITS_PER_WIDE_INT)
return sext_hwi (this->get_val ()[0], precision);
else
return this->get_val ()[0];
}
+/* Return THIS as a signed HOST_WIDE_INT, in its natural precision. */
+template <typename storage>
+inline HOST_WIDE_INT
+generic_wide_int <storage>::to_shwi () const
+{
+ if (is_sign_extended)
+ return this->get_val ()[0];
+ else
+ return to_shwi (this->get_precision ());
+}
+
/* Return THIS as an unsigned HOST_WIDE_INT, zero-extending from
PRECISION. If THIS does not fit in PRECISION, the information
is lost. */
@@ -754,14 +761,20 @@ generic_wide_int <storage>::to_shwi (uns
inline unsigned HOST_WIDE_INT
generic_wide_int <storage>::to_uhwi (unsigned int precision) const
{
- if (precision == 0)
- precision = this->get_precision ();
if (precision < HOST_BITS_PER_WIDE_INT)
return zext_hwi (this->get_val ()[0], precision);
else
return this->get_val ()[0];
}
+/* Return THIS as an signed HOST_WIDE_INT, in its natural precision. */
+template <typename storage>
+inline unsigned HOST_WIDE_INT
+generic_wide_int <storage>::to_uhwi () const
+{
+ return to_uhwi (this->get_precision ());
+}
+
/* TODO: The compiler is half converted from using HOST_WIDE_INT to
represent addresses to using offset_int to represent addresses.
We use to_short_addr at the interface from new code to old,
@@ -2289,9 +2302,7 @@ wi::add (const T1 &x, const T2 &y, signo
unsigned HOST_WIDE_INT xl = xi.ulow ();
unsigned HOST_WIDE_INT yl = yi.ulow ();
unsigned HOST_WIDE_INT resultl = xl + yl;
- if (precision == 0)
- *overflow = false;
- else if (sgn == SIGNED)
+ if (sgn == SIGNED)
*overflow = (((resultl ^ xl) & (resultl ^ yl))
>> (precision - 1)) & 1;
else
@@ -2364,9 +2375,7 @@ wi::sub (const T1 &x, const T2 &y, signo
unsigned HOST_WIDE_INT xl = xi.ulow ();
unsigned HOST_WIDE_INT yl = yi.ulow ();
unsigned HOST_WIDE_INT resultl = xl - yl;
- if (precision == 0)
- *overflow = false;
- else if (sgn == SIGNED)
+ if (sgn == SIGNED)
*overflow = (((xl ^ yl) & (resultl ^ xl)) >> (precision - 1)) & 1;
else
*overflow = ((resultl << (HOST_BITS_PER_WIDE_INT - precision))