New wi::bitreverse function.
This patch provides a wide-int implementation of bitreverse, that implements both of Richard Sandiford's suggestions from the review at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/618215.html of an improved API (as a stand-alone function matching the bswap refactoring), and an implementation that works with any bit-width precision. 2023-06-05 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * wide-int.cc (wi::bitreverse_large): New function implementing bit reversal of an integer. * wide-int.h (wi::bitreverse): New (template) function prototype. (bitreverse_large): Prototype helper function/implementation. (wi::bitreverse): New template wrapper around bitreverse_large.
This commit is contained in:
parent
f7f12f0b64
commit
108ff03bac
2 changed files with 42 additions and 0 deletions
|
@ -766,6 +766,33 @@ wi::bswap_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
|
|||
return canonize (val, len, precision);
|
||||
}
|
||||
|
||||
/* Bitreverse the integer represented by XVAL and LEN into VAL. Return
|
||||
the number of blocks in VAL. Both XVAL and VAL have PRECISION bits. */
|
||||
unsigned int
|
||||
wi::bitreverse_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
|
||||
unsigned int len, unsigned int precision)
|
||||
{
|
||||
unsigned int i, s;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
val[i] = 0;
|
||||
|
||||
for (s = 0; s < precision; s++)
|
||||
{
|
||||
unsigned int block = s / HOST_BITS_PER_WIDE_INT;
|
||||
unsigned int offset = s & (HOST_BITS_PER_WIDE_INT - 1);
|
||||
if (((safe_uhwi (xval, len, block) >> offset) & 1) != 0)
|
||||
{
|
||||
unsigned int d = (precision - 1) - s;
|
||||
block = d / HOST_BITS_PER_WIDE_INT;
|
||||
offset = d & (HOST_BITS_PER_WIDE_INT - 1);
|
||||
val[block] |= 1 << offset;
|
||||
}
|
||||
}
|
||||
|
||||
return canonize (val, len, precision);
|
||||
}
|
||||
|
||||
/* Fill VAL with a mask where the lower WIDTH bits are ones and the bits
|
||||
above that up to PREC are zeros. The result is inverted if NEGATE
|
||||
is true. Return the number of blocks in VAL. */
|
||||
|
|
|
@ -553,6 +553,7 @@ namespace wi
|
|||
UNARY_FUNCTION zext (const T &, unsigned int);
|
||||
UNARY_FUNCTION set_bit (const T &, unsigned int);
|
||||
UNARY_FUNCTION bswap (const T &);
|
||||
UNARY_FUNCTION bitreverse (const T &);
|
||||
|
||||
BINARY_FUNCTION min (const T1 &, const T2 &, signop);
|
||||
BINARY_FUNCTION smin (const T1 &, const T2 &);
|
||||
|
@ -1748,6 +1749,8 @@ namespace wi
|
|||
unsigned int, unsigned int, unsigned int);
|
||||
unsigned int bswap_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
|
||||
unsigned int, unsigned int);
|
||||
unsigned int bitreverse_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
|
||||
unsigned int, unsigned int);
|
||||
|
||||
unsigned int lshift_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
|
||||
unsigned int, unsigned int, unsigned int);
|
||||
|
@ -2281,6 +2284,18 @@ wi::bswap (const T &x)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Bitreverse the integer X. */
|
||||
template <typename T>
|
||||
inline WI_UNARY_RESULT (T)
|
||||
wi::bitreverse (const T &x)
|
||||
{
|
||||
WI_UNARY_RESULT_VAR (result, val, T, x);
|
||||
unsigned int precision = get_precision (result);
|
||||
WIDE_INT_REF_FOR (T) xi (x, precision);
|
||||
result.set_len (bitreverse_large (val, xi.val, xi.len, precision));
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return the mininum of X and Y, treating them both as having
|
||||
signedness SGN. */
|
||||
template <typename T1, typename T2>
|
||||
|
|
Loading…
Add table
Reference in a new issue