2017-11-23 10 views
1

数値計算にはSBCL(64ビットv1.4.0)を使用します。コンパイラ・ノート以下、最適化を有効にした後 が表示されます。Common Lispで浮動小数点からポインタへの変換を避ける

note: doing float to pointer coercion (cost 13) to "<return value>" 

次のように私が使用するコードは次のとおりです。

(defun add (a b) 
    (declare (optimize (speed 3) (safety 0))) 
    (declare (double-float a b)) 
    (the double-float (+ a b))) 

私もftypeを試してみましたが、同じノートを持っています。一方

、コードは以下のことのメモを表示しません:

(defun add-fixnum (a b) 
    (declare (optimize (speed 3) (safety 0))) 
    (declare (fixnum a b)) 
    (the fixnum (+ a b))) 

私は二重フロートとFIXNUMが広い両方の64ビットであると思います。 なぜSBCLはC言語のようなレジスタを介してdouble float値を返すことができないのですか?そして、インライン展開せずに浮動小数点型の強制変換を回避する方法はありますか?

+0

https://groups.google.com/forum/#!topic/comp.lang.lisp/AsKvR0emFtU – Barmar

答えて

7

問題は、Lispデータが動的に型付けされ、関数の戻り値に型情報が含まれなければならないということです。ほとんどの実装における型タグは、値の下位ビットに格納されます。

これにより、fixnumの特別な最適化が可能になります。それらの型タグはすべてゼロであり、値は型タグ内のビット数だけ左にシフトされた整数です。これらの値を追加すると、タグビットには結果がまだゼロになるため、通常のCPU操作を使用して値に対して算術演算を実行できます。

しかし、これは浮動小数点値では機能しません。 CPU操作を実行した後、タイプタグを値に追加する必要があります。これは "float to pointer coercion"(多くの言語ではより一般的な単語は "ボクシング"です)が意味することです。

呼び出し元が必ずしも宣言にアクセスする必要がないため、戻り値の型を宣言してもこれを回避することはできません。 - 呼び出し元は呼び出し元の関数とは別のコンパイル単位で呼び出し元をコンパイルできます。

関数INLINEを宣言した場合、呼び出し元が返す型を知っていて、タグを追加せずに直接ハードウェア値を返すことができるため、これを行う必要はありません。

さらに詳しい説明は古代comp.lang.lisp threadにあります。これはSBCLの由来であるCMUCLを指しています(警告の文言はまったく同じです)。

+0

ありがとうございました!私はSBCLと他のCommon Lispインタプリタの型タグ仕様を理解していて、fixnum(実際にはSBCLでは62ビット幅)のケースは特別でした。別のコンパイルについてのあなたの説明は、私の問題を完全に解決しました。ありがとうございました! – magnon

関連する問題