aboutsummaryrefslogtreecommitdiff
path: root/gcc/wide-int.cc
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2023-06-05 17:28:51 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2023-06-05 17:28:51 +0100
commit108ff03bac3c440db792fcc61d6247e75b56a572 (patch)
tree18a11eec38eb13408461427a1fd7d4dccaf1314c /gcc/wide-int.cc
parentf7f12f0b64646968d722c2d80f149934358a7d71 (diff)
downloadgcc-108ff03bac3c440db792fcc61d6247e75b56a572.zip
gcc-108ff03bac3c440db792fcc61d6247e75b56a572.tar.gz
gcc-108ff03bac3c440db792fcc61d6247e75b56a572.tar.bz2
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.
Diffstat (limited to 'gcc/wide-int.cc')
-rw-r--r--gcc/wide-int.cc27
1 files changed, 27 insertions, 0 deletions
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index 1e4c046..24bdce2 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -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. */