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

Reply via email to