This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/64718] New: Bad 16-bit bswap replacement


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64718

            Bug ID: 64718
           Summary: Bad 16-bit bswap replacement
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: aaz@q-fu.com
            Target: i686-pc-linux-gnu

This code is reduced from htons((int)port) on FreeBSD.

The expression gets replaced with a rotation in a 32-bit register
instead of a 16-bit register, so the upper byte is lost.

int swap(int x) {
    return (unsigned short)((unsigned short)x << 8 | (unsigned short)x >> 8);
}

gcc -O2 -S swap.c

swap:
        movl    4(%esp), %eax
        roll    $8, %eax       # should be %ax
        movzwl  %ax, %eax
        ret


Complete program:

#include <stdio.h>

int swap(int x) {
    return (unsigned short)((unsigned short)x << 8 | (unsigned short)x >> 8);
}

int a = 0x1234;
int main() {
    int b = 0x1234;
    printf("%x -> %x\n", a, swap(a));
    printf("%x -> %x\n", b, swap(b));
}

gcc -O2 swap.c && ./a.out

1234 -> 3400
1234 -> 3412


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]