[gambit-list] Guile's new compiler

Bradley Lucier lucier at math.purdue.edu
Thu Nov 5 17:21:53 EST 2015


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.



More information about the Gambit-list mailing list