llvm / llvm-project

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

movd %r8, %mm7 should be illegal #47916

Closed llvmbot closed 3 years ago

llvmbot commented 3 years ago
Bugzilla Link 48572
Resolution INVALID
Resolved on Dec 22, 2020 10:00
Version trunk
OS All
Reporter LLVM Bugzilla Contributor
CC @topperc,@RKSimon,@phoebewang,@rotateright

Extended Description

In x86_64, movd mm0, mm1 gets an invalid operand error. gcc and icc both accept this. The bug happens when there are two mmx register operands for movd. It doesn't happen for movq or with only a single mmx register operand.

https://godbolt.org/z/7GEdrz

topperc commented 3 years ago

From the X86InstrInfo.td

// Match 'movd GR64, MMX' as an alias for movq to be compatible with gas,
// which supports this due to an old AMD documentation bug when 64-bit mode was
// created.
def : InstAlias<"movd\t{$src, $dst|$dst, $src}",
(MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>;
def : InstAlias<"movd\t{$src, $dst|$dst, $src}",
(MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>;

llvmbot commented 3 years ago

I'm reopening this and changing the name summary slightly. I don't know if that is correct or if I should just open another bug.

movd %r8, %mm7 should be illegal. (Correct code would use r8d.) However, instead of syntax erroring, movd is instead silently converted to movq %r8, %mm7

BAD: echo "movd %r8, %mm7" | llvm-mc -show-encoding -assemble -triple x86_64-unknown-unknown

.text
movq    %r8, %mm7                       # encoding: [0x49,0x0f,0x6e,0xf8]

GOOD: echo "movd %r8d, %mm7" | llvm-mc -show-encoding -assemble -triple x86_64-unknown-unknown

.text
movd    %r8d, %mm7                      # encoding: [0x41,0x0f,0x6e,0xf8]

GOOD: echo "movq %r8, %mm7" | llvm-mc -show-encoding -assemble -triple x86_64-unknown-unknown

.text
movq    %r8, %mm7                       # encoding: [0x49,0x0f,0x6e,0xf8]
llvmbot commented 3 years ago

There are TWO sets of MOVQ instructions. This I did not know.

There's "MOVD/MOVQ—Move Doubleword/Move Quadword"

NP REX.W + 0F 6E /r MOVQ mm, r/m64 NP REX.W + 0F 7E /r MOVQ r/m64, mm 66 REX.W 0F 6E /r MOVQ xmm, r/m64 66 REX.W 0F 7E /r MOVQ r/m64, xmm

NP 0F 6E /r MOVD mm, r/m32 NP 0F 7E /r MOVD r/m32, mm 66 0F 6E /r MOVD xmm, r/m32 66 0F 7E /r MOVD r/m32, xmm

and there is also "MOVQ—Move Quadword"

NP 0F 6F /r MOVQ mm, mm/m64 NP 0F 7F /r MOVQ mm/m64, mm F3 0F 7E /r MOVQ xmm1, xmm2/m64

The first does NOT support MOVD mm0, mm1. The second supports MOVQ mm0, mm1.

No bug.

phoebewang commented 3 years ago

AFAIK, ICC also uses GNU assembler by default.

topperc commented 3 years ago

gcc and icc both reject this if you select "compile to binary" in output on godbolt. For gcc its probably because they don't have an integrated assembler and need the GNU assembler to evaluate the assembly text. That's a separate process. I don't know how icc's internals work.