[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
This commit is contained in:
Reid Kleckner 2017-05-04 18:19:52 +00:00
parent 142cb83768
commit 6d2ea6ec80
9 changed files with 255 additions and 155 deletions

View File

@ -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

View File

@ -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* %{{.*}})
}

View File

@ -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
}

View File

@ -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]] = {

View File

@ -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();

View File

@ -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
}

View File

@ -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

View File

@ -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;

View File

@ -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 }