2016-11-20 114 views
1

我正在使用gcc編譯器,我希望能夠快速更改sse舍入模式。MinGW gcc設置fp舍入模式

#include <xmmintrin.h> 
unsigned int _mxcsr_up = _MM_MASK_MASK | _MM_ROUND_UP; 
unsigned int _mxcsr_down = _MM_MASK_MASK | _MM_ROUND_DOWN; 
unsigned int _mxcsr_n = _MM_MASK_MASK; 

void round_nearest_mode() { 
    asm (
    "ldmxcsr %0" : : "m" (_mxcsr_n) 
    ); 
} 

void round_up_mode() { 
    asm (
    "ldmxcsr %0" : : "m" (_mxcsr_up) 
    ); 
} 

void round_down_mode() { 
     asm (
     "ldmxcsr %0" : : "m" (_mxcsr_down) 
     ); 
} 

但是當我編譯使用MinGW的窗戶下,舍入模式沒有改變:如果編譯linux下下面的代碼工作。是什麼原因?

+3

如果您處於託管環境中,請使用標準庫而不是內聯彙編(http://en.cppreference.com/w/c/numeric/fenv/feround) – StoryTeller

+0

@StoryTeller我包含但是我無法使用它的內容。我認爲條件'#if _GLIBCXX_USE_C99_FENV_TR1'不滿意,但我不知道爲什麼。 –

+0

將您的項目構建爲C99。將'-std = c99'添加到編譯器調用中(或者,如果使用IDE,請在項目選項中查找該選項)。 – StoryTeller

回答

1

提供所述_MM_ROUND_UP常數還限定圍繞的相關指令_mm_setcsr(unsigned int i)_mm_getcsr(void)固有包裝相同的標題。

您通常應該檢索舊值,OR或ANDN您想要更改的位,然後應用新值。 (例如mxcsr &= ~SOME_BITS)。你不會找到很多例子,只是使用LDMXCSR沒有先做一個STMXCSR。

哦,我認爲你實際上是在代碼中做錯了那部分。我沒有看過如何定義_MM_MASK_MASK,但它的名字包含MASK這個詞。你用其他各種常量對它進行或運算,而不是對其進行「與」運算。 您可能每次都將MXCSR設置爲相同的值,因爲您對_MM_MASK_MASK進行了或運算,我假設所有舍入模式位均已設置。


由於@StoryTeller指出的那樣,你不需要內聯彙編或內在函數更改舍入模式,由於x86硬件匹配所提供的四種舍入模式由fenv.h在C99的定義四種:(FE_DOWNWARD, FE_TONEAREST (the default), FE_TOWARDZERO, and FE_UPWARD)您可以使用fesetround(FE_DOWNWARD);進行設置。

如果你想改變的飛行舍入模式,並確保優化器不會重新排序任何浮點操作的地方設置舍入模式不同的地方,你需要
#pragma STDC FENV_ACCESS ONbut gcc doesn't support it。另見this gcc bug from 2008 which is still open: Optimization generates incorrect code with -frounding-math option (#pragma STDC FENV_ACCESS not implemented)


asm volatile做手工仍然不會阻止CSE從思想x/y前面計算的值相同,但是,並沒有彙編語句後重新計算它。除非您使用xy作爲從未實際使用的asm語句的讀寫操作數。例如

asm volatile("" : "+g"(x)); // optimizer must not make any assumptions about x's value. 

你可以把LDMXCSR相同的直列彙編語句內,以保證在舍入模式改變的點也是在那裏,編譯器將x作爲已經改變的地步。