declared return type prevents tail call
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
New
|
Undecided
|
Unassigned |
Bug Description
In the following example, the funcall is compiled as a tail call but not if the caller's return type is declared although the callee's and caller's return types are the same. I would expect both to be tail calls although clearly it's not mandated by the spec.
Tested on linux x86-64 with sbcl commit 8c119e5a4 (latest as of today).
CL-USER> (defun fff (fn x)
(declare (type (function (t) (values fixnum &optional)) fn)
(funcall fn x))
FFF
CL-USER> (disassemble 'fff)
; disassembly for FFF
; Size: 25 bytes. Origin: #x53667E78 ; FFF
; 78: 498B4510 MOV RAX, [R13+16] ; thread.
; 7C: 488945F8 MOV [RBP-8], RAX
; 80: 488BD7 MOV RDX, RDI
; 83: 488BC6 MOV RAX, RSI
; 86: B902000000 MOV ECX, 2
; 8B: FF7508 PUSH QWORD PTR [RBP+8]
; 8E: FF60FD JMP [RAX-3]
NIL
CL-USER> (declaim (ftype (function (t t) (values fixnum &optional)) fff))
(FFF)
CL-USER> (defun fff (fn x)
(declare (type (function (t) (values fixnum &optional)) fn)
(funcall fn x))
WARNING: redefining COMMON-
FFF
CL-USER> (disassemble 'fff)
; disassembly for FFF
; Size: 44 bytes. Origin: #x53667F21 ; FFF
; 21: 498B4510 MOV RAX, [R13+16] ; thread.
; 25: 488945F8 MOV [RBP-8], RAX
; 29: 4883EC10 SUB RSP, 16
; 2D: 488BD7 MOV RDX, RDI
; 30: 498BC0 MOV RAX, R8
; 33: B902000000 MOV ECX, 2
; 38: 48892C24 MOV [RSP], RBP
; 3C: 488BEC MOV RBP, RSP
; 3F: FF50FD CALL [RAX-3]
; 42: 4C8B45E8 MOV R8, [RBP-24]
; 46: 488B7DF0 MOV RDI, [RBP-16]
; 4A: C9 LEAVE
; 4B: F8 CLC
; 4C: C3 RET
If you also declare (optimize (debug 0)) the tail call is converted to a jump.