Re: SBCL tells me it is deleting unreachable code that is almost surely reachable

Stavros Macrakis <[email protected]>
Newsgroups gmane.comp.mathematics.maxima.general
Message-ID <CACLVabXNSEXh5=WstXMjSosvLoysoEw=ejyOSM+teC-HGTNozA@mail.gmail.com>
Sorry, this was muddled:

The *and *is so that we depend only on the boolean value, not the list
value of *member: *for example, *(member 'b '(a b c))* returns *(b c)*,
which then has to be tested to see whether it's* nil *in the function case,
and in the inline case, each conditional has to return a different value.


I meant

The *and *is so that we depend only on the boolean value, not the list
value of *member*. (Recall that, for example, *(member 'b '(a b c))*
 returns *(b c)*.)
When we're using *member* in a *cond*, all we care about is the truth
value, so the function case has the extra overhead of checking whether the
return value is non-nil.

The inline version doesn't have that overhead in the *cond* case, but it
has to do a little more work to return the full value of *member*.

This still feels convoluted as an explanation, but as Pascal said, "I have
made this letter longer than usual because I lack the time to make it
shorter."

On Wed, Apr 15, 2026 at 6:06 PM Stavros Macrakis <[email protected]> wrote:

> On Wed, Apr 15, 2026 at 4:07 PM Raymond Toy <[email protected]> wrote:
> ...
>
>> On 4/15/26 10:12 AM, Stavros Macrakis wrote:
>>
>> Looking at the generated code, I see that with *optimize speed:0 space:3*,
>> SBCL calls *member-eq*, even though that takes more space. Apparently it
>> uses an inaccurate heuristic to estimate space usage.
>>
>> Surely a simple function call to member-eq takes less space than inlining
>> 3 comparisons and branches
>>
>
> Sounds plausible, and presumably that's what the *space* heuristic is
> based on, but...
>
> Here's the test:
>
> (disassemble
>     (lambda (x)
>       (declare (optimize (space *X*) (speed *Y*)))
>       (and (member x '(a b c)) t)))
>
> The *and *is so that we depend only on the boolean value, not the list
> value of *member: *for example, *(member 'b '(a b c))* returns *(b c)*,
> which then has to be tested to see whether it's* nil *in the function
> case, and in the inline case, each conditional has to return a different
> value.
>
> In SBCL:
> With speed=3, and space=0, it inlines, and compiles to 47 bytes.
> With speed=3, and space=3, it inlines, and compiles to 47 bytes.
> With speed=0 and space=0, it inlines, and compiles to 55 bytes.
> With speed=0 and space=3, it calls *member*, and compiles to 66 bytes.
>
>              -s
>
> (%i1) :lisp (disassemble (lambda (x) (declare (optimize (space 0) (speed
> 3))) (and (member x '(a b c)) t)))
>
> ; disassembly for (LAMBDA (X))
> ; Size: 47 bytes. Origin: #x10013BADF0                        ; (LAMBDA
> (X))
> ; DF0:       4184442469
> <http://voice.google.com/calls?a=nc,%2B14184442469>
> <http://voice.google.com/calls?a=nc,%2B14184442469>     TEST AL,
> [R12+105]              ; safepoint
> ; DF5:       483B15B4FFFFFF   CMP RDX, [RIP-76]               ; 'A
> ; DFC:       7508             JNE L2
> ; DFE: L0:   498D542488       LEA RDX, [R12-120]              ; T
> ; E03: L1:   C9               LEAVE
> ; E04:       F8               CLC
> ; E05:       C3               RET
> ; E06: L2:   483B15ABFFFFFF   CMP RDX, [RIP-85]               ; 'B
> ; E0D:       74EF             JE L0
> ; E0F:       483B15AAFFFFFF   CMP RDX, [RIP-86]               ; 'C
> ; E16:       74E6             JE L0
> ; E18:       498BD4           MOV RDX, R12                    ; NIL
> ; E1B:       EBE6             JMP L1
> ; E1D:       CC0F             INT3 15                         ; Invalid
> argument count trap
> NIL
> (%i1) :lisp (disassemble (lambda (x) (declare (optimize (space 3) (speed
> 3))) (and (member x '(a b c)) t)))
>
> ; disassembly for (LAMBDA (X))
> ; Size: 47 bytes. Origin: #x10013BAE90                        ; (LAMBDA
> (X))
> ; 90:       4184442469       TEST AL, [R12+105]               ; safepoint
> ; 95:       483B15B4FFFFFF   CMP RDX, [RIP-76]                ; 'A
> ; 9C:       7508             JNE L2
> ; 9E: L0:   498D542488       LEA RDX, [R12-120]               ; T
> ; A3: L1:   C9               LEAVE
> ; A4:       F8               CLC
> ; A5:       C3               RET
> ; A6: L2:   483B15ABFFFFFF   CMP RDX, [RIP-85]                ; 'B
> ; AD:       74EF             JE L0
> ; AF:       483B15AAFFFFFF   CMP RDX, [RIP-86]                ; 'C
> ; B6:       74E6             JE L0
> ; B8:       498BD4           MOV RDX, R12                     ; NIL
> ; BB:       EBE6             JMP L1
> ; BD:       CC0F             INT3 15                          ; Invalid
> argument count trap
> NIL
> (%i1) :lisp (disassemble (lambda (x) (declare (optimize (space 0) (speed
> 0))) (and (member x '(a b c)) t)))
>
> ; disassembly for (LAMBDA (X))
> ; Size: 55 bytes. Origin: #x10013BAF34                        ; (LAMBDA
> (X))
> ; 34:       498B4510         MOV RAX, [R13+16]                ;
> thread.binding-stack-pointer
> ; 38:       488945F8         MOV [RBP-8], RAX
> ; 3C:       4184442469       TEST AL, [R12+105]               ; safepoint
> ; 41:       483B35A8FFFFFF   CMP RSI, [RIP-88]                ; 'A
> ; 48:       7508             JNE L2
> ; 4A: L0:   498D542488       LEA RDX, [R12-120]               ; T
> ; 4F: L1:   C9               LEAVE
> ; 50:       F8               CLC
> ; 51:       C3               RET
> ; 52: L2:   483B359FFFFFFF   CMP RSI, [RIP-97]                ; 'B
> ; 59:       74EF             JE L0
> ; 5B:       483B359EFFFFFF   CMP RSI, [RIP-98]                ; 'C
> ; 62:       74E6             JE L0
> ; 64:       498BD4           MOV RDX, R12                     ; NIL
> ; 67:       EBE6             JMP L1
> ; 69:       CC0F             INT3 15                          ; Invalid
> argument count trap
> NIL
> (%i1) :lisp (disassemble (lambda (x) (declare (optimize (space 3) (speed
> 0))) (and (member x '(a b c)) t)))
>
> ; disassembly for (LAMBDA (X))
> ; Size: 66 bytes. Origin: #x10013BAFD8                        ; (LAMBDA
> (X))
> ; AFD8:       498B4510         MOV RAX, [R13+16]              ;
> thread.binding-stack-pointer
> ; AFDC:       488945F8         MOV [RBP-8], RAX
> ; AFE0:       4184442469       TEST AL, [R12+105]             ; safepoint
> ; AFE5:       4883EC10         SUB RSP, 16
> ; AFE9:       498BD0           MOV RDX, R8
> ; AFEC:       488B3DADFFFFFF   MOV RDI, [RIP-83]              ; '(A B C)
> ; AFF3:       48892C24         MOV [RSP], RBP
> ; AFF7:       488BEC           MOV RBP, RSP
> ; AFFA:       498B442429       MOV RAX, [R12+41]              ;
> LISP-LINKAGE-TABLE
> ; AFFF:       FF9028070000     CALL [RAX+1832]                ;
> SB-KERNEL:%MEMBER
> ; B005:       4C8B45F0         MOV R8, [RBP-16]
> ; B009:       4C39E2           CMP RDX, R12                   ; NIL
> ; B00C:       498D542488       LEA RDX, [R12-120]             ; T
> ; B011:       490F44D4         CMOVE RDX, R12                 ; NIL
> ; B015:       C9               LEAVE
> ; B016:       F8               CLC
> ; B017:       C3               RET
> ; B018:       CC0F             INT3 15                        ; Invalid
> argument count trap
> NIL
>

_______________________________________________
Maxima-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/maxima-discuss
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.