2016-04-22 5 views
5

私は丸めモード(+ inf、-inf、nearest、またはtruncate)を変更するRust crateを扱っています。 、私はそれが意図したとおりに動作するデバッグモードでコードをコンパイルすると正の無限大に向かって丸めたときどのLLVMパスが浮動小数点最適化を担当していますか?

fn upward() { 
    let cw: u32 = 0; 
    unsafe { 
    asm!("stmxcsr $0; 
      mov $0, %eax; 
      or $$0x4000, %eax; 
      mov %eax, $0; 
      ldmxcsr $0;" 
      : "=*m"(&cw) 
      : "*m"(&cw) 
      : "{eax}" 
     ); 
    } 
} 

は、私は3分の1 0.3333333333337を得る:

丸めモードを変更する機能は、インラインアセンブリを使用して書かれていますリリースモードでコンパイルすると、丸めモードに関係なく同じ結果が得られます。私はこの動作が、LLVMバックエンドが行う最適化によるものだと思います。

この最適化を担当するLLVMパスが分かっていた場合は、現時点で他の回避策が表示されないため、これらを無効にすることができます。

+0

この情報は、LLVMのバージョン(パスの追加と削除が自由です)と、結果的に 'rustc'のバージョンに依存している可能性があります。 'rustc'のどのバージョンを使用していますか?アップグレードの際にこれが壊れてもかまいませんか? –

+0

私は夜通し錆1.10を使用しています。私はそれが壊れても構わない。何が起こっているのか理解できれば、ちょっとした努力をして回避策を講じることができます。 –

+1

いくつかの読書の後、私は、()関数呼び出しの前にdivide命令を動かしているいくつかのスケジューリングパスがあると思います。 (ちょうど推測)、私が間違っている場合は私を修正します。 –

答えて

4

基本的には、これを行うことはできません。 LLVMでは、すべての浮動小数点演算でデフォルトの丸めモードが使用され、浮動小数点制御レジスタは決して読み取られたり変更されたりしないものとみなされます。

興味があれば、some discussion of this issue recently on the LLVM-dev mailing listがあります。

一方、信頼性の高い唯一の回避策は、asm!("addsd $0, $1"のようなインラインアセンブリを使用することです。

Rustの標準ライブラリでは、丸めモードを変更しないことも前提としています(特に、浮動小数点と文字列間の変換コードはこれに敏感です)。

+0

私が正しく理解していれば、インラインアセンブリを使用するとき、mxcsrまたはfctrlレジスタで設定された丸めモードがasmの計算で考慮されます!マクロ? –

+1

はい。この時点では、基本的には生のアセンブリを書くだけなので、RustまたはLLVM IRの意味は重要ではありません。 –

+0

はい、LLVM最適化がIR上で行われました。ありがとうございます。 –

関連する問題