On 11/05/2015 07:29 AM, Marc Feeley wrote:
You haven’t given the compiler much information to help it optimize…
Try:
(declare (standard-bindings))
(define (a x y) (map (lambda (c d) (+ c d)) x y))
It gives better inlining than (map + x y) . I haven’t looked into the details of why, but it is the transformations in gsc/_ptree2.scm that are involved in the inlining. Perhaps you could trace the code to see where the inlining is cut short.
Did you try this with Guile also to compare?
Well, the guile compiler takes this
(let ((string->chars (lambda (s) (define char-at (lambda (n) (string-ref s n))) (define len (lambda () (string-length s))) (let loop ((i 0)) (if (< i (len)) (cons (char-at i) (loop (+ 1 i))) '()))))) (string->chars "yo"))
and turns it into (compile-file "crap.scm" #:to 'assembly) $2 = "/home/lucier/.cache/guile/ccache/2.0-LE-8-2.0/home/lucier/Desktop/crap.scm.go"
which is
(load-program ((:LCASE341 . 2)) 16 (load-program () 66 #f (make-eol) (load-symbol "filename") (load-string "crap.scm") (cons) (make-int8:0) (make-int8 8) (make-int8:0) (cons) (cons) (make-int8 4) (make-int8 11) (make-int8 23) (cons) (cons) (make-int8 9) (make-int8 18) (make-int8 15) (cons) (cons) (list 0 4) (make-int8 2) (make-int8 10) (make-int8:0) (list 0 3) (list 0 1) (list 0 3) (return)) (assert-nargs-ee/locals 0) (make-char8 121) (make-char8 111) (list 0 2) (return) (nop) (nop) (nop) (nop) (nop) (nop))
(which is just constructing the list of characters '(#\y #\o))
Even after adding
(declare (standard-bindings) (fixnum) (not safe) (inlining-limit 1000))
Gambit does
firefly:~/Desktop> gsc -c -expansion crap Expansion:
(let ((s "yo")) (letrec ((loop (lambda (s i) (if ('#<procedure #2 ##fx<> i ('#<procedure #3 ##string-length> s)) ('#<procedure #4 ##cons> ('#<procedure #5 ##string-ref> s i) (let ((i ('#<procedure #6 ##fx+> 1 i))) (if ('#<procedure #2 ##fx<> i ('#<procedure #3 ##string-length> s)) ('#<procedure #4 ##cons> ('#<procedure #5 ##string-ref> s i) (let ((i ('#<procedure #6 ##fx+> 1 i))) (if ('#<procedure #2 ##fx<> i ('#<procedure #3 ##string-length> s)) ('#<procedure #4 ##cons> ('#<procedure #5 ##string-ref> s i) (let ((i ('#<procedure #6 ##fx+> 1 i))) (if ('#<procedure #2 ##fx<> i ('#<procedure #3 ##string-length> s)) ('#<procedure #4 ##cons> ('#<procedure #5 ##string-ref> s i) (loop s ('#<procedure #6 ##fx+> 1 i))) '()))) '()))) '()))) '())))) (loop s 0)))
I.e., it never pulls that argument into the closure.