https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115102
Bug ID: 115102
Summary: [SH] GCC misunderstands swap.b instruction
Product: gcc
Version: 14.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: paul at crapouillou dot net
Target Milestone: ---
Given the following C code:
#include <stdint.h>
uint32_t bswap8(uint32_t val) {
return (val & 0xffff0000) | ((val & 0xff00) >> 8) | ((val & 0xff) << 8);
}
GCC will generate (-m4 -Os):
_bswap8:
mov.l .L2,r1
extu.w r4,r0
swap.b r0,r0
and r1,r4
rts
or r4,r0
.L2:
.long -65536
GCC understand that it can swap the two lower bytes using the swap.b
instruction. However, it seems to believe that it needs to clear up the upper
16 bits first, which is wrong, as those are simply copied over to the
destination register.
As a result, it will zero-extend to 16 bits first, swap the two low bytes, then
apply a high 16-bit mask to the original value, and OR the two results
together.
This is not optimal, and GCC could simply generate the following:
_bswap8:
rts
swap.b r4,r0