diff options
-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 } |