Hi Brad,
Thank you for pointing it out - very funny.
I re-ran the test with varied compiler declares set, inspired by your test. In all cases was standard-bindings and extended-bindings on.
With safe off and interrupts off: The u8vector-ref fx+ etc are both inlined indeed, independent of if they're ##-prefixed or not. They generate equivalent C and assembly outputs. This is the same thing as your test shows.
So this is exactly the expected behavior, it's inlined, great.
Here comes something funny:
With safe is on and interrupts off: The only difference with the previous one in expansion, is that u8vector-length now (not ##-prefixed) now brings with it a u8vector? test call. And here's what's funny: it appears to me that each evaluation step is made by putting on the stack, together with the host procedure's state, an instruction for the respective procedure (##u8vector-ref ##fx+ etc.) to be invoked, and then the host procedure returns. In this mode, ##u8vector-ref ##fx+ etc. are not inlined. There seem to be some conditions that can make the host procedure not return, but I didn't quite understand until now what happens in those cases, i.e. if some kind of jump or call to ##u8vector-ref is made directly without a return being made or alike.
This is really funny, I though just using ##-prefixes on procedures was enough for exactly those calls to be executed with the highest speed, but apparently that was not the case. I'd be interested what the motivation for this is, perhaps some kind of safety mechanism for stack overflows??
Why can't ##u8vector-ref ##fx+ etc. be inlined, wouldn't that somehow contribute??
With safe off and interrupts on: Same as safe off and interrupts off, plus three interrupt checks.
With safe on and interrupts on: Same as safe on and interupts off, plus six interrupt checks.
Regarding the possibility of using ##u8vector-ref for accessing arbitrary memory addresses, I'm starting to think that clearly can be done, though the details would need to be worked out. A pure ##sysmem-byte-ref would be slightly faster though, as it would not need the operation of adding together the "zeroref-u8vector"'s base address (0) with the requested offset.
Best regards, Mikael
(In the assembly, highlighted the central loop with yellow. In the first test it's clear to me exactly which it is, in the second test it's only an approximate guess.)
*First test, safe off, using procedures under their ordinary names and by their ##-prefixed names respectively, both produce equivalent C and assembly output*
Code variant 1:
(declare (standard-bindings) (extended-bindings) (not interrupts-enabled) (not safe) )
(define (inc-u8v u with-what) (let ((l (u8vector-length u))) (##c-code "asm("noop");") (##c-code "asm("noop");") (let loop ((at 0)) (if (fx< at l) (begin (u8vector-set! u at (fx+ (u8vector-ref u at) 123)) (loop (fx+ at 1))))) (##c-code "asm("noop");") ))
Code variant 2:
(declare (standard-bindings) (extended-bindings) (not interrupts-enabled) (not safe) )
(define (inc-u8v u with-what) (let ((l (u8vector-length u))) (##c-code "asm("noop");") (##c-code "asm("noop");") (let loop ((at 0)) (if (##fx< at l) (begin (##u8vector-set! u at (##fx+ (##u8vector-ref u at) 123)) (loop (##fx+ at 1))))) (##c-code "asm("noop");") ))
Expansion:
(define inc-u8v (lambda (u with-what) (let ((l ('#<procedure #2 ##u8vector-length> u))) (let ((begin-temp.3 ('#<procedure #3 ##c-code> "asm("noop");"))) (let ((begin-temp.2 ('#<procedure #3 ##c-code> "asm("noop");"))) (let ((begin-temp.1 (letrec ((loop (lambda (u l at) (if ('#<procedure #4 ##fx<> at l) (let ((begin-temp.0 ('#<procedure #5 ##u8vector-set!> u at ('#<procedure #6 ##fx+> ('#<procedure #7 ##u8vector-ref> u at) 123)))) (loop u l ('#<procedure #6 ##fx+> at 1))) #!void)))) (loop u l 0)))) ('#<procedure #3 ##c-code> "asm("noop");")))))))
Assembly:
.file "t1.c" .intel_syntax .text .align 2 .type _Z12___init_procv, @function _Z12___init_procv: .LFB17: push %ebp .LCFI0: mov %ebp, %esp .LCFI1: mov %eax, DWORD PTR ___lp add %eax, 16 mov DWORD PTR ___G__20_t1, %eax mov %eax, DWORD PTR ___G__20_t1 mov DWORD PTR ___G__20_t1+4, %eax mov %eax, 0 pop %ebp ret .LFE17: .size _Z12___init_procv, .-_Z12___init_procv .globl __gxx_personality_v0 .align 2 .globl ____20_t1 .type ____20_t1, @function ____20_t1: .LFB18: push %ebp .LCFI2: mov %ebp, %esp .LCFI3: mov %eax, OFFSET FLAT:___module_descr pop %ebp ret .LFE18: .size ____20_t1, .-____20_t1 .align 2 .type _Z15___H_inc_2d_u8vP25___processor_state_struct, @function _Z15___H_inc_2d_u8vP25___processor_state_struct: .LFB16: push %ebp .LCFI4: mov %ebp, %esp .LCFI5: sub %esp, 60 .LCFI6: cmp DWORD PTR [%ebp+8], 0 sete %al movzx %eax, %al test %eax, %eax je .L6 mov DWORD PTR [%ebp-60], OFFSET FLAT:_ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl jmp .L8 .L6: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+24] mov DWORD PTR [%ebp-48], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+8] mov DWORD PTR [%ebp-44], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+36] mov DWORD PTR [%ebp-40], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+40] mov DWORD PTR [%ebp-36], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+44] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+48] mov DWORD PTR [%ebp-28], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+52] mov DWORD PTR [%ebp-24], %eax mov %eax, DWORD PTR ___lp add %eax, 48 mov DWORD PTR [%ebp-52], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+56] mov DWORD PTR [%ebp-56], %eax mov %eax, DWORD PTR [%ebp-56] add %eax, 7 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-20], %eax .L9: jmp [DWORD PTR [%ebp-20]] .L10: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+76] cmp %eax, 2 sete %al movzx %eax, %al test %eax, %eax jne .L11 mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-52] mov DWORD PTR [%eax+60], %edx mov %eax, DWORD PTR ___gstate+292 mov DWORD PTR [%ebp-56], %eax jmp .L13 .L11: mov %eax, DWORD PTR [%ebp-36] dec %eax mov %eax, DWORD PTR [%eax] shr %eax, 8 sal %eax, 2 mov DWORD PTR [%ebp-32], %eax #APP noop noop #NO_APP mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax], %edx mov DWORD PTR [%ebp-28], 0 mov %eax, DWORD PTR [%ebp-52] add %eax, 16 mov DWORD PTR [%ebp-40], %eax sub DWORD PTR [%ebp-44], 16 mov %edx, DWORD PTR [%ebp-32] cmp DWORD PTR [%ebp-28], %edx jge .L14 .L15: mov %eax, DWORD PTR [%ebp-28] sar %eax, 2 mov %edx, %eax mov %eax, DWORD PTR [%ebp-36] lea %eax, [%edx+%eax] add %eax, 3 movzx %eax, BYTE PTR [%eax] movzx %eax, %al sal %eax, 2 mov DWORD PTR [%ebp-24], %eax add DWORD PTR [%ebp-24], 492 mov %eax, DWORD PTR [%ebp-28] sar %eax, 2 mov %edx, %eax mov %eax, DWORD PTR [%ebp-36] lea %eax, [%edx+%eax] lea %edx, [%eax+3] mov %eax, DWORD PTR [%ebp-24] sar %eax, 2 mov BYTE PTR [%edx], %al add DWORD PTR [%ebp-28], 4 mov %eax, DWORD PTR [%ebp-32] cmp DWORD PTR [%ebp-28], %eax jl .L15 .L14: mov DWORD PTR [%ebp-36], -18 mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%ebp-56], %edx jmp .L16 .L17: #APP noop #NO_APP mov %eax, DWORD PTR [%ebp-4] mov DWORD PTR [%ebp-36], %eax add DWORD PTR [%ebp-44], 16 mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-56], %eax .L16: mov %eax, DWORD PTR [%ebp-56] add %eax, 11 mov %eax, DWORD PTR [%eax] cmp %eax, OFFSET FLAT:_Z15___H_inc_2d_u8vP25___processor_state_struct sete %al movzx %eax, %al test %eax, %eax je .L13 mov %eax, DWORD PTR [%ebp-56] add %eax, 7 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-20], %eax jmp .L9 .L13: mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-56] mov DWORD PTR [%eax+56], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-48] mov DWORD PTR [%eax+24], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-44] mov DWORD PTR [%eax+8], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax+36], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%eax+40], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-32] mov DWORD PTR [%eax+44], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-28] mov DWORD PTR [%eax+48], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-24] mov DWORD PTR [%eax+52], %edx mov %eax, DWORD PTR [%ebp-56] mov DWORD PTR [%ebp-60], %eax .L8: mov %eax, DWORD PTR [%ebp-60] leave ret .LFE16: .size _Z15___H_inc_2d_u8vP25___processor_state_struct, .-_Z15___H_inc_2d_u8vP25___processor_state_struct .align 2 .type _Z11___H__20_t1P25___processor_state_struct, @function _Z11___H__20_t1P25___processor_state_struct: .LFB15: push %ebp .LCFI7: mov %ebp, %esp .LCFI8: sub %esp, 20 .LCFI9: cmp DWORD PTR [%ebp+8], 0 sete %al movzx %eax, %al test %eax, %eax je .L21 mov DWORD PTR [%ebp-20], OFFSET FLAT:_ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl jmp .L23 .L21: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+36] mov DWORD PTR [%ebp-8], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+40] mov DWORD PTR [%ebp-4], %eax mov %eax, DWORD PTR ___lp add %eax, 16 mov DWORD PTR [%ebp-12], %eax .L24: .L25: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+76] test %eax, %eax sete %al movzx %eax, %al test %eax, %eax jne .L26 mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-12] mov DWORD PTR [%eax+60], %edx mov %eax, DWORD PTR ___gstate+292 mov DWORD PTR [%ebp-16], %eax jmp .L28 .L26: mov %eax, DWORD PTR [%ebp-12] add %eax, 32 mov DWORD PTR ___G_inc_2d_u8v, %eax mov DWORD PTR [%ebp-4], -18 mov %edx, DWORD PTR [%ebp-8] mov DWORD PTR [%ebp-16], %edx .L29: mov %eax, DWORD PTR [%ebp-16] add %eax, 11 mov %eax, DWORD PTR [%eax] cmp %eax, OFFSET FLAT:_Z11___H__20_t1P25___processor_state_struct sete %al movzx %eax, %al test %eax, %eax je .L28 jmp .L24 .L28: mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-16] mov DWORD PTR [%eax+56], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-4] mov DWORD PTR [%eax+40], %edx mov %eax, DWORD PTR [%ebp-16] mov DWORD PTR [%ebp-20], %eax .L23: mov %eax, DWORD PTR [%ebp-20] leave ret .LFE15: .size _Z11___H__20_t1P25___processor_state_struct, .-_Z11___H__20_t1P25___processor_state_struct .section .rodata .LC0: .string " t1" .data .align 32 .type ___module_descr, @object .size ___module_descr, 136 ___module_descr: .long 406002 .long 0 .long .LC0 .long 1 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long ___lp .long ___lbl_tbl .long 5 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long _Z12___init_procv .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .local ___lp .comm ___lp,4,4 .align 4 .type _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl, @object .size _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl, 16 _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl: .long 0 .long .L10 .long .L17 .long 0 .align 4 .type _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl, @object .size _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl, 12 _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl: .long 0 .long .L25 .long 0 .align 32 .type ___lbl_tbl, @object .size ___lbl_tbl, 96 ___lbl_tbl: .long 1030 .long -2 .long .LC0 .long 0 .long 118 .long 0 .long 0 .long _Z11___H__20_t1P25___processor_state_struct .long 2054 .long -2 .long 0 .long 0 .long 630 .long 0 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 4101 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 0 .long 0 .long 0 .long 0 .ident "GCC: (GNU) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)" .section .note.GNU-stack,"",@progbits
Second test, safe is on, using ##-prefixed procedure name variants
Code:
(declare (standard-bindings) (extended-bindings) (not interrupts-enabled) ; (not safe) )
(define (inc-u8v u with-what) (let ((l (u8vector-length u))) (##c-code "asm("noop");") (##c-code "asm("noop");") (let loop ((at 0)) (if (##fx< at l) (begin (##u8vector-set! u at (##fx+ (##u8vector-ref u at) 123)) (loop (##fx+ at 1))))) (##c-code "asm("noop");") ))
Expansion:
(define inc-u8v (lambda (u with-what) (let ((l (if ('#<procedure #2 ##u8vector?> u) ('#<procedure #3 ##u8vector-length> u) ('#<procedure #4 u8vector-length> u)))) (let ((begin-temp.3 ('#<procedure #5 ##c-code> "asm("noop");"))) (let ((begin-temp.2 ('#<procedure #5 ##c-code> "asm("noop");"))) (let ((begin-temp.1 (letrec ((loop (lambda (u l at) (if ('#<procedure #6 ##fx<> at l) (let ((begin-temp.0 ('#<procedure #7 ##u8vector-set!> u at ('#<procedure #8 ##fx+> ('#<procedure #9 ##u8vector-ref> u at) 123)))) (loop u l ('#<procedure #8 ##fx+> at 1))) #!void)))) (loop u l 0)))) ('#<procedure #5 ##c-code> "asm("noop");")))))))
Assembly:
.file "t1.c" .intel_syntax .text .align 2 .type _Z12___init_procv, @function _Z12___init_procv: .LFB17: push %ebp .LCFI0: mov %ebp, %esp .LCFI1: mov %eax, DWORD PTR ___lp add %eax, 16 mov DWORD PTR ___G__20_t1, %eax mov %eax, DWORD PTR ___G__20_t1 mov DWORD PTR ___G__20_t1+4, %eax mov %eax, 0 pop %ebp ret .LFE17: .size _Z12___init_procv, .-_Z12___init_procv .globl __gxx_personality_v0 .align 2 .globl ____20_t1 .type ____20_t1, @function ____20_t1: .LFB18: push %ebp .LCFI2: mov %ebp, %esp .LCFI3: mov %eax, OFFSET FLAT:___module_descr pop %ebp ret .LFE18: .size ____20_t1, .-____20_t1 .align 2 .type _Z15___H_inc_2d_u8vP25___processor_state_struct, @function _Z15___H_inc_2d_u8vP25___processor_state_struct: .LFB16: push %ebp .LCFI4: mov %ebp, %esp .LCFI5: sub %esp, 68 .LCFI6: cmp DWORD PTR [%ebp+8], 0 sete %al movzx %eax, %al test %eax, %eax je .L6 mov DWORD PTR [%ebp-68], OFFSET FLAT:_ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl jmp .L8 .L6: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+24] mov DWORD PTR [%ebp-48], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+8] mov DWORD PTR [%ebp-44], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+36] mov DWORD PTR [%ebp-40], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+40] mov DWORD PTR [%ebp-36], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+44] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+48] mov DWORD PTR [%ebp-28], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+52] mov DWORD PTR [%ebp-24], %eax mov %eax, DWORD PTR ___lp add %eax, 48 mov DWORD PTR [%ebp-56], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+56] mov DWORD PTR [%ebp-60], %eax mov %eax, DWORD PTR [%ebp-60] add %eax, 7 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-20], %eax .L9: jmp [DWORD PTR [%ebp-20]] .L10: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+76] cmp %eax, 2 sete %al movzx %eax, %al test %eax, %eax jne .L11 mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-56] mov DWORD PTR [%eax+60], %edx mov %eax, DWORD PTR ___gstate+292 mov DWORD PTR [%ebp-60], %eax jmp .L13 .L11: mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%ebp-52], %edx mov %eax, DWORD PTR [%ebp-52] and %eax, 3 cmp %eax, 1 jne .L14 mov %eax, DWORD PTR [%ebp-52] dec %eax mov %eax, DWORD PTR [%eax] and %eax, 248 cmp %eax, 168 je .L16 .L14: mov BYTE PTR [%ebp-61], 1 jmp .L17 .L16: mov BYTE PTR [%ebp-61], 0 .L17: movzx %eax, BYTE PTR [%ebp-61] test %al, %al jne .L18 mov %eax, DWORD PTR [%ebp-36] dec %eax mov %eax, DWORD PTR [%eax] shr %eax, 8 sal %eax, 2 mov DWORD PTR [%ebp-32], %eax jmp .L20 .L21: mov %eax, DWORD PTR [%ebp-36] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 24 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-36], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 28 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-40], %eax add DWORD PTR [%ebp-44], 32 .L20: #APP noop noop #NO_APP mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax], %edx mov DWORD PTR [%ebp-28], 0 mov %eax, DWORD PTR [%ebp-56] add %eax, 112 mov DWORD PTR [%ebp-40], %eax sub DWORD PTR [%ebp-44], 16 .L22: mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-44] sub %eax, 8 mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-44] sub %eax, 12 mov %edx, DWORD PTR [%ebp-32] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-44] sub %eax, 16 mov %edx, DWORD PTR [%ebp-28] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-28] mov DWORD PTR [%ebp-36], %eax mov %edx, DWORD PTR [%ebp-56] add %edx, 32 mov DWORD PTR [%ebp-40], %edx sub DWORD PTR [%ebp-44], 32 mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 2 mov %eax, DWORD PTR ___G__23__23_fx_3c_+4 mov DWORD PTR [%ebp-60], %eax jmp .L23 .L24: cmp DWORD PTR [%ebp-36], -2 je .L25 mov %eax, DWORD PTR [%ebp-44] add %eax, 16 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 24 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-36], %eax mov %edx, DWORD PTR [%ebp-56] add %edx, 48 mov DWORD PTR [%ebp-40], %edx mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 2 mov %eax, DWORD PTR ___G__23__23_u8vector_2d_ref+4 mov DWORD PTR [%ebp-60], %eax jmp .L23 .L27: mov DWORD PTR [%ebp-32], 492 mov %edx, DWORD PTR [%ebp-56] add %edx, 64 mov DWORD PTR [%ebp-40], %edx mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 2 mov %eax, DWORD PTR ___G__23__23_fx_2b_+4 mov DWORD PTR [%ebp-60], %eax jmp .L23 .L28: mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%ebp-28], %edx mov %eax, DWORD PTR [%ebp-44] add %eax, 16 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 24 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-36], %eax mov %eax, DWORD PTR [%ebp-56] add %eax, 80 mov DWORD PTR [%ebp-40], %eax mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 3 mov %edx, DWORD PTR ___G__23__23_u8vector_2d_set_21_+4 mov DWORD PTR [%ebp-60], %edx jmp .L23 .L29: mov %eax, DWORD PTR [%ebp-44] add %eax, 16 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-36], %eax mov DWORD PTR [%ebp-32], 4 mov %eax, DWORD PTR [%ebp-56] add %eax, 96 mov DWORD PTR [%ebp-40], %eax mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 2 mov %edx, DWORD PTR ___G__23__23_fx_2b_+4 mov DWORD PTR [%ebp-60], %edx jmp .L23 .L30: mov %eax, DWORD PTR [%ebp-36] mov DWORD PTR [%ebp-28], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 20 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-32], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 24 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-36], %eax mov %eax, DWORD PTR [%ebp-44] add %eax, 28 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-40], %eax add DWORD PTR [%ebp-44], 32 jmp .L22 .L25: mov DWORD PTR [%ebp-36], -18 add DWORD PTR [%ebp-44], 32 mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-60], %eax jmp .L23 .L31: #APP noop #NO_APP mov %edx, DWORD PTR [%ebp-4] mov DWORD PTR [%ebp-36], %edx add DWORD PTR [%ebp-44], 16 mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-60], %eax jmp .L23 .L18: mov %eax, DWORD PTR [%ebp-44] sub %eax, 4 mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-44] sub %eax, 8 mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%eax], %edx mov %eax, DWORD PTR [%ebp-56] add %eax, 16 mov DWORD PTR [%ebp-40], %eax sub DWORD PTR [%ebp-44], 32 mov %eax, DWORD PTR [%ebp+8] mov DWORD PTR [%eax+76], 1 mov %edx, DWORD PTR ___G_u8vector_2d_length+4 mov DWORD PTR [%ebp-60], %edx .L23: mov %eax, DWORD PTR [%ebp-60] add %eax, 11 mov %eax, DWORD PTR [%eax] cmp %eax, OFFSET FLAT:_Z15___H_inc_2d_u8vP25___processor_state_struct sete %al movzx %eax, %al test %eax, %eax je .L13 mov %eax, DWORD PTR [%ebp-60] add %eax, 7 mov %eax, DWORD PTR [%eax] mov DWORD PTR [%ebp-20], %eax jmp .L9 .L13: mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-60] mov DWORD PTR [%eax+56], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-48] mov DWORD PTR [%eax+24], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-44] mov DWORD PTR [%eax+8], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-40] mov DWORD PTR [%eax+36], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-36] mov DWORD PTR [%eax+40], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-32] mov DWORD PTR [%eax+44], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-28] mov DWORD PTR [%eax+48], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-24] mov DWORD PTR [%eax+52], %edx mov %eax, DWORD PTR [%ebp-60] mov DWORD PTR [%ebp-68], %eax .L8: mov %eax, DWORD PTR [%ebp-68] leave ret .LFE16: .size _Z15___H_inc_2d_u8vP25___processor_state_struct, .-_Z15___H_inc_2d_u8vP25___processor_state_struct .align 2 .type _Z11___H__20_t1P25___processor_state_struct, @function _Z11___H__20_t1P25___processor_state_struct: .LFB15: push %ebp .LCFI7: mov %ebp, %esp .LCFI8: sub %esp, 20 .LCFI9: cmp DWORD PTR [%ebp+8], 0 sete %al movzx %eax, %al test %eax, %eax je .L35 mov DWORD PTR [%ebp-20], OFFSET FLAT:_ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl jmp .L37 .L35: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+36] mov DWORD PTR [%ebp-8], %eax mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+40] mov DWORD PTR [%ebp-4], %eax mov %eax, DWORD PTR ___lp add %eax, 16 mov DWORD PTR [%ebp-12], %eax .L38: .L39: mov %eax, DWORD PTR [%ebp+8] mov %eax, DWORD PTR [%eax+76] test %eax, %eax sete %al movzx %eax, %al test %eax, %eax jne .L40 mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-12] mov DWORD PTR [%eax+60], %edx mov %eax, DWORD PTR ___gstate+292 mov DWORD PTR [%ebp-16], %eax jmp .L42 .L40: mov %eax, DWORD PTR [%ebp-12] add %eax, 32 mov DWORD PTR ___G_inc_2d_u8v, %eax mov DWORD PTR [%ebp-4], -18 mov %edx, DWORD PTR [%ebp-8] mov DWORD PTR [%ebp-16], %edx .L43: mov %eax, DWORD PTR [%ebp-16] add %eax, 11 mov %eax, DWORD PTR [%eax] cmp %eax, OFFSET FLAT:_Z11___H__20_t1P25___processor_state_struct sete %al movzx %eax, %al test %eax, %eax je .L42 jmp .L38 .L42: mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-16] mov DWORD PTR [%eax+56], %edx mov %eax, DWORD PTR [%ebp+8] mov %edx, DWORD PTR [%ebp-4] mov DWORD PTR [%eax+40], %edx mov %eax, DWORD PTR [%ebp-16] mov DWORD PTR [%ebp-20], %eax .L37: mov %eax, DWORD PTR [%ebp-20] leave ret .LFE15: .size _Z11___H__20_t1P25___processor_state_struct, .-_Z11___H__20_t1P25___processor_state_struct .section .rodata .LC0: .string " t1" .data .align 32 .type ___module_descr, @object .size ___module_descr, 136 ___module_descr: .long 406002 .long 0 .long .LC0 .long 1 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long ___lp .long ___lbl_tbl .long 11 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long _Z12___init_procv .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .local ___lp .comm ___lp,4,4 .align 32 .type _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl, @object .size _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl, 40 _ZZ15___H_inc_2d_u8vP25___processor_state_structE11___hlbl_tbl: .long 0 .long .L10 .long .L21 .long .L24 .long .L27 .long .L28 .long .L29 .long .L30 .long .L31 .long 0 .align 4 .type _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl, @object .size _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl, 12 _ZZ11___H__20_t1P25___processor_state_structE11___hlbl_tbl: .long 0 .long .L39 .long 0 .align 32 .type ___lbl_tbl, @object .size ___lbl_tbl, 192 ___lbl_tbl: .long 1030 .long -2 .long .LC0 .long 0 .long 118 .long 0 .long 0 .long _Z11___H__20_t1P25___processor_state_struct .long 8198 .long -2 .long 0 .long 0 .long 630 .long 0 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 12309 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 61461 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 61461 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 61461 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 61461 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 28693 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 3198 .long 4101 .long 0 .long _Z15___H_inc_2d_u8vP25___processor_state_struct .long 0 .long 0 .long 0 .long 0 .ident "GCC: (GNU) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)" .section .note.GNU-stack,"",@progbits
2012/8/9 Bradley Lucier lucier@math.purdue.edu
I don't know what you want to do, but this code:
(declare (standard-bindings) (extended-bindings) (not interrupts-enabled) (not safe))
(define (u8transfer in out) (do ((i (fx- (u8vector-length in) 1) (fx- i 1))) ((fx< i 0)) (u8vector-set! out i (u8vector-ref in i))))
expands to
[Bradley-Luciers-MacBook-Pro:~/Downloads] lucier% gsc -cc-options "-save-temps" -keep-c -expansion fxtest.scm Expansion:
(define u8transfer (lambda (in out) (letrec ((do-temp.0 (lambda (in out i) (if ('#<procedure #2 ##fx<> i 0) #!void (let ((begin-temp.1 ('#<procedure #3 ##u8vector-set!> out i ('#<procedure #4 ##u8vector-ref> in i)))) (do-temp.0 in out ('#<procedure #5 ##fx-> i 1))))))) (let ((i ('#<procedure #5 ##fx-> ('#<procedure #6 ##u8vector-length> in) 1))) (if ('#<procedure #2 ##fx<> i 0) #!void (let ((begin-temp.1 ('#<procedure #3 ##u8vector-set!> out i ('#<procedure #4 ##u8vector-ref> in i)))) (do-temp.0 in out ('#<procedure #5 ##fx-> i 1))))))))
and the inner loop is
L14: movq %rdx, %rax sarq $2, %rax subq $4, %rdx movzbl 7(%rsi,%rax), %ecx leaq 0(,%rcx,4), %r8 movb %cl, 7(%r9,%rax) jns L14
which seems to have about 1 extra instruction (I don't know what the load effective address is doing there).
Brad