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))