作者:平凡特产小店 | 来源:互联网 | 2023-09-25 16:48
我正在尝试使用 gcc 内联 asm 加载和存储 YMM 寄存器。我使用 vmovdqa 来做这件事。
为了将 __m256i 存储到特定的 YMM 寄存器(比如 YMM10),我使用以下代码
__m256i addr;
//load value to addr
asm ("vmovdqa %0,%%ymm10nt"
:
: "x" (addr)
:);
为了将 YMM10 中的值加载到变量,我使用以下代码
__m256i readbuff;
asm ("vmovdqa %%ymm10,%0nt"
: "=x" (readbuff)
:
:);
我在这里面临的问题是,在我用一个值加载 YMM10 之后,我只使用了加载了值的寄存器的一半。我的意思是只加载了 128 位,另一半全为零。
我做错了什么吗?我不确定要使用什么指令 - vmovdqa、vmovaps、vmovups。请就此给我建议。
回答
你似乎试图用内联汇编做的事情的整体设计被破坏了。这不是内联汇编的工作方式。这可能是一个 XY 问题;您希望代码执行某些操作,而您选择了一种不可行的方法。
我的意思是只加载了 128 位,另一半全为零。
听起来 GCCveroupper
在你的 asm 语句之间做了某处,可能是在函数调用边界。 您没有告诉 GCC YMM10 是您希望稍后阅读的输出。(有点类似于GCC 不会在我的内联 asm 函数调用周围推送寄存器,即使我有 clobbers错误地使用内联 asm)。在这种情况下,GCC 踩到了您的数据;在其他情况下,您可能会破坏 GCC 放在那里的一些数据,稍后再读取。
你可以用另一个__m256i
变量告诉 GCC 你的 asm 语句中的数据,register __m256i ymm10 asm("ymm10")
如果你真的想说服编译器使 asm 变得更糟,而不是让它__m256i
像往常一样将变量保存在寄存器中,也许是这样。
但真的不要。您可以使用或其他方式查看GCC 的 asm 输出gcc -S foo.c -o- | less
。(不要忘记通常的-O3 -march=native
或其他什么)。 如何从 GCC/clang 程序集输出中去除“噪音”? 在某些 YMM 寄存器上使用您自己的vmovdqa
指令,而 GCC 出于自己的目的使用其他 YMM 寄存器,只会使 asm 变得更糟。 https://gcc.gnu.org/wiki/DontUseInlineAsm
另请参阅https://stackoverflow.com/tags/inline-assembly/info以获取解释如何正确使用 GNU C 内联 asm 的指南和文档。(但您可能根本不需要 asm。)
请注意,"x" (addr)
需要 GCC 已经__m256i addr
在另一个 YMM 寄存器中,所以它甚至不是从内存“加载”,它只是在 GCC 已经从内存加载它之后复制 YMM 寄存器(如有必要)。这就是为什么我如此强烈地说这是毫无意义的。