我使用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语言一样通过寄存器返回一个双浮点值?有没有办法避免 float 到指针强制而没有内联扩展?
最佳答案
问题是 Lisp 数据是动态类型的,函数的返回值必须包含类型信息。大多数实现中的类型标签存储在值的低位。
这允许对 fixnum 进行特殊优化。它们的类型标记全为零,值是左移类型标记中位数的整数。当您添加这些值时,结果的标记位中仍然包含零,因此您可以使用正常的 CPU 操作对这些值执行算术运算。
但这不适用于浮点值。在执行 CPU 操作后,它必须将类型标记添加到值中。这就是“ float 到指针强制”的含义(在许多语言中更常见的词是“装箱”)。
声明返回类型并不能避免这种情况,因为调用者不一定有权访问声明——Lisp 允许您在与调用函数不同的编译单元中编译调用者。
如果你声明函数 INLINE
,那么这个就不需要了,因为调用者知道它返回的类型,硬件值可以直接返回给他们,不用加标签。
更详细的解释可以在这个古老的comp.lang.lisp thread中找到。 .它指的是 CMUCL,它是 SBCL 的派生词(注意警告的措辞完全相同)。
关于optimization - 避免 float 到 Common Lisp 中的指针强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47450450/