new optimization compiles
This commit is contained in:
parent
3b39b890b9
commit
3906f165ff
BIN
lib/ikarus.boot
BIN
lib/ikarus.boot
Binary file not shown.
|
@ -1188,9 +1188,139 @@
|
|||
free (unparse prog)))
|
||||
prog))
|
||||
|
||||
(define (optimize-closures x)
|
||||
(define who 'optimize-closures)
|
||||
x)
|
||||
(define (optimize-closures/lift-codes x)
|
||||
(define who 'optimize-closures/lift-codes)
|
||||
(define all-codes '())
|
||||
(define (init-non-thunk var)
|
||||
(set-var-assigned! var #f)
|
||||
(set-var-referenced! var #f))
|
||||
(define (var-thunk var)
|
||||
(var-referenced var))
|
||||
(define (make-thunk-var var thunk)
|
||||
(set-var-referenced! var thunk))
|
||||
(define (thunk? x)
|
||||
(record-case x
|
||||
[(closure code free*)
|
||||
(null? free*)]
|
||||
[else #f]))
|
||||
(define (trim/lift-code code free*)
|
||||
(record-case code
|
||||
[(clambda-code label cls* free*/dropped)
|
||||
(let ([cls* (map
|
||||
(lambda (x)
|
||||
(record-case x
|
||||
[(clambda-case fml* proper body)
|
||||
(for-each init-non-thunk fml*)
|
||||
(make-clambda-case fml* proper
|
||||
(E body))]))
|
||||
cls*)])
|
||||
(let ([g (make-code-loc label)])
|
||||
(set! all-codes
|
||||
(cons (make-clambda-code label cls* free*) all-codes))
|
||||
g))]))
|
||||
(define (optimize-one-closure x)
|
||||
(record-case x
|
||||
[(closure code free*)
|
||||
(let ([free* (trim-vars free*)])
|
||||
(make-closure (trim/lift-code code free*) free*))]))
|
||||
(define (trim p? ls)
|
||||
(cond
|
||||
[(null? ls) '()]
|
||||
[(p? (car ls)) (trim p? (cdr ls))]
|
||||
[else
|
||||
(cons (car ls) (trim p? (cdr ls)))]))
|
||||
(define (trim-vars ls)
|
||||
(trim var-thunk ls))
|
||||
(define (trim-thunks ls)
|
||||
(trim thunk? ls))
|
||||
(define (do-bind lhs* rhs* body)
|
||||
(for-each init-non-thunk lhs*)
|
||||
(let ([rhs* (map E rhs*)])
|
||||
(for-each (lambda (x v)
|
||||
(when (thunk? v) (make-thunk-var x v)))
|
||||
lhs* rhs*)
|
||||
(make-bind (trim-vars lhs*) (trim-thunks rhs*) (E body))))
|
||||
(define (do-fix lhs* rhs* body)
|
||||
(for-each init-non-thunk lhs*)
|
||||
(let ([free** ;;; trim the free lists first; after init.
|
||||
(map (lambda (x) (trim-vars (closure-free* x))) rhs*)])
|
||||
(define-record node (name code deps whacked free))
|
||||
(let ([node* (map (lambda (lhs rhs)
|
||||
(let ([n (make-node lhs (closure-code rhs) '() #f '())])
|
||||
(make-thunk-var x n)
|
||||
n))
|
||||
lhs* rhs*)])
|
||||
;;; if x is free in y, then whenever x becomes a non-thunk,
|
||||
;;; y also becomes a non-thunk. Here, we mark these
|
||||
;;; dependencies.
|
||||
(for-each
|
||||
(lambda (my-node free*)
|
||||
(for-each (lambda (fvar)
|
||||
(cond
|
||||
[(var-thunk fvar) => ;;; one of ours
|
||||
(lambda (her-node)
|
||||
(set-node-deps! her-node
|
||||
(cons my-node (node-deps her-node))))]
|
||||
[else ;;; not one of ours
|
||||
(set-node-free! my-node
|
||||
(cons fvar (node-free my-node)))]))
|
||||
free*))
|
||||
node* free**)
|
||||
;;; Next, we go over the list of nodes, and if we find one
|
||||
;;; that has any free variables, we know it's a non-thunk,
|
||||
;;; so we whack it and add it to all of its dependents.
|
||||
(let ()
|
||||
(define (process-node x)
|
||||
(unless (null? (node-free x))
|
||||
(unless (node-whacked x)
|
||||
(set-node-whacked! x #t)
|
||||
(for-each
|
||||
(lambda (y)
|
||||
(set-node-free! y
|
||||
(cons (node-name x) (node-free y)))
|
||||
(process-node y))
|
||||
(node-deps x)))))
|
||||
(for-each process-node node*))
|
||||
;;; Now those that have free variables are actual closures.
|
||||
;;; Those with no free variables are actual thunks.
|
||||
(let ([rhs*
|
||||
(map
|
||||
(lambda (node)
|
||||
(let ([free (node-free node)])
|
||||
(let ([closure
|
||||
(make-closure (node-code node) free)])
|
||||
(if (null? free)
|
||||
(make-thunk-var (node-name node) closure)
|
||||
(init-non-thunk (node-name node)))
|
||||
closure)))
|
||||
node*)])
|
||||
(for-each
|
||||
(lambda (x)
|
||||
(set-closure-code! x
|
||||
(trim/lift-code (closure-code x))))
|
||||
rhs*)
|
||||
;;;
|
||||
(make-fix (trim-vars lhs*)
|
||||
(trim-thunks rhs*)
|
||||
(E body))))))
|
||||
(define (E x)
|
||||
(record-case x
|
||||
[(constant) x]
|
||||
[(var) (or (var-thunk x) x)]
|
||||
[(primref) x]
|
||||
[(bind lhs* rhs* body) (do-bind lhs* rhs* body)]
|
||||
[(fix lhs* rhs* body) (do-fix lhs* rhs* body)]
|
||||
[(conditional test conseq altern)
|
||||
(make-conditional (E test) (E conseq) (E altern))]
|
||||
[(seq e0 e1) (make-seq (E e0) (E e1))]
|
||||
[(closure c free) (optimize-one-closure c free)]
|
||||
[(primcall op rand*) (make-primcall op (map E rand*))]
|
||||
[(forcall op rand*) (make-forcall op (map E rand*))]
|
||||
[(funcall rator rand*) (make-funcall (E rator) (map E rand*))]
|
||||
[(appcall rator rand*) (make-appcall (E rator) (map E rand*))]
|
||||
[else (error who "invalid expression ~s" (unparse x))]))
|
||||
(let ([x (E x)])
|
||||
(make-codes all-codes x)))
|
||||
|
||||
(define (lift-codes x)
|
||||
(define who 'lift-codes)
|
||||
|
@ -3900,7 +4030,7 @@
|
|||
[p (copy-propagate p)]
|
||||
[p (rewrite-assignments p)]
|
||||
[p (convert-closures p)]
|
||||
[p (optimize-closures p)]
|
||||
;[p (optimize-closures p)]
|
||||
[p (lift-codes p)]
|
||||
[p (introduce-primcalls p)]
|
||||
[p (simplify-operands p)]
|
||||
|
|
Loading…
Reference in New Issue