diff options
| author | Reid Kleckner <rnk@google.com> | 2017-05-04 18:19:52 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2017-05-04 18:19:52 +0000 |
| commit | 6d2ea6ec809d7c648c7b31ae195753b5507e7169 (patch) | |
| tree | 7fb28c065501b35cd7d0baa425b0e0aa9baa8c1c | |
| parent | 142cb83768ffd781a1edb21c072120fc34dc7fa0 (diff) | |
| download | bcm5719-llvm-6d2ea6ec809d7c648c7b31ae195753b5507e7169.tar.gz bcm5719-llvm-6d2ea6ec809d7c648c7b31ae195753b5507e7169.zip | |
[ms-inline-asm] Use the frontend size only for ambiguous instructions
This avoids problems on code like this:
char buf[16];
__asm {
movups xmm0, [buf]
mov [buf], eax
}
The frontend size in this case (1) is wrong, and the register makes the
instruction matching unambiguous. There are also enough bytes available
that we shouldn't complain to the user that they are potentially using
an incorrectly sized instruction to access the variable.
Supersedes D32636 and D26586 and fixes PR28266
llvm-svn: 302179
| -rw-r--r-- | clang/test/CodeGen/mozilla-ms-inline-asm.c | 38 | ||||
| -rw-r--r-- | clang/test/CodeGen/ms-inline-asm-64.c | 20 | ||||
| -rw-r--r-- | clang/test/CodeGen/ms-inline-asm-avx512.c | 15 | ||||
| -rw-r--r-- | clang/test/CodeGen/ms-inline-asm.c | 139 | ||||
| -rw-r--r-- | clang/test/CodeGen/ms-inline-asm.cpp | 65 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ms-inline-asm-fields.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 94 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86Operand.h | 11 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/ms-inline-asm-avx512.ll | 24 |
9 files changed, 255 insertions, 155 deletions
diff --git a/clang/test/CodeGen/mozilla-ms-inline-asm.c b/clang/test/CodeGen/mozilla-ms-inline-asm.c index 3335a87fefe..26e8ebce1e2 100644 --- a/clang/test/CodeGen/mozilla-ms-inline-asm.c +++ b/clang/test/CodeGen/mozilla-ms-inline-asm.c @@ -18,25 +18,25 @@ void invoke(void* that, unsigned methodIndex, // CHECK: store i32 %2, i32* %7, align 4 // CHECK: store i8* %3, i8** %8, align 4 // CHECK: call void asm sideeffect inteldialect -// CHECK: mov edx,dword ptr $1 -// CHECK: test edx,edx -// CHECK: jz {{[^_]*}}__MSASMLABEL_.${:uid}__noparams -// ^ Can't use {{.*}} here because the matching is greedy. -// CHECK: mov eax,edx -// CHECK: shl eax,$$3 -// CHECK: sub esp,eax -// CHECK: mov ecx,esp -// CHECK: push dword ptr $0 -// CHECK: call dword ptr $2 -// CHECK: {{.*}}__MSASMLABEL_.${:uid}__noparams: -// CHECK: mov ecx,dword ptr $3 -// CHECK: push ecx -// CHECK: mov edx,[ecx] -// CHECK: mov eax,dword ptr $4 -// CHECK: call dword ptr[edx+eax*$$4] -// CHECK: mov esp,ebp -// CHECK: pop ebp -// CHECK: ret +// CHECK-SAME: mov edx,$1 +// CHECK-SAME: test edx,edx +// CHECK-SAME: jz {{[^_]*}}__MSASMLABEL_.${:uid}__noparams +// ^ Can't use {{.*}} here because the matching is greedy. +// CHECK-SAME: mov eax,edx +// CHECK-SAME: shl eax,$$3 +// CHECK-SAME: sub esp,eax +// CHECK-SAME: mov ecx,esp +// CHECK-SAME: push $0 +// CHECK-SAME: call dword ptr $2 +// CHECK-SAME: {{.*}}__MSASMLABEL_.${:uid}__noparams: +// CHECK-SAME: mov ecx,$3 +// CHECK-SAME: push ecx +// CHECK-SAME: mov edx,[ecx] +// CHECK-SAME: mov eax,$4 +// CHECK-SAME: call dword ptr[edx+eax*$$4] +// CHECK-SAME: mov esp,ebp +// CHECK-SAME: pop ebp +// CHECK-SAME: ret // CHECK: "=*m,*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}" // CHECK: (i8** %8, i32* %7, void (...)* bitcast (void ()* @invoke_copy_to_stack to void (...)*), i8** %5, i32* %6) // CHECK: ret void diff --git a/clang/test/CodeGen/ms-inline-asm-64.c b/clang/test/CodeGen/ms-inline-asm-64.c index d6f6e2ee0e0..69828feb362 100644 --- a/clang/test/CodeGen/ms-inline-asm-64.c +++ b/clang/test/CodeGen/ms-inline-asm-64.c @@ -5,14 +5,18 @@ void t1() { int var = 10; __asm mov rax, offset var ; rax = address of myvar // CHECK: t1 -// CHECK: call void asm sideeffect inteldialect "mov rax, $0", "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov rax, $0 +// CHECK-SAME: "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } void t2() { int var = 10; __asm mov [eax], offset var // CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov [eax], $0 +// CHECK-SAME: "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } struct t3_type { int a, b; }; @@ -28,7 +32,11 @@ int t3() { } return foo.b; // CHECK: t3 -// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr $0\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: lea ebx, $0 +// CHECK-SAME: mov eax, [ebx].0 +// CHECK-SAME: mov [ebx].4, ecx +// CHECK-SAME: "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) } int t4() { @@ -44,5 +52,9 @@ int t4() { } return foo.b; // CHECK: t4 -// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr $0\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: lea ebx, $0 +// CHECK-SAME: mov eax, [ebx].0 +// CHECK-SAME: mov [ebx].4, ecx +// CHECK-SAME: "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}}) } diff --git a/clang/test/CodeGen/ms-inline-asm-avx512.c b/clang/test/CodeGen/ms-inline-asm-avx512.c index c1b783a2107..6189e50d211 100644 --- a/clang/test/CodeGen/ms-inline-asm-avx512.c +++ b/clang/test/CodeGen/ms-inline-asm-avx512.c @@ -1,5 +1,5 @@ // REQUIRES: x86-registered-target -// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -target-cpu knl -fasm-blocks -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-pc-windows-msvc -target-cpu skylake-avx512 -fasm-blocks -emit-llvm -o - | FileCheck %s void t1() { // CHECK: @t1 @@ -19,3 +19,16 @@ void t2() { vaddpd zmm8 {k1}, zmm27, zmm6 } } + +void ignore_fe_size() { + // CHECK-LABEL: define void @ignore_fe_size() + char c; + // CHECK: vaddps xmm1, xmm2, $1{1to4} + __asm vaddps xmm1, xmm2, [c]{1to4} + // CHECK: vaddps xmm1, xmm2, $2 + __asm vaddps xmm1, xmm2, [c] + // CHECK: mov eax, $3 + __asm mov eax, [c] + // CHECK: mov $0, rax + __asm mov [c], rax +} diff --git a/clang/test/CodeGen/ms-inline-asm.c b/clang/test/CodeGen/ms-inline-asm.c index c4fe08a3e13..5182d7f2e81 100644 --- a/clang/test/CodeGen/ms-inline-asm.c +++ b/clang/test/CodeGen/ms-inline-asm.c @@ -92,7 +92,11 @@ void t9() { __asm { pop ebx } } // CHECK: t9 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx\0A\09", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, $$0x07 +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } unsigned t10(void) { @@ -107,7 +111,10 @@ unsigned t10(void) { // CHECK: [[I:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: [[J:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: store i32 1, i32* [[I]], align 4 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $2\0A\09mov dword ptr $0, eax", "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect +// CHECK-SAME: mov eax, $2 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) // CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32, i32* [[J]], align 4 // CHECK: ret i32 [[RET]] } @@ -128,7 +135,12 @@ unsigned t12(void) { } return j + m; // CHECK: t12 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $3\0A\09mov dword ptr $0, eax\0A\09mov eax, dword ptr $4\0A\09mov dword ptr $1, eax", "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect +// CHECK-SAME: mov eax, $3 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: mov eax, $4 +// CHECK-SAME: mov $1, eax +// CHECK-SAME: "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t13() { @@ -136,8 +148,23 @@ void t13() { short j = 2; __asm movzx eax, i __asm movzx eax, j -// CHECK: t13 -// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0\0A\09movzx eax, word ptr $1", "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) +// CHECK-LABEL: define void @t13() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: movzx eax, byte ptr $0 +// CHECK-SAME: movzx eax, word ptr $1 +// CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) +} + +void t13_brac() { + char i = 1; + short j = 2; + __asm movzx eax, [i] + __asm movzx eax, [j] +// CHECK-LABEL: define void @t13_brac() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: movzx eax, byte ptr $0 +// CHECK-SAME: movzx eax, word ptr $1 +// CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) } void t14() { @@ -150,7 +177,7 @@ void t14() { .endif } // CHECK: t14 -// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, dword ptr $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } int gvar = 10; @@ -158,7 +185,7 @@ void t15() { // CHECK: t15 int lvar = 10; __asm mov eax, lvar ; eax = 10 -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, offset lvar ; eax = address of lvar // CHECK: mov eax, $1 __asm mov eax, offset gvar ; eax = address of gvar @@ -236,7 +263,11 @@ void t21() { __asm pop ebx } // CHECK: t21 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$07H\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, $$07H +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } extern void t22_helper(int x); @@ -252,9 +283,15 @@ void t22() { __asm pop ebx } // CHECK: t22 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, esp", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: push ebx +// CHECK-SAME: mov ebx, esp +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() // CHECK: call void @t22_helper -// CHECK: call void asm sideeffect inteldialect "mov esp, ebx\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov esp, ebx +// CHECK-SAME: pop ebx +// CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() } void t23() { @@ -342,9 +379,9 @@ int *t30() { int *res; __asm lea edi, results -// CHECK: lea edi, dword ptr $2 +// CHECK: lea edi, $2 __asm mov res, edi -// CHECK: mov dword ptr $0, edi +// CHECK: mov $0, edi return res; // CHECK: "=*m,={eax},*m,~{edi},~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}, [2 x i32]* @{{.*}}) } @@ -362,7 +399,7 @@ void t32() { // CHECK: t32 int i; __asm mov eax, i -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, dword ptr i // CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr i @@ -376,7 +413,7 @@ void t33() { // CHECK: t33 int i; __asm mov eax, [i] -// CHECK: mov eax, dword ptr $0 +// CHECK: mov eax, $0 __asm mov eax, dword ptr [i] // CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr [i] @@ -409,31 +446,31 @@ void t36() { int arr[4]; // Work around PR20368: These should be single line blocks __asm { mov eax, 4[arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 8[arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 12[4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4[64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, [64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } void t37() { @@ -464,21 +501,21 @@ void t38() { int arr[4]; // Work around PR20368: These should be single line blocks __asm { mov eax, 4+4[arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, (4+4)[arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 8*2[arr + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 12+20[4 + arr] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*16+4[4 + arr + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*4[64 + arr + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 4*(4-2)[64 + arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) __asm { mov eax, 32*(4-2)[arr - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } void cpuid() { @@ -554,7 +591,7 @@ void t42() { // CHECK-LABEL: define void @t42 int flags; __asm mov flags, eax -// CHECK: mov dword ptr $0, eax +// CHECK: mov $0, eax // CHECK: "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %flags) } @@ -563,31 +600,31 @@ void t43() { C strct; // Work around PR20368: These should be single line blocks __asm { mov eax, 4[strct.c1] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[strct.c3 + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 8[strct.c2.a + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 12[4 + strct.c2.b] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[4 + strct.c4.b2.b + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[64 + strct.c1 + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, 4[64 + strct.c2.a - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [strct.c4.b1 + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [strct.c4.b2.a + 4 + 32*2 - 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [4 + strct.c1] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [4 + strct.c2.b + 4] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [64 + strct.c3 + (2*32)] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) __asm { mov eax, [64 + strct.c4.b2.b - 2*32] } -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } void call_clobber() { @@ -662,7 +699,7 @@ void mxcsr() { __asm fxrstor buf } // CHECK-LABEL: define void @mxcsr -// CHECK: call void asm sideeffect inteldialect "fxrstor byte ptr $0", "=*m,~{dirflag},~{fpsr},~{flags}" +// CHECK: call void asm sideeffect inteldialect "fxrstor $0", "=*m,~{dirflag},~{fpsr},~{flags}" typedef union _LARGE_INTEGER { struct { @@ -680,7 +717,7 @@ int test_indirect_field(LARGE_INTEGER LargeInteger) { __asm mov eax, LargeInteger.LowPart } // CHECK-LABEL: define i32 @test_indirect_field( -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", // MS ASM containing labels must not be duplicated (PR23715). // CHECK: attributes [[ATTR1]] = { diff --git a/clang/test/CodeGen/ms-inline-asm.cpp b/clang/test/CodeGen/ms-inline-asm.cpp index 424c1992cc2..a435e4b826d 100644 --- a/clang/test/CodeGen/ms-inline-asm.cpp +++ b/clang/test/CodeGen/ms-inline-asm.cpp @@ -14,15 +14,21 @@ struct Foo { }; void t1() { +// CHECK-LABEL: define void @_Z2t1v() Foo::ptr = (int *)0xDEADBEEF; Foo::Bar::ptr = (int *)0xDEADBEEF; +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $0 +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: mov eax, $2 +// CHECK-SAME: mov eax, dword ptr $3 +// CHECK-SAME: mov eax, dword ptr $4 +// CHECK-SAME: "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE) __asm mov eax, Foo ::ptr __asm mov eax, Foo :: Bar :: ptr __asm mov eax, [Foo:: ptr] __asm mov eax, dword ptr [Foo :: ptr] __asm mov eax, dword ptr [Foo :: ptr] -// CHECK: @_Z2t1v -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0\0A\09mov eax, dword ptr $1\0A\09mov eax, dword ptr $2\0A\09mov eax, dword ptr $3\0A\09mov eax, dword ptr $4", "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE) } int gvar = 10; @@ -30,8 +36,11 @@ void t2() { int lvar = 10; __asm mov eax, offset Foo::ptr __asm mov eax, offset Foo::Bar::ptr -// CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov eax, $0\0A\09mov eax, $1", "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE) +// CHECK-LABEL: define void @_Z2t2v() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $0 +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE) } // CHECK-LABEL: define void @_Z2t3v() @@ -50,7 +59,20 @@ void t3() { __asm mov eax, SIZE Foo::Bar::ptr __asm mov eax, SIZE Foo::arr __asm mov eax, SIZE Foo::Bar::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$2\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$16\0A\09mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$2 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$1 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$4 +// CHECK-SAME: mov eax, $$16 +// CHECK-SAME: mov eax, $$2 +// CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } @@ -67,7 +89,10 @@ void T4::test() { // CHECK: [[X:%.*]] = getelementptr inbounds [[T4]], [[T4]]* [[THIS]], i32 0, i32 0 __asm mov eax, x; __asm mov y, eax; -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}}) +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: mov eax, $1 +// CHECK-SAME: mov $0, eax +// CHECK-SAME: "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}}) } template <class T> struct T5 { @@ -82,7 +107,11 @@ void test5() { __asm push y __asm call T5<int>::create<float> __asm mov x, eax - // CHECK: call void asm sideeffect inteldialect "push dword ptr $0\0A\09call dword ptr $2\0A\09mov dword ptr $1, eax", "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_) + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: push $0 + // CHECK-SAME: call dword ptr $2 + // CHECK-SAME: mov $1, eax + // CHECK-SAME: "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_) } // Just verify this doesn't emit an error. @@ -100,7 +129,9 @@ void t7_struct() { }; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z9t7_structv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t7_typedef() { @@ -110,7 +141,9 @@ void t7_typedef() { } A; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z10t7_typedefv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t7_using() { @@ -120,20 +153,28 @@ void t7_using() { }; __asm mov eax, [eax].A.b // CHECK-LABEL: define void @_Z8t7_usingv - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: mov eax, [eax].4 + // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t8() { __asm some_label: // CHECK-LABEL: define void @_Z2t8v() - // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.${:uid}__some_label:", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label: + // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"() struct A { static void g() { __asm jmp some_label ; This should jump forwards __asm some_label: __asm nop // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv() - // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.${:uid}__some_label\0A\09L__MSASMLABEL_.${:uid}__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect + // CHECK-SAME: jmp L__MSASMLABEL_.${:uid}__some_label + // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label: + // CHECK-SAME: nop + // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"() } }; A::g(); diff --git a/clang/test/CodeGenCXX/ms-inline-asm-fields.cpp b/clang/test/CodeGenCXX/ms-inline-asm-fields.cpp index 6f329330bda..5ee6acf5746 100644 --- a/clang/test/CodeGenCXX/ms-inline-asm-fields.cpp +++ b/clang/test/CodeGenCXX/ms-inline-asm-fields.cpp @@ -17,14 +17,14 @@ A a_global; extern "C" int test_param_field(A p) { // CHECK: define i32 @test_param_field(%struct.A* byval align 4 %p) // CHECK: getelementptr inbounds %struct.A, %struct.A* %p, i32 0, i32 0 -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1" +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1" // CHECK: ret i32 __asm mov eax, p.a1 } extern "C" int test_namespace_global() { // CHECK: define i32 @test_namespace_global() -// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) +// CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) // CHECK: ret i32 __asm mov eax, asdf::a_global.a3.b2 } diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index c1cfc82b4a8..32ab475f118 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -776,11 +776,6 @@ private: bool ParseZ(std::unique_ptr<X86Operand> &Z, const SMLoc &StartLoc); - /// MS-compatibility: - /// Obtain an appropriate size qualifier, when facing its absence, - /// upon AVX512 vector/broadcast memory operand - unsigned AdjustAVX512Mem(unsigned Size, X86Operand* UnsizedMemOpNext); - bool is64BitMode() const { // FIXME: Can tablegen auto-generate this? return getSTI().getFeatureBits()[X86::Mode64Bit]; @@ -1206,27 +1201,16 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm( Identifier, Info.OpDecl); } + // We either have a direct symbol reference, or an offset from a symbol. The // parser always puts the symbol on the LHS, so look there for size // calculation purposes. + unsigned FrontendSize = 0; const MCBinaryExpr *BinOp = dyn_cast<MCBinaryExpr>(Disp); bool IsSymRef = isa<MCSymbolRefExpr>(BinOp ? BinOp->getLHS() : Disp); - if (IsSymRef) { - if (!Size) { - Size = Info.Type * 8; // Size is in terms of bits in this context. - if (Size) - InstInfo->AsmRewrites->emplace_back(AOK_SizeDirective, Start, - /*Len=*/0, Size); - if (AllowBetterSizeMatch) - // Handle cases where size qualifier is absent, upon an indirect symbol - // reference - e.g. "vaddps zmm1, zmm2, [var]" - // set Size to zero to allow matching mechansim to try and find a better - // size qualifier than our initial guess, based on available variants of - // the given instruction - Size = 0; - } - } + if (IsSymRef && !Size && Info.Type) + FrontendSize = Info.Type * 8; // Size is in terms of bits in this context. // When parsing inline assembly we set the base register to a non-zero value // if we don't know the actual value at this time. This is necessary to @@ -1234,7 +1218,7 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm( BaseReg = BaseReg ? BaseReg : 1; return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End, Size, Identifier, - Info.OpDecl); + Info.OpDecl, FrontendSize); } static void @@ -2884,23 +2868,6 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, return true; } -unsigned X86AsmParser::AdjustAVX512Mem(unsigned Size, - X86Operand* UnsizedMemOpNext) { - // Check for the existence of an AVX512 platform - if (!getSTI().getFeatureBits()[X86::FeatureAVX512]) - return 0; - // Allow adjusting upon a (x|y|z)mm - if (Size == 512 || Size == 256 || Size == 128) - return Size; - // This is an allegadly broadcasting mem op adjustment, - // allow some more inquiring to validate it - if (Size == 64 || Size == 32) - return UnsizedMemOpNext && UnsizedMemOpNext->isToken() && - UnsizedMemOpNext->getToken().substr(0, 4).equals("{1to") ? Size : 0; - // Do not allow any other type of adjustments - return 0; -} - bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -2920,19 +2887,14 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, // Find one unsized memory operand, if present. X86Operand *UnsizedMemOp = nullptr; - // If unsized memory operand was found - obtain following operand. - // For use in AdjustAVX512Mem - X86Operand *UnsizedMemOpNext = nullptr; for (const auto &Op : Operands) { X86Operand *X86Op = static_cast<X86Operand *>(Op.get()); - if (UnsizedMemOp) { - UnsizedMemOpNext = X86Op; + if (X86Op->isMemUnsized()) { + UnsizedMemOp = X86Op; // Have we found an unqualified memory operand, // break. IA allows only one memory operand. break; } - if (X86Op->isMemUnsized()) - UnsizedMemOp = X86Op; } // Allow some instructions to have implicitly pointer-sized operands. This is @@ -2978,7 +2940,6 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, // If an unsized memory operand is present, try to match with each memory // operand size. In Intel assembly, the size is not part of the instruction // mnemonic. - unsigned MatchedSize = 0; if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; for (unsigned Size : MopSizes) { @@ -2993,17 +2954,10 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; - if (M == Match_Success) - // MS-compatability: - // Adjust AVX512 vector/broadcast memory operand, - // when facing the absence of a size qualifier. - // Match GCC behavior on respective cases. - MatchedSize = AdjustAVX512Mem(Size, UnsizedMemOpNext); } // Restore the size of the unsized memory operand if we modified it. - if (UnsizedMemOp) - UnsizedMemOp->Mem.Size = 0; + UnsizedMemOp->Mem.Size = 0; } // If we haven't matched anything yet, this is not a basic integer or FPU @@ -3027,20 +2981,30 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, Op.getLocRange(), MatchingInlineAsm); } + unsigned NumSuccessfulMatches = + std::count(std::begin(Match), std::end(Match), Match_Success); + + // If matching was ambiguous and we had size information from the frontend, + // try again with that. This handles cases like "movxz eax, m8/m16". + if (UnsizedMemOp && NumSuccessfulMatches > 1 && + UnsizedMemOp->getMemFrontendSize()) { + UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize(); + unsigned M = MatchInstruction( + Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax()); + if (M == Match_Success) + NumSuccessfulMatches = 1; + + // Add a rewrite that encodes the size information we used from the + // frontend. + InstInfo->AsmRewrites->emplace_back( + AOK_SizeDirective, UnsizedMemOp->getStartLoc(), + /*Len=*/0, UnsizedMemOp->getMemFrontendSize()); + } + // If exactly one matched, then we treat that as a successful match (and the // instruction will already have been filled in correctly, since the failing // matches won't have modified it). - unsigned NumSuccessfulMatches = - std::count(std::begin(Match), std::end(Match), Match_Success); if (NumSuccessfulMatches == 1) { - if (MatchedSize && isParsingInlineAsm() && isParsingIntelSyntax()) - // MS compatibility - - // Fix the rewrite according to the matched memory size - // MS inline assembly only - for (AsmRewrite &AR : *InstInfo->AsmRewrites) - if ((AR.Loc.getPointer() == UnsizedMemOp->StartLoc.getPointer()) && - (AR.Kind == AOK_SizeDirective)) - AR.Val = MatchedSize; // Some instructions need post-processing to, for example, tweak which // encoding is selected. Loop on it while changes happen so the individual // transformations can chain off each other. @@ -3057,7 +3021,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, "multiple matches only possible with unsized memory operands"); return Error(UnsizedMemOp->getStartLoc(), "ambiguous operand size for instruction '" + Mnemonic + "\'", - UnsizedMemOp->getLocRange(), MatchingInlineAsm); + UnsizedMemOp->getLocRange()); } // If one instruction matched with a missing feature, report this as a diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h index 9f1fa6c6590..52e82f0f38e 100644 --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -62,6 +62,10 @@ struct X86Operand : public MCParsedAsmOperand { unsigned Scale; unsigned Size; unsigned ModeSize; + + /// If the memory operand is unsized and there are multiple instruction + /// matches, prefer the one with this size. + unsigned FrontendSize; }; union { @@ -136,6 +140,10 @@ struct X86Operand : public MCParsedAsmOperand { assert(Kind == Memory && "Invalid access!"); return Mem.ModeSize; } + unsigned getMemFrontendSize() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.FrontendSize; + } bool isToken() const override {return Kind == Token; } @@ -532,7 +540,7 @@ struct X86Operand : public MCParsedAsmOperand { CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), - void *OpDecl = nullptr) { + void *OpDecl = nullptr, unsigned FrontendSize = 0) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); @@ -548,6 +556,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.Scale = Scale; Res->Mem.Size = Size; Res->Mem.ModeSize = ModeSize; + Res->Mem.FrontendSize = FrontendSize; Res->SymName = SymName; Res->OpDecl = OpDecl; Res->AddressOf = false; diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-avx512.ll b/llvm/test/CodeGen/X86/ms-inline-asm-avx512.ll new file mode 100644 index 00000000000..be60f5bca16 --- /dev/null +++ b/llvm/test/CodeGen/X86/ms-inline-asm-avx512.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s | FileCheck %s + +; Generated from clang/test/CodeGen/ms-inline-asm-avx512.c + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +; Function Attrs: noinline nounwind +define void @ignore_fe_size() #0 { +entry: + %c = alloca i8, align 1 + call void asm sideeffect inteldialect "vaddps xmm1, xmm2, $1{1to4}\0A\09vaddps xmm1, xmm2, $2\0A\09mov eax, $3\0A\09mov $0, rax", "=*m,*m,*m,*m,~{eax},~{xmm1},~{dirflag},~{fpsr},~{flags}"(i8* %c, i8* %c, i8* %c, i8* %c) #1 + ret void +} + +; CHECK-LABEL: ignore_fe_size: +; CHECK: vaddps 7(%rsp){1to4}, %xmm2, %xmm1 +; CHECK: vaddps 7(%rsp), %xmm2, %xmm1 +; CHECK: movl 7(%rsp), %eax +; CHECK: movq %rax, 7(%rsp) +; CHECK: retq + +attributes #0 = { noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="skylake-avx512" "target-features"="+adx,+aes,+avx,+avx2,+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512vl,+bmi,+bmi2,+clflushopt,+clwb,+cx16,+f16c,+fma,+fsgsbase,+fxsr,+lzcnt,+mmx,+movbe,+mpx,+pclmul,+pku,+popcnt,+rdrnd,+rdseed,+rtm,+sgx,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind } |

