Issue 141863
Summary Bad codegen for reversing bits in bytes without swapping bytes
Labels new issue
Assignees
Reporter tom-rein
    The following code on RISC-V target with Zbkb extension ([godbolt](https://godbolt.org/z/cTqEYsbaz)):
```C++
#include <cstdint>
uint8_t brev8(uint8_t x) {
    return __builtin_bitreverse8(x);
}
```
Results in:
```
brev8(unsigned char):
 rev8    a0, a0
        brev8   a0, a0
        srli    a0, a0, 56
 ret
```
The expected result would be just `brev8 a0, a0` since it doesn't swap bytes.

On armv8 target (and similarly on armv7) bit reversing bytes in `uint16_t` uses `rev16` which results in an extra shift:
```C++
uint16_t brev8(uint16_t x) {
    return __builtin_bswap16(__builtin_bitreverse16(x));
}
```
```
brev8(unsigned short):
        rbit    w8, w0
        lsr     w8, w8, #16
        rev16 w0, w8
        ret
```
This could instead be:
```
brev8(unsigned short):
        rbit    w0, w0
        rev     w0, w0
 ret
```
(Also the register allocation somehow uses w8 instead of reusing w0, which I find weird, since that is done on other targets, including armv7)

When doing `bswap16` first and then `bitreverse16`, it doesn't even use `rev16`, but adds two shifts:
```C++
uint16_t brev8_2(uint16_t x) {
 return __builtin_bitreverse16(__builtin_bswap16(x));
}
```
```
brev8_2(unsigned short):
        rev     w8, w0
        lsr     w8, w8, #16
        rbit w8, w8
        lsr     w0, w8, #16
        ret
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to