Optimize (funcall (constantly ...))

Bug #1800539 reported by Paul F. Dietz
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Undecided
Unassigned

Bug Description

(as seen on #lisp)

(funcall (constantly x)) should optimize to x in compiled code. Currently, even at speed 3 and constantly declared inline, the call to constantly is not optimized away.

Revision history for this message
Steve Losh (stevelosh) wrote :

I was the one who asked about this in #lisp.

More generally: it would be nice if (funcall (constantly v) a b c) could get translated to something like (prog1 v a b c).

My use case is an inlineable A* search function that takes a heuristic function as an argument. It would be nice if, when you declare A* inline and pass (constantly 0) as the heuristic, you'd get:

    (+ score (funcall heuristic target)) ; original
    (+ score (funcall (constantly 0) target)) ; inlined
    (+ score (prog1 0 target)) ; optimize
    (+ score 0) ; optimize further

which would let it just gracefully degrade to Dijkstra's if the user passes (constant 0) for the heuristic.

This kind of optimization does happen if you pass in an equivalent lambda instead of using CONSTANTLY:

(disassemble
  (lambda ()
    (declare (optimize speed))
    (let* ((v 0)
           (h (constantly v)))
      (funcall h 1 2 3))))

; disassembly for (LAMBDA ())
; Size: 56 bytes. Origin: #x52C336BB
; BB: 4883EC10 SUB RSP, 16 ; no-arg-parsing entry point
; BF: 31D2 XOR EDX, EDX
; C1: B902000000 MOV ECX, 2
; C6: 48892C24 MOV [RSP], RBP
; CA: 488BEC MOV RBP, RSP
; CD: B818643150 MOV EAX, #x50316418 ; #<FDEFN CONSTANTLY>
; D2: FFD0 CALL RAX
; D4: 488BC2 MOV RAX, RDX
; D7: BA02000000 MOV EDX, 2
; DC: BF04000000 MOV EDI, 4
; E1: BE06000000 MOV ESI, 6
; E6: B906000000 MOV ECX, 6
; EB: FF7508 PUSH QWORD PTR [RBP+8]
; EE: FF60FD JMP QWORD PTR [RAX-3]
; F1: CC0F BREAK 15 ; Invalid argument count trap

(disassemble
  (lambda ()
    (declare (optimize speed))
    (let* ((v 0)
           (h (lambda (&rest args)
                (declare (ignore args))
                v)))
      (funcall h 1 2 3))))

; disassembly for (LAMBDA ())
; Size: 10 bytes. Origin: #x52C3352B
; 2B: 31D2 XOR EDX, EDX ; no-arg-parsing entry point
; 2D: 488BE5 MOV RSP, RBP
; 30: F8 CLC
; 31: 5D POP RBP
; 32: C3 RET
; 33: CC0F BREAK 15 ; Invalid argument count trap

Revision history for this message
Stas Boukarev (stassats) wrote :

15746737e35c1286ab0ad72df517274a4ad1a34d

Changed in sbcl:
status: New → Fix Committed
Stas Boukarev (stassats)
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.