llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.97k stars 11.54k forks source link

i386 ; generates code for target that doesn't support it (cmovne) #59061

Open 0xDRRB opened 1 year ago

0xDRRB commented 1 year ago

CPU target: i586, Clang -O2 generates code that is not supported and program crash with illegal instruction. Illegal instruction is: cmovne

Tested on AMD64 with -mcpu and on physical box, both running FreeBSD 13.1.

CPU: Pentium/P55C (233.87-MHz 586-class CPU)
Origin="GenuineIntel" Id=0x543 Family=0x5 Model=0x4 Stepping=3
Features=0x8001bf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,MMX>

This bug was detected with this project: https://gitlab.com/0xDRRB/st25.

$ clang -mcpu=pentium-mmx -Wall main.c -o st25taread  `pkg-config --cflags --libs libnfc`
$ objdump --disassemble st25taread | grep cmovne
[nothing]

$ clang -mcpu=pentium-mmx -Wall -O2 main.c -o st25taread  `pkg-config --cflags --libs libnfc`
$ objdump --disassemble st25taread | grep cmovne
  20403f:       48 0f 45 f2             cmovne %rdx,%rsi
  2040b9:       48 0f 45 f1             cmovne %rcx,%rsi
  20503e:       0f 45 c1                cmovne %ecx,%eax

On i586 box:

$ clang -Wall -O2 main.c -o st25taread `pkg-config --cflags --libs libnfc`
$ sudo ./st25taread -i
Password:
NFC reader: pn532_uart:/dev/ttyU0 opened
ISO/IEC 14443A (106 kbps) tag found. UID: 02C4004E3771A4
ST System file
  Len:                      18
  UID:                      02C4004E3771A4
  Memory Size (-1):         8191
  Product:                  ST25TA64K (0xC4)
  Number of NDEF file:      1
Illegal instruction (core dumped)

$ clang -c -Wall -O2 main.c -o main.o `pkg-config --cflags libnfc`
$ objdump --disassemble main.o | grep cmovne
     6c5:       0f 45 c2                cmovne %edx,%eax
     744:       0f 45 ca                cmovne %edx,%ecx
    1662:       0f 45 c1                cmovne %ecx,%eax

$ clang -S -Wall -O2 main.c `pkg-config --cflags libnfc`
$ grep cmovne main.s
        cmovnel %edx, %eax
        cmovnel %edx, %ecx
        cmovnel %ecx, %eax
llvmbot commented 1 year ago

@llvm/issue-subscribers-backend-x86

RKSimon commented 1 year ago

I'll take a look at this

topperc commented 1 year ago

The first set is particularly strange because some of those are 64-bit instructions. I thought we rejected 32-bit -mcpu on 64-bit targets

topperc commented 1 year ago

But then again -mcpu isn't a valid x86 option. It's -march for X86

RKSimon commented 1 year ago

I tried with: clang -c -S -m32 -march=pentium-mmx and the output contained no cmoves But changing to clang -c -S -m32 -march=pentium4 did contain cmoves

@0xDRRB Please can you try with -march=pentium-mmx (or -march=native)?

0xDRRB commented 1 year ago

Here it is:

$ clang -march=native -S -Wall main.c  `pkg-config --cflags libnfc`
$ grep cmovne main.s
[nothing]

Same with -O2 :

$ clang -march=native -O2 -S -Wall main.c  `pkg-config --cflags libnfc`
$ grep cmovne main.s
[nothing]

If i drop the -march:

$ clang -O2 -S -Wall main.c  `pkg-config --cflags libnfc`
$ grep cmovne main.s 
        cmovnel %edx, %eax
        cmovnel %edx, %ecx
        cmovnel %ecx, %eax

All of this is on the Pentium MMX box.

RKSimon commented 1 year ago

So the problem appears to be that the default 32-bit CPU has CMOV enabled (and maybe other x86-64 default settings, SSE2 etc.) - but I thought this was true for gcc as well?

iucoen commented 9 months ago

So the problem appears to be that the default 32-bit CPU has CMOV enabled (and maybe other x86-64 default settings, SSE2 etc.) - but I thought this was true for gcc as well?

This is because clang defaults to pentium4 when no -march flags are specified for i386. https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Arch/X86.cpp#L115