2016-11-20 37 views
1

私はgccコンパイラを使用していますので、sse丸めモードをすばやく変更できます。次のコードは、Linuxの下でそれをコンパイルした場合に動作します: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のを使用して、Windowsの下でそれをコンパイルするときに、丸めモードは変更されません。理由は何ですか?

+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)。 が最初にSTMXCSRを実行せずにLDMXCSRを使用する例が多数見つかりません。

ああ、あなたは実際にあなたのコードでその部分を間違っていると思います。 _MM_MASK_MASKがどのように定義されているかを見ていないが、その名前にMASKという単語が含まれている。あなたはそれをANDingするのではなく、他のさまざまな定数と論理和を取っています。 _MM_MASK_MASKですべてを論理和しているので、毎回同じ値にMXCSRを設定しているでしょう。すべての丸めモードビットがセットされていると仮定しています。


@StoryTellerが指摘するようにx86ハードウェアの一致によって設けられた4つの丸めモードは、4つのC99でfenv.hで定義されているので、あなたは、インラインアセンブラまたは丸めモードを変更するための組み込み関数は必要ありません:(FE_DOWNWARD, FE_TONEAREST (the default), FE_TOWARDZERO, and FE_UPWARD)、これはfesetround(FE_DOWNWARD);で設定できます。

あなたはその場で丸めモードを変更すると、オプティマイザは、丸めモードが異なって設定された場所に任意のFPオプスの順序を変更しないことを確認したい場合は、
#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)も参照してください。


まだ早い計算x/yを考えてからCSEを防ぐことはできませんasm volatileでそれを手動で行うとはいえ、同じ値であり、asm文の後にそれを再計算しませ。 xまたはyを、実際には使用されないasmステートメントの読み書きオペランドとして使用しない限り、例えば

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

あなたは丸めモードの変更点はまた、コンパイラが変更されたとxを扱う点であることを保証するために、その同じインラインasm文の内側LDMXCSRを置くことができます。

関連する問題