避免浮动到Common Lisp中的指针强制

mag*_*non 3 double optimization common-lisp

我使用SBCL(64位v1.4.0)进行数值计算.启用优化后,将显示以下编译器注释:

note: doing float to pointer coercion (cost 13) to "<return value>"
Run Code Online (Sandbox Code Playgroud)

我使用的代码如下:

(defun add (a b)
  (declare (optimize (speed 3) (safety 0)))
  (declare (double-float a b))
  (the double-float (+ a b)))
Run Code Online (Sandbox Code Playgroud)

我也试过ftype并得到了相同的说明.

另一方面,以下代码未显示注释:

(defun add-fixnum (a b)
  (declare (optimize (speed 3) (safety 0)))
  (declare (fixnum a b))
  (the fixnum (+ a b)))
Run Code Online (Sandbox Code Playgroud)

我认为double-float和fixnum都是64位宽.为什么SBCL不能通过像C语言这样的寄存器返回双浮点值?有没有办法避免浮动指针强制没有内联扩展?

Bar*_*mar 9

问题是Lisp数据是动态类型的,函数的返回值必须包含类型信息.大多数实现中的类型标记存储在值的低位中.

这允许对fixnums进行特殊优化.它们的类型标记全为零,值是由类型标记中的位数左移的整数.添加这些值时,结果在标记位中仍为零,因此您可以使用常规CPU操作对值执行算术运算.

但这不适用于浮点值.执行CPU操作后,必须将type标记添加到值中.这就是"浮动到指针强制"的意思(在许多语言中它更常用的词是"拳击").

声明返回类型并不能避免这种情况,因为调用者不一定能够访问声明--Lisp允许您在一个单独的编译单元中编译调用者而不是他们调用的函数.

如果声明该函数INLINE,则不需要这样做,因为调用者知道它返回的类型,并且硬件值可以直接返回给它们而不添加标记.

在这个古老的comp.lang.lisp线程中可以找到更详细的解释.它指的是CMUCL,这是SBCL的衍生(注意警告的措辞完全相同).