c - 让 GCC 在整个使用内联汇编的函数中保留 SSE 寄存器

标签 c gcc assembly sse inline-assembly

我正在用 C 语言编写一个程序,需要进行一些快速的数学计算。我正在使用内联 SSE 汇编指令来获取一些 SIMD 操作(使用压缩 double float )。我在 Linux 上使用 GCC 进行编译。

我现在需要循环一些数据,我在计算中使用了一个常数因子。我想在循环期间将该因素隐藏在一个安全的寄存器中,这样我就不必每次都重新加载它。

用一些代码来说明:

struct vect2 {
    fltpt x;
    fltpt y;
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */
typedef struct vect2 vect2_t;


void function()
{
    /* get a specific value set up in xmm1, and keep it there for the 
     * rest of the loop. */
    for( int i = 0, i<N; i++ ){
        asm(
            "Some calculations;"
            "on an element of;"
            "a data set.;"
            "The value in xmm1;"
            "is needed;"
        );
    }
}

我试过使用“register”关键字做一些事情。但如果我没记错的话,看起来我只能保留一个指向该结构的指针(在通用寄存器中)。这将需要在每次迭代中被推迟,浪费宝贵的时间。

register vect2_t hVect asm("xmm1") = {h, h};
/* Gives error: data type of 'hVect' isn't suitable for a register */

register vect2_t *hVect2 asm("rax");
*hVect2 = (vect2_t){h,h};
/* Seems to work, but not what I'm looking for */

我不只是想假设 GCC 不会更改 xmm1 寄存器,这太像“从 Nose 里飞出来的恶魔”之类的东西了:-)。所以我希望有一个合适的方法来做到这一点。

最佳答案

我认为这里的解决方案是让 gcc 知道你的 vec2_t 类型实际上是一个 vector ;然后你可以只计算循环不变值并将其视为普通变量(除非编译器知道它是 vector 类型):

typedef double vec2_t __attribute__ ((vector_size (16)));

void function()
{
  /* get a specific value set up, e.g. */
  vec2_t invariant;
  asm( "some calculations, soring result in invariant."
       : "=x" (invariant) );

  for( int i = 0; i<N; i++ ){
    asm(
            "Some calculations;"
            "on an element of;"
            "a data set.;"
            "The value in xmm1;"
            "is needed;"
            : "x" (invariant) // and other SSE arguments
       );
   }
}

我只是在循环内用一个简单的计算编译了它,并且在至少优化级别 1 的情况下,invariant 的值在循环期间保存在 XMM 寄存器中。

(这一切都假设您不需要显式 XMM 寄存器中的循环不变性;并且您可以使用 GCC 的正常寄存器分配)。

关于c - 让 GCC 在整个使用内联汇编的函数中保留 SSE 寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1250083/

相关文章:

c - Makefile .o 文件规则问题

c++ - gcc 4.7 的可选和变体

linux - 使用 FASM EQU 通过 $ - 符号计算出错误的大小 "len"

assembly - 如何正确执行 ADD/SUB 有符号或无符号整数?

c - 如何为结构数组中的 char 字符串分配内存?

c - 使用 malloc() 分配内存时出错,只能向表中添加一项

c - C语言中如何将整数转为字符串? (例如 0 => 零)

我可以将 memcmp 与 qsort 一起使用吗?

编译器和数据类型 => c 作为引用

assembly - 在MIPS中使用addi vs addiu的特定情况