On 05/09/2020 01:33, Rick C. Hodgin wrote:
> -----
> Are there any algorithms which take a known-at-compile-time sequence
> of bitwise operations on an 8-bit to 64-bit quantity, and optimize
> them down to their minimal set of operations?
>
> For example, if I have an 8-bit byte and I want to swizzle the bits
> thusly:
>
> Input: 07 06 05 04 03 02 01 00
> Output: 05 04 07 02 01 03 00 06
If it's just 8-bit bytes, then it's easy: use any method to build a map
that translates one 8-bit value to its swizzled version. I assume it
will be used many millions of times.
> I can easily swizzle the data using a brute force method:
>
> v = get_value();
> o = 0;
> swizzle1(o, v, 0, 6);
> swizzle1(o, v, 1, 0);
> swizzle1(o, v, 2, 3);
> swizzle1(o, v, 3, 1);
> swizzle1(o, v, 4, 2);
> swizzle1(o, v, 5, 7);
> swizzle1(o, v, 6, 4);
> swizzle1(o, v, 7, 5);
>
> // Untested, off the top of my head
> void swizzle(unsigned char& o, unsigned char v, int s, int d)
> {
> o |= (((v & (1 << s)) >> s) << d);
> }
It took me a while to figure out what this means, which appears to be
take bit s of v, and store it as bit d of o. (But o has to start at 0
since |= means it can't change a 1 in o to 0.)
In my language it would be simply this:
o.[d] := v.[s]
although there, it can write both 1s and 0s into o.
> And, of course, that algorithm can be optimized based on relative
> values of s and d, and if s is 0, etc.
>
> However, there also exists a minimal set of steps to complete that
> swizzling because in the operation above, bits 5 and 4 are used in
> sequence. It could be done using a swizzle2() operation, for example
> and handle 2 bits at a time.
>
> Are there any existing algorithms which examine the operations that
> must be conducted and the optimized / minimal sequence of steps to
> conduct it?
The algorithm that works on what, bits of C++ code? What is its input?
What are the aims: to make it fast? Will the mapping always be known
constants, or variables? Will all bits be translated or just some?
And, what would be its output?
If it's just reordering the bits in a word (where you don't map, for
example, both bits 5 and 7 to bit 3), that doesn't sound too hard
(although it probably is!). But importantly, this isn't done in-place.
Up to 8 or 16 bits, probably you can use tables, but the tables need to
be set up.
Otherwise the simplest thing I can think of, for an N-bit word, is a
table of translation pairs. For your 8-bit example this will just be the
parameters to your swizzle function, but as data:
(0,6)
(1,0)
(2,3)
(3,1)
(4,2)
(5,7)
(6,4)
(7,5)
This be input to a routine that will do the job, or it can be the input
to an algorithem that generates, for example, one giant logical expression.
I can probably just about do that last part, if it doesn't need to be
optimised, example:
y = ((x&1)<<6)|((x&2)>>1)|((x&4)<<1)|((x&8)>>2)|
((x&16)>>2)|((x&32)<<2)|((x&64)>>2)|((x&128)>>2);
where x is the input word, and y is the output word. I did this with a
12-line script based on that data input. (Not tested; may need extra
parens.)
I'm sure gcc-O3 will find some optimisations in there if there are any.