Skip to content

(member x '(a b c)) uses eql test instead of eq #533

Description

@TomasRiker

As a simple performance optimization, calling member with a list of symbols should always use eq as the test (better performance), but CCL uses eql. The following example shows how the functions f (using just member) and g (using :test #'eq) are compiled differently.

? (defun f (x) (member x '(a b c)))
F
? (defun g (x) (member x '(a b c) :test #'eq))
G
? (disassemble 'f)
;;; (defun f (x) (member x '(a b c)))
    (recover-fn-from-rip)                   ;     [0]
    (cmpl ($ 8) (% nargs))                  ;     [7]
    (jne L53)                               ;    [10]
    (pushq (% rbp))                         ;    [12]
    (movq (% rsp) (% rbp))                  ;    [13]
    (pushq (% arg_z))                       ;    [16]

;;; (member x '(a b c))
    (movq (@ -8 (% rbp)) (% arg_y))         ;    [17]

;;; '(a b c)
    (movq (@ '(A B C) (% fn)) (% arg_z))    ;    [21]

;;; (member x '(a b c))
    (movl ($ 16) (% nargs))                 ;    [28]
    (movq (@ 'CCL::MEMEQL (% fn)) (% temp0)) ;    [33]
    (movq (% rbp) (% rsp))                  ;    [40]
    (popq (% rbp))                          ;    [43]
    (jmpq (@ 10 (% temp0)))                 ;    [44]

;;; #<no source text>

    (:align 2)
L53                                         ;   [@68]
    (uuo-error-wrong-number-of-args)        ;    [53]
NIL
? (disassemble 'g)
;;; (defun g (x) (member x '(a b c) :test #'eq))
    (recover-fn-from-rip)                   ;     [0]
    (cmpl ($ 8) (% nargs))                  ;     [7]
    (jne L97)                               ;    [10]
    (pushq (% rbp))                         ;    [12]
    (movq (% rsp) (% rbp))                  ;    [13]
    (pushq (% arg_z))                       ;    [16]

;;; '(a b c)
    (pushq (@ '(A B C) (% fn)))             ;    [17]

;;; (member x '(a b c) :test #'eq)
    (jmp L74)                               ;    [24]
L26                                         ;   [@41]
    (movq (@ -16 (% rbp)) (% arg_z))        ;    [26]
    (movl (% arg_z.l) (% imm0.l))           ;    [30]
    (andl ($ 7) (% imm0.l))                 ;    [32]
    (cmpl ($ 3) (% imm0.l))                 ;    [35]
    (jne L105)                              ;    [38]
    (movq (@ 5 (% arg_z)) (% arg_y))        ;    [40]
    (movq (@ -8 (% rbp)) (% arg_x))         ;    [44]
    (cmpq (% arg_x) (% arg_y))              ;    [48]
    (jne L62)                               ;    [51]
    (movq (@ -16 (% rbp)) (% arg_z))        ;    [53]
    (movq (% rbp) (% rsp))                  ;    [57]
    (popq (% rbp))                          ;    [60]
    (retq)                                  ;    [61]
L62                                         ;   [@77]
    (movq (@ -16 (% rbp)) (% arg_z))        ;    [62]
    (movq (@ -3 (% arg_z)) (% arg_z))       ;    [66]
    (movq (% arg_z) (@ -16 (% rbp)))        ;    [70]
L74                                         ;   [@89]
    (cmpb ($ 11) (@ -16 (% rbp)))           ;    [74]
    (jne L26)                               ;    [78]
    (movl ($ #x1300B) (% arg_z.l))          ;    [80]
    (movq (% rbp) (% rsp))                  ;    [85]
    (popq (% rbp))                          ;    [88]
    (retq)                                  ;    [89]

;;; #<no source text>

    (:align 4)
L97                                         ;  [@112]
    (uuo-error-wrong-number-of-args)        ;    [97]

    (:align 3)
L105                                        ;  [@120]
    (uuo-error-reg-not-list (% arg_z))      ;   [105]
NIL

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions