2009-08-08 60 views
7

我正在編寫一個需要做一些快速數學計算的C程序。我正在使用內聯SSE彙編指令來獲取一些SIMD操作(使用打包的雙精度浮點數)。我正在Linux上使用GCC進行編譯。獲取GCC在整個使用內聯asm的函數中保留SSE寄存器

我處於需要循環一些數據的情況,並且在我的計算中使用了一個常數因子。我希望在循環過程中將這個因子保存在一個安全的寄存器中,所以我不必每次都重新加載它。

要使用一些代碼澄清:

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 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註冊,這是太多的「惡魔飛出一個人的鼻子」樣的東西:-)。所以我希望有一個合適的方法來做到這一點。

回答

8

我認爲這裏的解決方案是讓gcc知道你的vec2_t類型實際上是一個向量;那麼你可以計算出循環不變值,並把它作爲一個正常的變量(除了編譯器知道它是一個矢量型):

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的正常寄存器分配)。

3

我認爲最好將寄存器賦值給編譯器。它可能比你更好地跟蹤它。 GCC將已經使用SSE擴展,但如果您確定自己更清楚,請使用GCC __builtin函數。 說實話,我懷疑你會以這種方式加快速度。

祝你好運!

這些網站可能是有趣的看看。

GCC X86 Built-in functions

Working with SIMD with GCC

3

我使用匯編語言和C和我會在這裏做的是,我會寫在裝配全功能工作。 如果您有靈活的製造系統,我建議單獨組裝ASM功能並將其鏈接到您的應用程序中。唯一的問題是該函數不能被編譯器內聯。

void function(void); // C

extern「C」function(void); // C++