Skip to content

Instantly share code, notes, and snippets.

@fouric
Last active August 28, 2019 18:31
Show Gist options
  • Save fouric/867cd3fb4d86fec991c63ebbf3c08317 to your computer and use it in GitHub Desktop.
Save fouric/867cd3fb4d86fec991c63ebbf3c08317 to your computer and use it in GitHub Desktop.
the SBCL compiler is available at runtime; how much can we optimize compilation of a function if we have information about its parameters?
;; example code to test out "JIT compilation" in (SBCL) CL
(defun foo (x f n)
"call f(f(f(...f(x)))) with f being called n times"
(dotimes (i n)
(setf x (funcall f x)))
x)
;; no type declarations
; Size: 186 bytes. Origin: #x1004C502AC
; 2AC: 498B4C2458 MOV RCX, [R12+88] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; 2B1: 48894DF8 MOV [RBP-8], RCX
; 2B5: 488B4DE8 MOV RCX, [RBP-24]
; 2B9: 8D41F1 LEA EAX, [RCX-15]
; 2BC: A801 TEST AL, 1
; 2BE: 7512 JNE L0
; 2C0: A80F TEST AL, 15
; 2C2: 0F8595000000 JNE L4
; 2C8: 8079F111 CMP BYTE PTR [RCX-15], 17
; 2CC: 0F858B000000 JNE L4
; 2D2: L0: 31F6 XOR ESI, ESI
; 2D4: EB5E JMP L3
; 2D6: 660F1F840000000000 NOP
; 2DF: 90 NOP
; 2E0: L1: 488BD3 MOV RDX, RBX
; 2E3: 4883EC10 SUB RSP, 16
; 2E7: 488975E0 MOV [RBP-32], RSI
; 2EB: 488B45F0 MOV RAX, [RBP-16]
; 2EF: B902000000 MOV ECX, 2
; 2F4: 48892C24 MOV [RSP], RBP
; 2F8: 488BEC MOV RBP, RSP
; 2FB: 8D58F5 LEA EBX, [RAX-11]
; 2FE: F6C30F TEST BL, 15
; 301: 7407 JEQ L2
; 303: BB1004B021 MOV EBX, #x21B00410 ; CALL-SYMBOL
; 308: FFD3 CALL RBX
; 30A: L2: FF50FD CALL QWORD PTR [RAX-3]
; 30D: 480F42E3 CMOVB RSP, RBX
; 311: 488B75E0 MOV RSI, [RBP-32]
; 315: 488BDA MOV RBX, RDX
; 318: 48895DD8 MOV [RBP-40], RBX
; 31C: BF02000000 MOV EDI, 2
; 321: 488BD6 MOV RDX, RSI
; 324: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 32A: 41FFD3 CALL R11
; 32D: 488B5DD8 MOV RBX, [RBP-40]
; 331: 488BF2 MOV RSI, RDX
; 334: L3: 48895DD8 MOV [RBP-40], RBX
; 338: 488975E0 MOV [RBP-32], RSI
; 33C: 488B7DE8 MOV RDI, [RBP-24]
; 340: 488BD6 MOV RDX, RSI
; 343: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; 348: FFD1 CALL RCX
; 34A: 488B75E0 MOV RSI, [RBP-32]
; 34E: 488B5DD8 MOV RBX, [RBP-40]
; 352: 7C8C JL L1
; 354: 488BD3 MOV RDX, RBX
; 357: 488BE5 MOV RSP, RBP
; 35A: F8 CLC
; 35B: 5D POP RBP
; 35C: C3 RET
; 35D: L4: 488B45E8 MOV RAX, [RBP-24]
; 361: CC53 BREAK 83 ; OBJECT-NOT-INTEGER-ERROR
; 363: 00 BYTE #X00 ; RAX
; 364: CC0F BREAK 15 ; Invalid argument count trap
;; type declarations for f and n
; Size: 132 bytes. Origin: #x1004C5078C
; 78C: 498B4C2458 MOV RCX, [R12+88] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; 791: 48894DF8 MOV [RBP-8], RCX
; 795: 31F6 XOR ESI, ESI
; 797: EB4C JMP L1
; 799: 0F1F8000000000 NOP
; 7A0: L0: 488BD3 MOV RDX, RBX
; 7A3: 4883EC10 SUB RSP, 16
; 7A7: 488975E0 MOV [RBP-32], RSI
; 7AB: 488B45F0 MOV RAX, [RBP-16]
; 7AF: B902000000 MOV ECX, 2
; 7B4: 48892C24 MOV [RSP], RBP
; 7B8: 488BEC MOV RBP, RSP
; 7BB: FF50FD CALL QWORD PTR [RAX-3]
; 7BE: 480F42E3 CMOVB RSP, RBX
; 7C2: 488B75E0 MOV RSI, [RBP-32]
; 7C6: 488BDA MOV RBX, RDX
; 7C9: 48895DD8 MOV [RBP-40], RBX
; 7CD: BF02000000 MOV EDI, 2
; 7D2: 488BD6 MOV RDX, RSI
; 7D5: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 7DB: 41FFD3 CALL R11
; 7DE: 488B5DD8 MOV RBX, [RBP-40]
; 7E2: 488BF2 MOV RSI, RDX
; 7E5: L1: 48895DD8 MOV [RBP-40], RBX
; 7E9: 488975E0 MOV [RBP-32], RSI
; 7ED: 488B7DE8 MOV RDI, [RBP-24]
; 7F1: 488BD6 MOV RDX, RSI
; 7F4: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; 7F9: FFD1 CALL RCX
; 7FB: 488B75E0 MOV RSI, [RBP-32]
; 7FF: 488B5DD8 MOV RBX, [RBP-40]
; 803: 7C9B JL L0
; 805: 488BD3 MOV RDX, RBX
; 808: 488BE5 MOV RSP, RBP
; 80B: F8 CLC
; 80C: 5D POP RBP
; 80D: C3 RET
; 80E: CC0F BREAK 15 ; Invalid argument count trap
;; substitute (funcall #'1+ x)
; Size: 135 bytes. Origin: #x1004C51088
; 088: 498B4C2458 MOV RCX, [R12+88] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; 08D: 48894DF8 MOV [RBP-8], RCX
; 091: 31F6 XOR ESI, ESI
; 093: EB4F JMP L1
; 095: 660F1F840000000000 NOP
; 09E: 6690 NOP
; 0A0: L0: 488BD3 MOV RDX, RBX
; 0A3: 4883EC10 SUB RSP, 16
; 0A7: 488975E8 MOV [RBP-24], RSI
; 0AB: 488B055EFFFFFF MOV RAX, [RIP-162] ; #<FUNCTION 1+>
; 0B2: B902000000 MOV ECX, 2
; 0B7: 48892C24 MOV [RSP], RBP
; 0BB: 488BEC MOV RBP, RSP
; 0BE: FF50FD CALL QWORD PTR [RAX-3]
; 0C1: 488B75E8 MOV RSI, [RBP-24]
; 0C5: 488BDA MOV RBX, RDX
; 0C8: 48895DE0 MOV [RBP-32], RBX
; 0CC: BF02000000 MOV EDI, 2
; 0D1: 488BD6 MOV RDX, RSI
; 0D4: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 0DA: 41FFD3 CALL R11
; 0DD: 488B5DE0 MOV RBX, [RBP-32]
; 0E1: 488BF2 MOV RSI, RDX
; 0E4: L1: 48895DE0 MOV [RBP-32], RBX
; 0E8: 488975E8 MOV [RBP-24], RSI
; 0EC: 488B7DF0 MOV RDI, [RBP-16]
; 0F0: 488BD6 MOV RDX, RSI
; 0F3: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; 0F8: FFD1 CALL RCX
; 0FA: 488B75E8 MOV RSI, [RBP-24]
; 0FE: 488B5DE0 MOV RBX, [RBP-32]
; 102: 7C9C JL L0
; 104: 488BD3 MOV RDX, RBX
; 107: 488BE5 MOV RSP, RBP
; 10A: F8 CLC
; 10B: 5D POP RBP
; 10C: C3 RET
; 10D: CC0F BREAK 15 ; Invalid argument count trap
;; substitute (1+ x)
; Size: 123 bytes. Origin: #x1004C51528
; 28: 498B4C2458 MOV RCX, [R12+88] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; 2D: 48894DF8 MOV [RBP-8], RCX
; 31: 31DB XOR EBX, EBX
; 33: EB43 JMP L1
; 35: 660F1F840000000000 NOP
; 3E: 6690 NOP
; 40: L0: 48895DE8 MOV [RBP-24], RBX
; 44: BF02000000 MOV EDI, 2
; 49: 498BD0 MOV RDX, R8
; 4C: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 52: 41FFD3 CALL R11
; 55: 488B5DE8 MOV RBX, [RBP-24]
; 59: 4C8BC2 MOV R8, RDX
; 5C: 4C8945E0 MOV [RBP-32], R8
; 60: BF02000000 MOV EDI, 2
; 65: 488BD3 MOV RDX, RBX
; 68: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 6E: 41FFD3 CALL R11
; 71: 4C8B45E0 MOV R8, [RBP-32]
; 75: 488BDA MOV RBX, RDX
; 78: L1: 4C8945E0 MOV [RBP-32], R8
; 7C: 48895DE8 MOV [RBP-24], RBX
; 80: 488B7DF0 MOV RDI, [RBP-16]
; 84: 488BD3 MOV RDX, RBX
; 87: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; 8C: FFD1 CALL RCX
; 8E: 488B5DE8 MOV RBX, [RBP-24]
; 92: 4C8B45E0 MOV R8, [RBP-32]
; 96: 7CA8 JL L0
; 98: 498BD0 MOV RDX, R8
; 9B: 488BE5 MOV RSP, RBP
; 9E: F8 CLC
; 9F: 5D POP RBP
; A0: C3 RET
; A1: CC0F BREAK 15 ; Invalid argument count trap
;; (declare (optimize (speed 3)))
; Size: 107 bytes. Origin: #x1004C51858
; 58: 31F6 XOR ESI, ESI ; no-arg-parsing entry point
; 5A: EB3C JMP L1
; 5C: 0F1F4000 NOP
; 60: L0: 488975F0 MOV [RBP-16], RSI
; 64: BF02000000 MOV EDI, 2
; 69: 488BD3 MOV RDX, RBX
; 6C: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 72: 41FFD3 CALL R11
; 75: 488B75F0 MOV RSI, [RBP-16]
; 79: 488BDA MOV RBX, RDX
; 7C: 48895DE8 MOV [RBP-24], RBX
; 80: BF02000000 MOV EDI, 2
; 85: 488BD6 MOV RDX, RSI
; 88: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 8E: 41FFD3 CALL R11
; 91: 488B5DE8 MOV RBX, [RBP-24]
; 95: 488BF2 MOV RSI, RDX
; 98: L1: 488975F0 MOV [RBP-16], RSI
; 9C: 48895DE8 MOV [RBP-24], RBX
; A0: 488B7DF8 MOV RDI, [RBP-8]
; A4: 488BD6 MOV RDX, RSI
; A7: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; AC: FFD1 CALL RCX
; AE: 488B5DE8 MOV RBX, [RBP-24]
; B2: 488B75F0 MOV RSI, [RBP-16]
; B6: 7CA8 JL L0
; B8: 488BD3 MOV RDX, RBX
; BB: 488BE5 MOV RSP, RBP
; BE: F8 CLC
; BF: 5D POP RBP
; C0: C3 RET
; C1: CC0F BREAK 15 ; Invalid argument count trap
;; declare x to also be an integer - somehow larger than when it wasn't??? (oh, and also remove the argument f)
; Size: 113 bytes. Origin: #x1004C529D2
; 9D2: 31F6 XOR ESI, ESI ; no-arg-parsing entry point
; 9D4: EB42 JMP L1
; 9D6: 660F1F840000000000 NOP
; 9DF: 90 NOP
; 9E0: L0: 488975F0 MOV [RBP-16], RSI
; 9E4: BF02000000 MOV EDI, 2
; 9E9: 488BD3 MOV RDX, RBX
; 9EC: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; 9F2: 41FFD3 CALL R11
; 9F5: 488B75F0 MOV RSI, [RBP-16]
; 9F9: 488BDA MOV RBX, RDX
; 9FC: 48895DE8 MOV [RBP-24], RBX
; A00: BF02000000 MOV EDI, 2
; A05: 488BD6 MOV RDX, RSI
; A08: 41BB7005B021 MOV R11D, #x21B00570 ; GENERIC-+
; A0E: 41FFD3 CALL R11
; A11: 488B5DE8 MOV RBX, [RBP-24]
; A15: 488BF2 MOV RSI, RDX
; A18: L1: 488975F0 MOV [RBP-16], RSI
; A1C: 48895DE8 MOV [RBP-24], RBX
; A20: 488B7DF8 MOV RDI, [RBP-8]
; A24: 488BD6 MOV RDX, RSI
; A27: B97007B021 MOV ECX, #x21B00770 ; GENERIC-<
; A2C: FFD1 CALL RCX
; A2E: 488B5DE8 MOV RBX, [RBP-24]
; A32: 488B75F0 MOV RSI, [RBP-16]
; A36: 7CA8 JL L0
; A38: 488BD3 MOV RDX, RBX
; A3B: 488BE5 MOV RSP, RBP
; A3E: F8 CLC
; A3F: 5D POP RBP
; A40: C3 RET
; A41: CC0F BREAK 15 ; Invalid argument count trap
;; declare n and x to be fixnum
; Size: 55 bytes. Origin: #x10030CCB21
; 21: 31D2 XOR EDX, EDX ; no-arg-parsing entry point
; 23: EB20 JMP L1
; 25: 660F1F840000000000 NOP
; 2E: 6690 NOP
; 30: L0: 48D1F8 SAR RAX, 1
; 33: 48FFC0 INC RAX
; 36: 488BC8 MOV RCX, RAX
; 39: 48D1E1 SHL RCX, 1
; 3C: 7015 JO L2
; 3E: 48D1E0 SHL RAX, 1
; 41: 4883C202 ADD RDX, 2
; 45: L1: 4839FA CMP RDX, RDI
; 48: 7CE6 JL L0
; 4A: 488BD0 MOV RDX, RAX
; 4D: 488BE5 MOV RSP, RBP
; 50: F8 CLC
; 51: 5D POP RBP
; 52: C3 RET
; 53: L2: CC47 BREAK 71 ; OBJECT-NOT-FIXNUM-ERROR
; 55: 02 BYTE #X02 ; RAX
; 56: CC0F BREAK 15 ; Invalid argument count trap
;; declare safety 0
; Size: 32 bytes. Origin: #x10030CCC49
; 49: 31C9 XOR ECX, ECX ; no-arg-parsing entry point
; 4B: EB0E JMP L1
; 4D: 0F1F00 NOP
; 50: L0: 488D4302 LEA RAX, [RBX+2]
; 54: 488BD8 MOV RBX, RAX
; 57: 4883C102 ADD RCX, 2
; 5B: L1: 4839F9 CMP RCX, RDI
; 5E: 7CF0 JL L0
; 60: 488BD3 MOV RDX, RBX
; 63: 488BE5 MOV RSP, RBP
; 66: F8 CLC
; 67: 5D POP RBP
; 68: C3 RET
;; final code:
(let ((f '1+))
(eval `(defun foo (x n)
"call f(f(f(...f(x)))) with f being called n times"
(declare (optimize (speed 3) (safety 0))
(type fixnum n)
(type fixnum x))
(dotimes (i n x)
(setf x (,f x))))))
@fouric
Copy link
Author

fouric commented Aug 26, 2019

What happens if we turn the loop + assign into a recursive call with a depth/count parameter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment