Tord Kallqvist Romstad <·······@math.uio.no> writes:
> I'm trying to get started using SBCL 0.9.11 on an Intel iMac (on my
> old Mac I used OpenMCL, which unfortunately doesn't run on Intel
> Macs). Section 5.2 of the SBCL manual shows a way to do fast 32-bit
> arithmetic with SBCL. The following function is given as an example:
>
> (defun i (x y)
> (declare (type (unsigned-byte 32) x y))
> (ldb (byte 32 0) (logxor x (lognot y))))
>
> According to the manual, this is supposed to compile to native 32-bit
> machine arithmetic on x86 CPUs. This sounds cool. The problem is
> that it doesn't seem to work:
It does, actually.
> CL-USER> (disassemble 'i)
> ; 11B65DDA: 8BC6 MOV EAX, ESI ; no-arg-parsing entry point
> ; DDC: F7D0 NOT EAX
> ; DDE: 8BCB MOV ECX, EBX
> ; DE0: 31C1 XOR ECX, EAX
This bit is the native 32-bit arithmetic: (lognot y) is the second
line, (logxor x <result>) is the fourth. By this stage, we have
computed the answer to your function. However...
> ; DE2: F7C1000000E0 TEST ECX, 3758096384
> ; DE8: 7522 JNE L1
> ; DEA: 8D148D00000000 LEA EDX, [ECX*4]
> ; DF1: L0: 8D65F8 LEA ESP, [EBP-8]
> ; DF4: F8 CLC
> ; DF5: 8B6DFC MOV EBP, [EBP-4]
> ; DF8: C20400 RET 4
This bit (and the consing sequence that I've snipped, down at L1) is
_returning_ the 32-bit value. The callee of I must get a tagged lisp
object back, rather than a raw 32-bit value; since (LOGXOR Y (LOGNOT
X)) can have any 32-bit value, the return sequence must test the raw
32-bit value to see if it fits in a fixnum, and otherwise must
allocate a bignum for it.
So, why is this useful? Well, if you're just calling your I function
on random input, it isn't; however, if you have slightly longer
arithmetic sequences, as are found in cryptographic or hashing
functions, or if you are storing the result of your short arithmetic
sequence into an array of results, then the inner loop or bottleneck
of the routine is made to take much less time than if the arithmetic
were generic.
Christophe
Christophe Rhodes <·····@cam.ac.uk> wrote:
> It does, actually.
>
>> CL-USER> (disassemble 'i)
>> ; 11B65DDA: 8BC6 MOV EAX, ESI ; no-arg-parsing entry point
>> ; DDC: F7D0 NOT EAX
>> ; DDE: 8BCB MOV ECX, EBX
>> ; DE0: 31C1 XOR ECX, EAX
>
> This bit is the native 32-bit arithmetic: (lognot y) is the second
> line, (logxor x <result>) is the fourth. By this stage, we have
> computed the answer to your function. However...
>
>> ; DE2: F7C1000000E0 TEST ECX, 3758096384
>> ; DE8: 7522 JNE L1
>> ; DEA: 8D148D00000000 LEA EDX, [ECX*4]
>> ; DF1: L0: 8D65F8 LEA ESP, [EBP-8]
>> ; DF4: F8 CLC
>> ; DF5: 8B6DFC MOV EBP, [EBP-4]
>> ; DF8: C20400 RET 4
>
> This bit (and the consing sequence that I've snipped, down at L1) is
> _returning_ the 32-bit value. The callee of I must get a tagged lisp object
> back, rather than a raw 32-bit value; since (LOGXOR Y (LOGNOT X)) can have
> any 32-bit value, the return sequence must test the raw 32-bit value to see
> if it fits in a fixnum, and otherwise must allocate a bignum for it.
This makes me think; what would be your advice to become familiar with
compiled lisp code disassembly and understanding (especially for somebody not
fluent at all in assembler) ? I'm aware of the page on this matter at the
CMUCL web site, but it is really short.
Thanks.
--
Didier Verna, ······@lrde.epita.fr, http://www.lrde.epita.fr/~didier
EPITA / LRDE, 14-16 rue Voltaire Tel.+33 (1) 44 08 01 85
94276 Le Kremlin-Bic�tre, France Fax.+33 (1) 53 14 59 22 ······@xemacs.org
Christophe Rhodes <·····@cam.ac.uk> writes:
> This bit (and the consing sequence that I've snipped, down at L1) is
> _returning_ the 32-bit value. The callee of I must get a tagged lisp
> object back, rather than a raw 32-bit value; since (LOGXOR Y (LOGNOT
> X)) can have any 32-bit value, the return sequence must test the raw
> 32-bit value to see if it fits in a fixnum, and otherwise must
> allocate a bignum for it.
I see. Thanks a lot for the explanation!
--
Tord Romstad