【问题标题】:Loading and storing YMM registers using gcc inline assembly使用 gcc 内联汇编加载和存储 YMM 寄存器
【发布时间】:2021-03-21 00:50:26
【问题描述】:

我正在尝试使用 gcc 内联 asm 加载和存储 YMM 寄存器。我使用 vmovdqa 来执行此操作。

为了将 __m256i 存储到特定的 YMM 寄存器(比如 YMM10),我使用以下代码

__m256i addr;
//load value to addr
asm ("vmovdqa %0,%%ymm10\n\t"
            :
            : "x" (addr)
            :);

为了将 YMM10 中的值加载到变量中,我使用以下代码

__m256i readbuff;
asm ("vmovdqa %%ymm10,%0\n\t"\
            : "=x" (readbuff)\
            :\
            :);

我在这里面临的问题是,在我用一个值加载 YMM10 之后,我只使用了加载值的寄存器的一半。我的意思是只加载了 128 位,另一半全为零。

我做错了吗?我不确定要使用什么指令 - vmovdqa、vmovaps、vmovups。 请在这方面给我建议。

【问题讨论】:

  • 这种内联汇编的用法是不正确的,不能期望工作。您不能假设您分配给随机寄存器的值仍然存在于下一个asm 语句中,并且您也不允许在不将寄存器放入 clobber 列表的情况下覆盖随机寄存器。如果您提供更多上下文,也许可以找到针对您的underlying problem 的更好解决方案。

标签: c gcc x86 inline-assembly avx2


【解决方案1】:

你似乎试图用内联汇编做的整体设计被打破了。 这不是内联汇编的工作方式。这可能是 X-Y 问题;你想让你的代码做一些事情,而你选择了一种不可行的方法。

我的意思是只加载了 128 位,另一半全为零。

听起来 GCC 在您的 asm 语句之间的某个地方(可能在函数调用边界)做了一个 veroupper您没有告诉 GCC YMM10 是您希望稍后阅读的输出。 (有点类似于GCC doesn't push registers around my inline asm function call even though I have clobbers 错误地使用内联汇编)。在这种情况下,GCC 踩到了您的数据;在其他情况下,您可以销毁 GCC 放在那里的一些数据,稍后再读取。

可以告诉 GCC 使用另一个 __m256i 变量(可能是 register __m256i ymm10 asm("ymm10"))告诉 GCC 来自您的 asm 语句的数据,如果您真的想说服编译器制作更糟糕的 asm 而不仅仅是让它像往常一样将__m256i 变量保存在寄存器中。

但真的不要。您可以使用gcc -S foo.c -o- | less 或其他方式查看 GCC 的asm 输出。 (不要忘记通常的-O3 -march=native 或其他)。 How to remove "noise" from GCC/clang assembly output? 在某些 YMM 寄存器上使用您自己的 vmovdqa 指令,而 GCC 出于自己的目的使用其他 YMM 寄存器,只会使 asm 变得更糟。 https://gcc.gnu.org/wiki/DontUseInlineAsm

另请参阅https://stackoverflow.com/tags/inline-assembly/info 以获得解释如何正确使用 GNU C 内联汇编的指南和文档。 (但您可能根本不需要 asm。)


请注意,"x" (addr) 要求 GCC 已经在另一个 YMM 寄存器中拥有__m256i addr,因此它甚至不是从内存中“加载”,它只是在 GCC 已经从内存中加载后复制 YMM 寄存器(如果需要)。这就是为什么我如此强烈地说这是没有意义的。

【讨论】:

    猜你喜欢
    • 2019-12-10
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2014-09-19
    • 2017-12-23
    相关资源
    最近更新 更多