Warm tip: This article is reproduced from serverfault.com, please click

Checking For A Compiler Optimization in SBCL

发布于 2020-12-01 17:30:10

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.

Questioner
davypough
Viewed
0
coredump 2020-12-02 06:28:08

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)