2016-06-01 3 views

答えて

5

あなたは、Cコンパイラのしくみを見るだけで答えることができるいくつかの簡単な質問をしました。そこから、使用した指示を調べて、実際に使用する指示を決定することができます。 (libmには何百もの異なる丸め関数があるので、最初は正しいものを選ぶことが必ずしも簡単ではない)。

-O3 -ffast-mathを使用すると、潜在的にNaNにerrnoを設定する必要がないため、ほとんどの単純なlibm関数がインライン展開されます。

とにかく、コンパイラの入力と出力、gcc 5.3 on the Godbolt Compiler Explorerからは:

#include <math.h> 

int floor_double(double x) { return (int) floor(x); } 
    roundsd xmm0, xmm0, 9 
    cvttsd2si  eax, xmm0 
    ret 

int truncate_double(double x) { return (int)x; } 
    cvttsd2si  eax, xmm0 
    ret 

は、Intelの命令セット・リファレンスマニュアルPDFへのリンクがタグのwikiを参照してください。 PDFから生成されるunofficial HTML versionもあります。 floor() functionのように-Infinityに丸めるのではなく、trunc()のように、

cvttsd2si truncates towards zeroのようになります。

その理由は、floor()がその命令セットが利用可能なときにSSE4.1 roundsdにコンパイルする理由です。 (それ以外の場合は、ゴールドボトルの-marchオプションを削除または変更して表示されるように、丸めモードを実行する必要があります)。 CVTTPD2DQ`のような変換命令の


もパックされたバージョンは、一度に2を行います。 (またはAVXの場合は4)。

0

フロアダブルにはCVTTPD2DQ—Convert with Truncation Packed Double-Precision FP Values to Packed Dword Integersを使用してください。

CVTTPD2DQするXMMレジスタに2つのdoubleから2つのintにフロア/トランケートします。

対応インテルC/C++コンパイラ組み込みEAXようGPR(汎用レジスタ)に結果を置くために

____m128i _mm_cvttpd_epi32(__m128d a) 

で、次の手順を使用することができます。

CVTTPD2DQ xmm0, xmm1 ; XMM1 is the source of doubles 
movd eax, xmm0  ; extracts int(0) from XMM0 to EAX 
pextrd ecx, xmm0, 1 ; extracts int(1) from XMM0 to ECX 
+0

どのようにxmmからf.eに結果を移動できますか? eax登録? – formateu

+1

@formateu:私は自分の答えを更新しました。 – zx485

+0

zx485:そのintがeaxレジスタに収まる場合、movd eax、xmm0はその仕事をしますか? – formateu

関連する問題