检查 SBCL 中的编译器优化

Checking For A Compiler Optimization in SBCL

有没有办法判断 SBCL 是否对特定源代码进行了优化?例如,在输入以下内容时,我希望 case 语句被优化为 (print "0"):

(defconstant +n+ 0)

(case +n+
  (0 (print "0"))
  (1 (print "1")))

但是扩展会带来不同的东西:

* (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"))))

这可能是一个不寻常的例子,但通常如何检查优化。

正如 Rainer Joswig 所解释的,一种可能性是检查反汇编。例如,使用 SBCL:

CL-USER> (defconstant +n+ 0)  
"0" 
"0"

CL-USER> (disassemble (compile nil (lambda () (case +n+
  (0 (print "0"))
  (1 (print "1"))))))

上面输出这个,说明代码已经简化了:

; 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

还有可能显示编译器是如何配置的:

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)