~ chicken-core (chicken-5) 41890ee45f03911e9f26730fcb1843c6776ebafd
commit 41890ee45f03911e9f26730fcb1843c6776ebafd
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Tue Mar 22 12:38:39 2011 +0100
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Tue Mar 22 12:38:39 2011 +0100
DIE, lambda-lift, DIE!!!
diff --git a/batch-driver.scm b/batch-driver.scm
index ecabddee..0946f4ce 100644
--- a/batch-driver.scm
+++ b/batch-driver.scm
@@ -184,7 +184,6 @@
(not a-only))
(set! all-import-libraries #t))
(set! enable-module-registration (not (memq 'no-module-registration options)))
- (when (memq 'lambda-lift options) (set! do-lambda-lifting #t))
(when (memq 'scrutinize options)
(set! do-scrutinize #t))
(when (memq 't debugging-chicken) (##sys#start-timer))
@@ -543,20 +542,6 @@
(end-time "scrutiny")
(set! first-analysis #t) ) )
- ;; lambda-lifting
- (when do-lambda-lifting
- (begin-time)
- (unless do-scrutinize ; no need to do analysis if already done above
- (set! first-analysis #f)
- (set! db (analyze 'lift node0))
- (print-db "analysis" '|0| db 0)
- (end-time "pre-analysis (lambda-lift)"))
- (begin-time)
- (perform-lambda-lifting! node0 db)
- (end-time "lambda lifting")
- (print-node "lambda lifted" '|L| node0)
- (set! first-analysis #t) )
-
(set! ##sys#line-number-database #f)
(set! constant-table #f)
(set! inline-table #f)
diff --git a/c-platform.scm b/c-platform.scm
index c1074bef..cc1e8f48 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -84,7 +84,7 @@
check-syntax to-stdout no-usual-integrations case-insensitive no-lambda-info
profile inline keep-shadowed-macros ignore-repository
fixnum-arithmetic disable-interrupts optimize-leaf-routines
- lambda-lift compile-syntax tag-pointers accumulate-profile
+ compile-syntax tag-pointers accumulate-profile
disable-stack-overflow-checks raw
emit-external-prototypes-first release local inline-global
analyze-only dynamic scrutinize no-argc-checks no-procedure-checks
diff --git a/chicken.scm b/chicken.scm
index efe52fb1..fa65cbea 100644
--- a/chicken.scm
+++ b/chicken.scm
@@ -100,7 +100,7 @@
(when (>= level 5)
(set! options
(cons* 'disable-interrupts 'no-trace 'unsafe 'block
- 'optimize-leaf-routines 'lambda-lift 'no-lambda-info
+ 'optimize-leaf-routines 'no-lambda-info
'inline 'inline-global 'unboxing
options) ) ) ) )
(loop (cdr rest)) ) )
diff --git a/compiler-namespace.scm b/compiler-namespace.scm
index d4fa6b56..b158a2dd 100644
--- a/compiler-namespace.scm
+++ b/compiler-namespace.scm
@@ -97,7 +97,6 @@
display-analysis-database
display-line-number-database
display-real-name-table
- do-lambda-lifting
do-scrutinize
dump-defined-globals
dump-global-refs
@@ -219,7 +218,6 @@
perform-cps-conversion
perform-high-level-optimizations
perform-inlining!
- perform-lambda-lifting!
perform-pre-optimization!
perform-unboxing!
posq
diff --git a/compiler.scm b/compiler.scm
index 0ba5b4a0..e838c399 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -57,7 +57,6 @@
; (hide {<name>})
; (inline-limit <limit>)
; (keep-shadowed-macros)
-; (lambda-lift)
; (no-argc-checks)
; (no-bound-checks)
; (no-procedure-checks)
@@ -321,7 +320,6 @@
(define disable-stack-overflow-checking #f)
(define require-imports-flag #f)
(define external-protos-first #f)
-(define do-lambda-lifting #f)
(define inline-max-size default-inline-max-size)
(define emit-closure-info #t)
(define undefine-shadowed-macros #t)
@@ -1413,7 +1411,6 @@
(for-each export-variable syms)))
((emit-external-prototypes-first)
(set! external-protos-first #t) )
- ((lambda-lift) (set! do-lambda-lifting #t))
((inline)
(if (null? (cdr spec))
(set! inline-locally #t)
diff --git a/csc.scm b/csc.scm
index 92edb166..1ace6844 100644
--- a/csc.scm
+++ b/csc.scm
@@ -132,7 +132,7 @@
'(-explicit-use -no-trace -no-warnings -no-usual-integrations -optimize-leaf-routines -unsafe
-block -disable-interrupts -fixnum-arithmetic -to-stdout -profile -raw -accumulate-profile
-check-syntax -case-insensitive -shared -compile-syntax -no-lambda-info
- -lambda-lift -dynamic -disable-stack-overflow-checks -local
+ -dynamic -disable-stack-overflow-checks -local
-emit-external-prototypes-first -inline -release -scrutinize
-analyze-only -keep-shadowed-macros -inline-global -ignore-repository
-no-symbol-escape -no-parentheses-synonyms -r5rs-syntax
@@ -364,7 +364,6 @@ Usage: #{csc} FILENAME | OPTION ...
-b -block enable block-compilation
-disable-interrupts disable interrupts in compiled code
-f -fixnum-arithmetic assume all numbers are fixnums
- -lambda-lift perform lambda-lifting
-disable-stack-overflow-checks disables detection of stack-overflows
-inline enable inlining
-inline-limit LIMIT set inlining threshold
diff --git a/manual/Declarations b/manual/Declarations
index ee7e350a..e73f43e2 100644
--- a/manual/Declarations
+++ b/manual/Declarations
@@ -161,13 +161,6 @@ Normally, when a toplevel variable is assigned or defined that has the same name
will be removed (in addition to showing a warning). This declaration will disable the removal of the macro.
-=== lambda-lift
-
- [declaration specifier] (lambda-lift)
-
-Enables lambda-lifting (equivalent to the {{-lambda-lift}} option).
-
-
=== local
[declaration specifier] (local)
diff --git a/manual/Using the compiler b/manual/Using the compiler
index 45374e52..00d8c079 100644
--- a/manual/Using the compiler
+++ b/manual/Using the compiler
@@ -41,7 +41,6 @@ the source text should be read from standard input.
s show program-size information and other statistics
a show node-matching during simplification
p show execution of compiler sub-passes
- l show lambda-lifting information
m show GC statistics during compilation
n print the line-number database
c print every expression before macro-expansion
@@ -50,10 +49,8 @@ the source text should be read from standard input.
x display information about experimental features
D when printing nodes, use node-tree output
N show the real-name mapping table
- 0 show database before lambda-lifting pass
S show applications of compiler syntax
T show expressions after converting to node tree
- L show expressions after lambda-lifting
U show expressions after unboxing
M show syntax-/runtime-requirements
1 show source expressions
@@ -120,8 +117,6 @@ the source text should be read from standard input.
; -keep-shadowed-macros : Do not remove macro definitions with the same name as assigned toplevel variables (the default is to remove the macro definition).
-; -lambda-lift : Enable the optimization known as lambda-lifting.
-
; -local : Assume toplevel variables defined in the current compilation unit are not externally modified. This gives the compiler more opportunities for inlining. Note that this may result in counter-intuitive and non-standard behaviour: an asssignment to an exported toplevel variable executed in a different compilation unit or in evaluated code will possibly not be seen by code executing in the current compilation unit.
; -module : wraps the compiled code in an implicit module named {{main}}, importing the {{scheme}} and {{chicken}} modules.
@@ -162,7 +157,7 @@ the source text should be read from standard input.
-optimize-level 2 is equivalent to -optimize-leaf-routines -inline -unboxing
-optimize-level 3 is equivalent to -optimize-leaf-routines -local -inline -inline-global -unboxing
-optimize-level 4 is equivalent to -optimize-leaf-routines -local -inline -inline-global -unboxing -unsafe
- -optimize-level 5 is equivalent to -optimize-leaf-routines -block -inline -inline-global -unsafe -unboxing -lambda-lift -disable-interrupts -no-trace -no-lambda-info
+ -optimize-level 5 is equivalent to -optimize-leaf-routines -block -inline -inline-global -unsafe -unboxing -disable-interrupts -no-trace -no-lambda-info
; -output-file FILENAME : Specifies the pathname of the generated C file. Default is {{FILENAME.c}}.
diff --git a/optimizer.scm b/optimizer.scm
index 68c2b0df..779c47ee 100644
--- a/optimizer.scm
+++ b/optimizer.scm
@@ -1481,367 +1481,3 @@
(debugging 'p "direct leaf routine optimization pass...")
(walk #f node #f)
dirty) )
-
-
-;;; Lambda lift:
-;
-; - Find lambda-liftable local procedures and lift them to toplevel.
-; - Pass free variables as extra parameters, including the free variables of
-; other lifted procedures. This implies that lifted procedures that call each
-; other have to be in the same scope.
-; - Declare the lifted procedures (effectively) as bound-to-procedure and block-global.
-
-(define (perform-lambda-lifting! node db)
- (let ([lambda-values '()]
- [eliminated '()] )
-
- (define (find-lifting-candidates)
- ;; Collect potentially liftable procedures and return as a list of (<name> . <value>) pairs:
- ;; - Also build a-list that maps lambda-nodes to names.
- (let ((cs '()))
- (##sys#hash-table-for-each
- (lambda (sym plist)
- (and-let* ((val (assq 'value plist))
- (refs (assq 'references plist))
- (css (assq 'call-sites plist)) )
- (let ((nrefs (length (cdr refs))))
- (when (and (not (assq 'unknown plist))
- (eq? 'lambda (node-class (cdr val)))
- (not (assq 'global plist))
- #;(> nrefs 1)
- (= nrefs (length (cdr css))) )
- (set! lambda-values (alist-cons (cdr val) sym lambda-values))
- (set! cs (alist-cons sym (cdr val) cs)) ) ) ) )
- db)
- cs) )
-
- (define (build-call-graph cs)
- ;; Build call-graph of the form ((<name> (<free1> ...) <called1> ...) ...):
- (let ([g '()]
- [free '()]
- [called '()] )
-
- (define (walk n env)
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(##core#variable set!)
- (let ([var (first params)])
- (unless (or (memq var env) (get db var 'global))
- (set! free (cons var free)) )
- (when (assq var cs) (set! called (cons var called)))
- (for-each (lambda (n) (walk n env)) subs) ) ]
- [(let)
- (let loop ([vars params] [vals subs])
- (if (null? vars)
- (walk (car vals) (append params env))
- (let ([var (car vars)])
- (walk (car vals) env)
- (loop (cdr vars) (cdr vals)) ) ) ) ]
- [(lambda)
- (decompose-lambda-list
- (first params)
- (lambda (vars argc rest) (walk (first subs) (append vars env))) ) ]
- [else (for-each (lambda (n) (walk n env)) subs)] ) ) )
-
- (for-each
- (lambda (cs)
- (let* ([here (car cs)]
- [lval (cdr cs)]
- [llist (car (node-parameters lval))] )
- (set! free '())
- (set! called '())
- (decompose-lambda-list
- llist
- (lambda (vars arg rest)
- (walk (car (node-subexpressions lval)) vars) ) )
- (set! g (alist-cons here (cons free called) g)) ) )
- cs)
- g) )
-
- (define (eliminate cs graph)
- ;; Eliminate all liftables that have free variables that are assigned to (and are not liftable),
- ;; or that have more than N free variables (including free variables of called liftables):
- (remove
- (lambda (gn)
- (or (> (count-free-variables (car gn) graph) maximal-number-of-free-variables-for-liftable)
- (any (lambda (v)
- (and (get db v 'assigned)
- (not (assq v cs)) ) )
- (second gn) ) ) )
- graph) )
-
- (define (count-free-variables name graph)
- (let ([gnames (unzip1 graph)])
- (let count ([n name] [walked '()])
- (let* ([a (assq n graph)]
- [cs (lset-difference eq? (cddr a) walked gnames)]
- [f (length (delete-duplicates (second a) eq?))]
- [w2 (cons n (append cs walked))] )
- (fold + f (map (lambda (c) (count c w2)) cs)) ) ) ) )
-
- (define (collect-accessibles graph)
- ;; Collect accessible variables for each liftable into list of the form (<name> <accessible1> ...):
- (let ([al '()])
- (let walk ([n node] [vars '()])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(##core#variable quote ##core#undefined ##core#primitive ##core#proc) #f]
- [(let)
- (let loop ([vars2 params] [vals subs])
- (if (null? vars2)
- (walk (car vals) (append params vars))
- (begin
- (walk (car vals) vars)
- (loop (cdr vars2) (cdr vals)) ) ) ) ]
- [(lambda)
- (let ([lval (assq n lambda-values)])
- (when lval
- (let ([name (cdr lval)])
- (when (assq name graph)
- (set! al (alist-cons (cdr lval) vars al))) ) ) )
- (decompose-lambda-list
- (first params)
- (lambda (vars2 argc rest)
- (walk (car subs) (append vars2 vars)) ) ) ]
- [else
- (for-each (lambda (n) (walk n vars)) subs) ] ) ) )
- al) )
-
- (define (eliminate2 graph al)
- ;; Eliminate liftables that have call-sites without access to all free variables;
- (remove
- (lambda (gn)
- (let* ([name (first gn)]
- [free (second gn)] )
- (any (lambda (gn2)
- (and (memq name (cddr gn2)) ; callee?
- (lset<= eq? (cdr (assq (car gn2) al)) free) ) )
- graph) ) )
- graph) )
-
- (define (eliminate3 graph)
- ;; Eliminate liftables that call other eliminated liftables:
- ;; - repeat until nothing changes.
- (let loop ([graph graph] [n (length graph)])
- (let* ([g2 (filter (lambda (gn) (every (lambda (n) (assq n graph)) (cddr gn))) graph)]
- [n2 (length g2)] )
- (if (= n n2)
- g2
- (loop g2 n2) ) ) ) )
-
- (define (eliminate4 graph)
- ;; Eliminate liftables that have unknown call-sites which do not have access to
- ;; any of the free variables of all callees:
- (let walk ([n node] [vars '()])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(##core#variable quote ##core#undefined ##core#primitive ##core#proc) #f]
- [(let)
- (let loop ([vars2 params] [vals subs])
- (if (null? vars2)
- (walk (car vals) (append params vars))
- (begin
- (walk (car vals) vars)
- (loop (cdr vars2) (cdr vals)) ) ) ) ]
- [(lambda)
- (decompose-lambda-list
- (first params)
- (lambda (vars2 argc rest)
- (walk (car subs) (append vars2 vars)) ) ) ]
- [(##core#call)
- (let ([fn (first subs)])
- (call-with-current-continuation
- (lambda (return)
- (when (eq? '##core#variable (node-class fn))
- (let ([done '()])
- (let loop ([name (first (node-parameters fn))])
- (unless (memq name done)
- (set! done (cons name done))
- (let ([gn (assq name graph)])
- (when gn
- (unless (lset<= eq? (second gn) vars)
- #;(print "*** " (first (node-parameters fn)) " | " name ": " vars " / " (second gn))
- (set! graph (delete! gn graph eq?))
- (return #f) )
- (for-each loop (cddr gn)) ) ) ) ) ) ) ) )
- (for-each (lambda (n) (walk n vars)) subs) ) ]
- [else (for-each (lambda (n) (walk n vars)) subs)] ) ) )
- graph)
-
- (define (compute-extra-variables graph)
- ;; Gather variables that have to be passed additionally:
- ;; - do not pass variables that are defined inside the body of a liftable.
- (define (defined n)
- (let ([defd '()])
- (let walk ([n n])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(let)
- (set! defd (append params defd))
- (for-each walk subs) ]
- [(lambda)
- (decompose-lambda-list
- (first params)
- (lambda (vars argc rest)
- (set! defd (append vars defd))
- (walk (first subs)) ) ) ]
- [else (for-each walk subs)] ) ) )
- defd) )
- (let ([extras (map (lambda (gn) (cons (first gn) (second gn))) graph)]
- [walked '()] )
- (define (walk gn)
- (let ([name (car gn)])
- ;; Hm. To handle liftables that are called recursively (but indirect) I use this kludge. Is it safe?
- (unless (> (count (cut eq? name <>) walked) 1)
- (set! walked (cons name walked))
- (let ([callees (cddr gn)])
- (for-each (lambda (c) (walk (assq c graph))) callees)
- (let ([f (assq name extras)])
- (set-cdr! f (append (cdr f) (concatenate (map (lambda (n2) (cdr (assq n2 extras))) callees)))) ) ) ) ) )
- (for-each walk graph)
- (map (lambda (xt)
- (let* ([name (car xt)]
- [defd (defined (get db name 'value))] )
- (cons name
- (remove
- (lambda (v)
- (or (assq v graph)
- (memq v defd) ) )
- (delete-duplicates (cdr xt) eq?)) ) ) )
- extras) ) )
-
- (define (reconstruct! graph extra)
- ;; Reconstruct node tree by adding global definitions:
- (node-subexpressions-set!
- node
- (list
- (fold-right
- (lambda (gn body)
- (let* ([name (car gn)]
- [lval (get db name 'value)] )
- (hide-variable name)
- (decompose-lambda-list
- (first (node-parameters lval))
- (lambda (vars argc rest)
- (let* ([xvars (cdr (assq name extra))]
- [xaliases (map gensym xvars)]
- [xmap (map cons xvars xaliases)] )
- (rename-extra-variables! (first (node-subexpressions lval)) xmap)
- (make-node
- 'let (list (gensym 't))
- (list (make-node
- 'set! (list name)
- (list
- (make-node
- 'lambda
- (list (build-lambda-list (append xaliases vars) (+ argc (length xvars)) rest))
- (node-subexpressions lval) ) ) )
- body) ) ) ) ) ) )
- (first (node-subexpressions node))
- graph) ) ) )
-
- (define (rename-extra-variables! node xmap)
- ;; Rename variables from a given map:
- (define (rename v)
- (let ([a (assq v xmap)])
- (if a (cdr a) v) ) )
- (let walk ([n node])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(let)
- (node-parameters-set! n (map rename params))
- (for-each walk subs) ]
- [(##core#variable)
- (node-parameters-set! n (list (rename (first params)))) ]
- [(set!)
- (node-parameters-set! n (list (rename (first params))))
- (for-each walk subs) ]
- [(lambda)
- (decompose-lambda-list
- (first params)
- (lambda (vars argc rest)
- (set-car! params (build-lambda-list (map rename vars) argc rest))
- (walk (first subs)) ) ) ]
- [else (for-each walk subs)] ) ) ) )
-
- (define (extend-call-sites! extra)
- ;; Change call sites by adding extra variables:
- (let walk ([n node])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(##core#call)
- (let ([fn (first subs)])
- (when (eq? '##core#variable (node-class fn))
- (let ([a (assq (first (node-parameters fn)) extra)])
- (when a
- (set-car! params #t)
- (node-subexpressions-set!
- n
- (cons fn (append (map varnode (cdr a)) (cdr subs))) ) ) ) )
- (for-each walk (node-subexpressions n)) ) ]
- [else (for-each walk subs)] ) ) ) )
-
- (define (remove-local-bindings! graph)
- ;; Remove local definitions of lifted procedures:
- (let walk ([n node])
- (let ([class (node-class n)]
- [params (node-parameters n)]
- [subs (node-subexpressions n)] )
- (case class
- [(let)
- (for-each walk (node-subexpressions n))
- (let ([vars2 '()]
- [vals2 '()] )
- (do ([vars params (cdr vars)]
- [vals subs (cdr vals)] )
- ((null? vars)
- (cond [(null? vars2) (copy-node! (car vals) n)]
- [else
- (node-parameters-set! n (reverse vars2))
- (node-subexpressions-set! n (append (reverse vals2) vals)) ] ) )
- (unless (assq (car vars) graph)
- (set! vars2 (cons (car vars) vars2))
- (set! vals2 (cons (car vals) vals2)) ) ) ) ]
- [(set!)
- (for-each walk (node-subexpressions n))
- (when (assq (first params) graph)
- (node-class-set! n '##core#undefined)
- (node-parameters-set! n '())
- (node-subexpressions-set! n '()) ) ]
- [else (for-each walk subs)] ) ) ) )
-
- (debugging 'p "gathering liftables...")
- (let ([cs (find-lifting-candidates)])
- (debugging 'p "building call graph...")
- (let ([g (build-call-graph cs)])
- (debugging 'p "eliminating non-liftables...")
- (let ([g2 (eliminate cs g)])
- (when (debugging 'l "call-graph:") (pretty-print g2))
- (debugging 'p "computing access-lists...")
- (let ([al (collect-accessibles g2)])
- (when (debugging 'l "accessibles:") (pretty-print al))
- (debugging 'p "eliminating liftables by access-lists and non-liftable callees...")
- (let ([ls (eliminate3 (eliminate4 g2))]) ;(eliminate2 g2 al)))]) - why isn't this used?
- (when (pair? ls)
- (debugging 'o "liftable local procedures" (delay (unzip1 ls))))
- (debugging 'p "gathering extra parameters...")
- (let ([extra (compute-extra-variables ls)])
- (when (debugging 'l "additional parameters:") (pretty-print extra))
- (debugging 'p "changing call sites...")
- (extend-call-sites! extra)
- (debugging 'p "removing local bindings...")
- (remove-local-bindings! ls)
- (debugging 'p "moving liftables to toplevel...")
- (reconstruct! ls extra) ) ) ) ) ) ) ) )
diff --git a/support.scm b/support.scm
index 4afec0ee..d2fde7af 100644
--- a/support.scm
+++ b/support.scm
@@ -1514,7 +1514,6 @@ Usage: chicken FILENAME OPTION ...
-optimize-level NUMBER enable certain sets of optimization options
-optimize-leaf-routines enable leaf routine optimization
- -lambda-lift enable lambda-lifting
-no-usual-integrations standard procedures may be redefined
-unsafe disable all safety checks
-local assume globals are only modified in current
@@ -1522,9 +1521,6 @@ Usage: chicken FILENAME OPTION ...
-block enable block-compilation
-disable-interrupts disable interrupts in compiled code
-fixnum-arithmetic assume all numbers are fixnums
- -benchmark-mode equivalent to 'block -optimize-level 4
- -debug-level 0 -fixnum-arithmetic -lambda-lift
- -inline -disable-interrupts'
-disable-stack-overflow-checks disables detection of stack-overflows
-inline enable inlining
-inline-limit LIMIT set inlining threshold
Trap