/fp:precise
と/fp:fast
フラグを使用するコードを調べていました。
のMSDNドキュメントによると/fp:precise
:
x86 プロセッサで /fp:precise を使用すると、コンパイラは float 型の変数に対して、代入とキャスト、および関数にパラメーターを渡すときに、適切な精度に丸めを実行します。この丸めにより、データがその型の容量を超える重要性を保持しないことが保証されます。/fp:precise を使用してコンパイルされたプログラムは、/fp:precise を使用せずにコンパイルされたプログラムよりも遅く、サイズが大きくなる可能性があります。/fp:precise は組み込み関数を無効にします。代わりに、標準のランタイム ライブラリ ルーチンが使用されます。詳細については、「/Oi (組み込み関数の生成)」を参照してください。
sqrtf
(/arch:SSE2
ターゲットx86/Win32
プラットフォームで呼び出される)への呼び出しの逆アセンブリを見ると、次のようになります。
0033185D cvtss2sd xmm0,xmm1
00331861 call __libm_sse2_sqrt_precise (0333370h)
00331866 cvtsd2ss xmm0,xmm0
この質問から、最新の x86/x64 プロセッサは 80 ビット レジスタを使用しない (または少なくともその使用を思いとどまらせる) ため、コンパイラは次善の策と思われることを実行し、64 ビット double を使用して計算を行うと考えています。また、組み込み関数が無効になっているため、ライブラリ sqrtf 関数への呼び出しがあります。
わかりました、これはドキュメントの内容に準拠しているようです。
ただし、x64 arch 用にコンパイルすると、奇妙なことが起こります。
000000013F2B199E movups xmm0,xmm1
000000013F2B19A1 sqrtps xmm1,xmm1
000000013F2B19A4 movups xmmword ptr [rcx+rax],xmm1
計算は 64 ビット double では実行されず、組み込み関数が使用されています。私が知る限り、結果は/fp:fast
フラグを使用した場合とまったく同じです。
両者の間に食い違いがあるのはなぜですか?/fp:precise
x64 プラットフォームでは動作しませんか?
ここで、サニティ チェックとして、VS2010 x86 で/fp:precise
と を使用して同じコードをテストしました/arch:SSE2
。驚いたことに、sqrtpd
組み込み関数が使用されていました。
00AF14C7 cvtps2pd xmm0,xmm0
00AF14CA sqrtsd xmm0,xmm0
00AF14CE cvtpd2ps xmm0,xmm0
何が起きてる?VS2012 がシステム ライブラリを呼び出すのに、VS2010 が組み込み関数を使用するのはなぜですか?
x64 プラットフォームを対象とした VS2010 のテストでは、VS2012 と同様の結果が得られます (/fp:precise
無視されているようです)。
古いバージョンの VS にアクセスできないため、これらのプラットフォームでテストを行うことはできません。
参考までに、Intel i5-m430 プロセッサを搭載した Windows 7 64 ビットでテストしています。