Is there a way to tell if SBCL has applied an optimization to a particular piece of source code? For example, on entering the following I would expect the case
statement to be optimized into (print "0")
:
(defconstant +n+ 0)
(case +n+
(0 (print "0"))
(1 (print "1")))
But expanding gives something different:
* (macroexpand '(case +n+ (0 (print "0")) (1 (print "1"))))
(LET ((#:G415 +N+))
(DECLARE (IGNORABLE #:G415))
(COND ((EQL #:G415 '0) NIL (PRINT "0")) ((EQL #:G415 '1) NIL (PRINT "1"))))
This is probably an unusual example, but how would one check for an optimization, in general.
As explained by Rainer Joswig, one possibility is to check for the disassembly. For example, with SBCL:
CL-USER> (defconstant +n+ 0)
"0"
"0"
CL-USER> (disassemble (compile nil (lambda () (case +n+
(0 (print "0"))
(1 (print "1"))))))
The above outputs this, which shows that the code has been simplified:
; disassembly for (LAMBDA ())
; Size: 32 bytes. Origin: #x52E552CC ; (LAMBDA ())
; CC: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; D0: 488945F8 MOV [RBP-8], RAX
; D4: 488B15B5FFFFFF MOV RDX, [RIP-75] ; "0"
; DB: B902000000 MOV ECX, 2
; E0: FF7508 PUSH QWORD PTR [RBP+8]
; E3: B8A2324950 MOV EAX, #x504932A2 ; #<FDEFN PRINT>
; E8: FFE0 JMP RAX
; EA: CC10 INT3 16 ; Invalid argument count trap
NIL
There is also the possibility to show how the compiler is configured:
CL-USER> (sb-ext:describe-compiler-policy)
Basic qualities:
COMPILATION-SPEED = 1
DEBUG = 1
SAFETY = 1
SPACE = 1
SPEED = 1
INHIBIT-WARNINGS = 1
Dependent qualities:
SB-C::CHECK-CONSTANT-MODIFICATION = 1 -> 1 (maybe)
SB-C::TYPE-CHECK = 1 -> 3 (full)
SB-C::CHECK-TAG-EXISTENCE = 1 -> 3 (yes)
SB-C::LET-CONVERSION = 1 -> 3 (on)
SB-C:ALIEN-FUNCALL-SAVES-FP-AND-PC = 1 -> 3 (yes)
SB-C:VERIFY-ARG-COUNT = 1 -> 3 (yes)
SB-C::INSERT-DEBUG-CATCH = 1 -> 1 (maybe)
SB-C::RECOGNIZE-SELF-CALLS = 1 -> 0 (no)
SB-C::FLOAT-ACCURACY = 1 -> 3 (full)
SB-C:INSERT-STEP-CONDITIONS = 1 -> 0 (no)
SB-C::COMPUTE-DEBUG-FUN = 1 -> 1 (yes)
SB-C:STORE-SOURCE-FORM = 1 -> 1 (maybe)
SB-C::PRESERVE-SINGLE-USE-DEBUG-VARIABLES = 1 -> 0 (no)
SB-C::INSERT-ARRAY-BOUNDS-CHECKS = 1 -> 3 (yes)
SB-C::STORE-XREF-DATA = 1 -> 3 (yes)
SB-C:STORE-COVERAGE-DATA = 1 -> 0 (no)
SB-C::INSTRUMENT-CONSING = 1 -> 1 (no)
SB-C::STORE-CLOSURE-DEBUG-POINTER = 1 -> 0 (no)
SB-KERNEL:ALLOW-NON-RETURNING-TAIL-CALL = 1 -> 0 (no)
If you don't want to dive into the assembly, it looks like an alternate (but potentially misleading) strategy is to compare with disassembly size on something that can't be optimized. Testing my case example with defparameter, rather than defconstant, increases the assembly by a factor of 3. Also, do you have any comment regarding just writing a macro for special uses where you want to guarantee an optimization (eg, putting the case statement in a macro that analyzes the parameter--assuming you recompile if it changes)?