Many standard Common Lisp functions, particularly those which do simple calculations or access data from arrays or structures, can be compiled inline by the compiler. Inline compilation results in faster, often significantly faster run times as the function call and return overheads are saved.
But there are tricks to getting the compiler to inline, and there are tools which assist is expalining what the compiler is doing. In this note, we take a simple function with a call to the math function round, and try to get the call to round to inline. Here is the function:
(defun foo (x) (declare (optimize (speed 3) (safety 0) (debug 0)) (double-float x)) (round (* x x)))
round looks like a good candidate for inlining: the type of its argument is known and speed, safety, and debug have values calling for maximum speed. But when it is compiled and the compiled function is disassembled, we see that round was not inlined:
cl-user(10): (compile 'foo) foo nil nil cl-user(11): (disassemble 'foo) ;; disassembly of #<Function foo> ;; formals: x ;; constant vector: 0: round ;; code start: #x10003508c80: 0: 48 83 ec 68 sub rsp,$104 4: 4c 89 74 24 08 movq [rsp+8],r14 9: f2 44 0f 10 6f movsd xmm13,[rdi-10] f6 15: f2 45 0f 59 ed mulsd xmm13,xmm13 20: f2 45 0f 10 fd movsd xmm15,xmm13 25: 31 c0 xorl eax,eax 27: 41 ff 97 d7 03 call *[r15+983] ; sys::new-double-float 00 00 34: 4c 89 7c 24 18 movq [rsp+24],r15 39: 48 8d 64 24 68 leaq rsp,[rsp+104] 44: 49 8b 6e 36 movq rbp,[r14+54] ; round 48: b0 08 movb al,$8 50: ff e3 jmp *rbx cl-user(11):
The line labeled 44 is the jump to the round function.
So what went wrong?