Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解决windows调用保留约定的xmm寄存器的问题?_Windows_Assembly_Sse_Calling Convention_Abi - Fatal编程技术网

解决windows调用保留约定的xmm寄存器的问题?

解决windows调用保留约定的xmm寄存器的问题?,windows,assembly,sse,calling-convention,abi,Windows,Assembly,Sse,Calling Convention,Abi,在Windows上有没有办法解决XMM寄存器保留在函数调用中的要求?(除了在汇编中编写之外) 我有很多AVX2的内在函数,不幸的是,这些函数都被这个函数膨胀了 例如,编译器(MSVC)将其置于函数顶部: 00007FF9D0EBC602 vmovaps xmmword ptr[rsp+1490h],xmm6 00007FF9D0EBC60B vmovaps xmmword ptr[rsp+1480h],xmm7 00007FF9D0EBC614 vmovaps xmmword ptr[rsp+1

在Windows上有没有办法解决XMM寄存器保留在函数调用中的要求?(除了在汇编中编写之外)

我有很多AVX2的内在函数,不幸的是,这些函数都被这个函数膨胀了

例如,编译器(MSVC)将其置于函数顶部:

00007FF9D0EBC602 vmovaps xmmword ptr[rsp+1490h],xmm6
00007FF9D0EBC60B vmovaps xmmword ptr[rsp+1480h],xmm7
00007FF9D0EBC614 vmovaps xmmword ptr[rsp+1470h],xmm8
00007FF9D0EBC61D vmovaps xmmword ptr[rsp+1460h],xmm9
00007FF9D0EBC626 vmovaps xmmword ptr[rsp+1450h],xmm10
00007FF9D0EBC62F vmovaps xmmword ptr[rsp+1440h],xmm11
00007FF9D0EBC638 vmovaps xmmword ptr[rsp+1430h],xmm12
00007FF9D0EBC641 vmovaps xmmword ptr[rsp+1420h],xmm13
00007FF9D0EBC64A vmovaps xmmword ptr[rsp+1410h],xmm14
00007FF9D0EBC653 vmovaps xmmword ptr[rsp+1400h],xmm15

然后在函数的末尾

00007FF9D0EBD6E6 vmovaps xmm6,xmmword ptr[r11-10h]
00007FF9D0EBD6EC vmovaps xmm7,xmmword ptr[r11-20h]
00007FF9D0EBD6F2 vmovaps xmm8,xmmword ptr[r11-30h]
00007FF9D0EBD6F8 vmovaps xmm9,xmmword ptr[r11-40h]
00007FF9D0EBD6FE vmovaps xmm10,xmmword ptr[r11-50h]
00007FF9D0EBD704 vmovaps xmm11,xmmword ptr[r11-60h]
00007FF9D0EBD70A vmovaps xmm12,xmmword ptr[r11-70h]
00007FF9D0EBD710 vmovaps xmm13,xmmword ptr[r11-80h]
00007FF9D0EBD716 vmovaps xmm14,xmmword ptr[r11-90h]
00007FF9D0EBD71F vmovaps xmm15,xmmword ptr[r11-0A0h]

这是20条指令,它们什么也不做,因为我不需要保留XMM的状态。我有100个这样的函数,编译器像这样膨胀。它们都是通过函数指针从同一调用站点调用的


我尝试更改调用约定(uu vectorcall/cdecl/fastcall),但这似乎没有任何作用。

使用x86-64 System V调用约定处理您希望通过函数指针组合在一起的助手函数。在该调用约定中,所有xmm/ymm0..15和zmm0..31都被调用截断,因此即使是需要5个以上向量寄存器的辅助函数也不必保存/恢复任何向量寄存器

调用它们的外部解释器函数仍应使用Windows x64 fastcall或vectorcall,因此从外部来看,它完全尊重调用约定

这将把XMM6..15的所有保存/恢复提升到该调用者中,而不是提升到每个助手函数中。这减少了静态代码大小,并通过函数指针分摊了多次调用的运行时成本


另外,MSVC不支持将函数标记为使用x86-64 System V调用约定,只支持fastcall与vectorcall,因此必须使用clang

(ICC有缺陷,在调用System V ABI函数时无法保存/恢复XMM6..15)

对于溢出的
\uuuum256
,因此将GCC与
-march=
一起使用通常不安全


对函数和函数指针声明使用
\uuuuu属性(sysv\u abi))
\uuuu属性(ms\u abi))

我认为
ms\u abi
\u快速呼叫
,而不是
\u向量呼叫
。Clang可能也支持
\uuuuuuuuuu属性((vectorcall))
,但我还没有尝试过。谷歌搜索结果主要是功能请求/讨论

void (*helpers[10])(float *, float*) __attribute__((sysv_abi));

__attribute__((ms_abi))
void outer(float *p) {
    helpers[0](p, p+10);
    helpers[1](p, p+10);
    helpers[2](p+20, p+30);
}
编译如下
-O3-march=skylake
。(Godbolt target Linux上的gcc/clang,但我在函数和函数指针上都使用了显式的
ms_abi
sysv_abi
,因此代码生成不依赖于默认值为
sysv_abi
这一事实。显然,您希望使用Windows gcc或clang构建函数,因此对其他函数的调用将使用该工具ht调用约定和有用的对象文件格式等)

请注意,gcc/clang为
outer()
发出代码,该代码需要RCX(Windows x64)中的传入指针arg,但将其传递给RDI和RSI(x86-64 System V)中的被调用方

GCC生成的代码基本相同。但是WindowsGCC在AVX上有缺陷

ICC19生成了类似的代码,但没有xmm6..15的保存/恢复。这是一个显示错误;如果任何被调用方像被允许的那样对这些regs进行重击,那么从这个函数返回将违反其调用约定

这使得clang成为唯一可以使用的编译器。那很好;叮当声很好


如果您的被调用方不需要所有的YMM寄存器,那么在外部函数中保存/恢复所有的YMM寄存器就太过分了。但现有的工具链没有中间立场;例如,您必须在asm中手工编写
outer
,以利用您知道没有任何可能的被调用方会碰到XMM15的优势



请注意,从内部
outer()
调用其他MS-ABI函数完全可以。GCC/clang也会(排除bug)为此发出正确的代码,如果被调用的函数选择不销毁xmm6..15,这也没关系。

通常,这些内在函数是内联的。为什么在您的代码中不是这样?您确定编译器优化已打开吗?“VM”是什么意思?如果函数不小,那么保存和恢复寄存器有什么问题?调用代码假定寄存器被保留。如果不保留它们,调用函数(或它的调用者,或它的调用者的调用者,…)的行为可能会不稳定。@Frogles我对你的心智能力没有任何假设。但考虑到你没有提供任何细节,也没有回答你的问题,我不得不猜测实际情况是什么。也许下次试着问一个更好的问题,而不是感觉不舒服
outer:                                  # @outer
        push    r14
        push    rsi
        push    rdi
        push    rbx
        sub     rsp, 168
        vmovaps xmmword ptr [rsp + 144], xmm15 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 128], xmm14 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 112], xmm13 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 96], xmm12 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 80], xmm11 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 64], xmm10 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 48], xmm9 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 32], xmm8 # 16-byte Spill
        vmovaps xmmword ptr [rsp + 16], xmm7 # 16-byte Spill
        vmovaps xmmword ptr [rsp], xmm6 # 16-byte Spill
        mov     rbx, rcx                            # save p 
        lea     r14, [rcx + 40]
        mov     rdi, rcx
        mov     rsi, r14
        call    qword ptr [rip + helpers]
        mov     rdi, rbx
        mov     rsi, r14
        call    qword ptr [rip + helpers+8]
        lea     rdi, [rbx + 80]
        lea     rsi, [rbx + 120]
        call    qword ptr [rip + helpers+16]
        vmovaps xmm6, xmmword ptr [rsp] # 16-byte Reload
        vmovaps xmm7, xmmword ptr [rsp + 16] # 16-byte Reload
        vmovaps xmm8, xmmword ptr [rsp + 32] # 16-byte Reload
        vmovaps xmm9, xmmword ptr [rsp + 48] # 16-byte Reload
        vmovaps xmm10, xmmword ptr [rsp + 64] # 16-byte Reload
        vmovaps xmm11, xmmword ptr [rsp + 80] # 16-byte Reload
        vmovaps xmm12, xmmword ptr [rsp + 96] # 16-byte Reload
        vmovaps xmm13, xmmword ptr [rsp + 112] # 16-byte Reload
        vmovaps xmm14, xmmword ptr [rsp + 128] # 16-byte Reload
        vmovaps xmm15, xmmword ptr [rsp + 144] # 16-byte Reload
        add     rsp, 168
        pop     rbx
        pop     rdi
        pop     rsi
        pop     r14
        ret