Doh! Wrong patch... Roger --
-----Original Message----- From: Roger Sayle <ro...@nextmovesoftware.com> Sent: Friday, June 2, 2023 3:17 PM To: 'gcc-patches@gcc.gnu.org' <gcc-patches@gcc.gnu.org> Cc: 'Richard Sandiford' <richard.sandif...@arm.com> Subject: [PATCH] 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. This patch has been tested on x86_64-pc-linux-gnu with make bootstrap (and a make check-gcc). Ok for mainline? Are the remaining pieces of the above patch pre-approved (pending re-testing)? The aim is that this new code will be thoroughly tested by the new *-2.c test cases in https://gcc.gnu.org/git/?p=gcc.git;h=c09471fbc7588db2480f036aa56a2403d3c03ae 5 with a minor tweak to use the BITREVERSE rtx in the NVPTX back-end, followed by similar tests on other targets that provide bit-reverse built-ins (such as ARM and xstormy16), in advance of support for a backend-independent solution to PR middle-end/50481. 2023-06-02 Roger Sayle <ro...@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. Thanks again, Roger --
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. */ diff --git a/gcc/wide-int.h b/gcc/wide-int.h index e4723ad..498d14d 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -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>