我使用SBCL(64位v1.4.0)进行数值计算。 启用优化后,将显示以下编译器注释:
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)))
我认为double-float和fixnum都是64位宽。 为什么SBCL不能通过像C语言这样的寄存器返回双浮点值?有没有办法避免浮动到指针强制而没有内联扩展?
答案 0 :(得分:9)
问题是Lisp数据是动态类型的,函数的返回值必须包含类型信息。大多数实现中的类型标记存储在值的低位中。
这允许对fixnums进行特殊优化。它们的类型标记全为零,值是由类型标记中的位数左移的整数。添加这些值时,结果在标记位中仍然为零,因此您可以使用常规CPU操作对值执行算术运算。
但这对浮点值不起作用。执行CPU操作后,必须将type标记添加到值中。这就是&#34;浮动到指针强制&#34; (在许多语言中,它的一个更常见的词是&#34;拳击&#34;)。
声明返回类型并不能避免这种情况,因为调用者不一定能够访问声明--Lisp允许您在与他们调用的函数不同的编译单元中编译调用者。 / p>
如果声明函数INLINE
,则不需要这样做,因为调用者知道它返回的类型,并且硬件值可以直接返回给他们添加标签。
在这个古老的comp.lang.lisp thread中可以找到更详细的解释。它指的是CMUCL,这是SBCL的衍生(注意警告的措辞完全相同)。