94 lines
2.7 KiB
Scheme
94 lines
2.7 KiB
Scheme
; Copyright (c) 1993-1999 by Richard Kelsey. See file COPYING.
|
|
|
|
|
|
; Post-CPS optimizer. All simplifications are done by changing the
|
|
; structure of the node tree.
|
|
;
|
|
; There are two requirements for the simplifiers:
|
|
; 1) Only the node being simplified and its descendents may be changed.
|
|
; 2) If a node is changed the NODE-SIMPLIFIED? flag of that node and all
|
|
; its ancestors must be set to false.
|
|
|
|
; No way to simplify literal or reference nodes.
|
|
|
|
(define (simplify-node node)
|
|
(cond ((call-node? node)
|
|
(simplify-call node))
|
|
((lambda-node? node)
|
|
(simplify-lambda-body node))))
|
|
|
|
(define (simplify-global-reference ref)
|
|
(let ((value (variable-known-value (reference-variable ref))))
|
|
(if value
|
|
(replace ref (vector->node value)))))
|
|
|
|
(define (simplify-lambda-body lambda-node)
|
|
(let loop ()
|
|
(let ((node (lambda-body lambda-node)))
|
|
(cond ((not (node-simplified? node))
|
|
(set-node-simplified?! node #t)
|
|
(simplify-call node)
|
|
(loop))))))
|
|
|
|
(define (default-simplifier call)
|
|
(simplify-args call 0))
|
|
|
|
; Utility used by many simplifiers - simplify the specified children.
|
|
|
|
(define (simplify-args call start)
|
|
(let* ((vec (call-args call))
|
|
(len (vector-length vec)))
|
|
(do ((i start (+ i '1)))
|
|
((>= i len))
|
|
(really-simplify-arg vec i))))
|
|
|
|
; Keep simplifying a node until it stops changing.
|
|
|
|
(define (simplify-arg call index)
|
|
(really-simplify-arg (call-args call) index))
|
|
|
|
(define (really-simplify-arg vec index)
|
|
(let loop ((node (vector-ref vec index)))
|
|
(cond ((not (node-simplified? node))
|
|
(set-node-simplified?! node #t)
|
|
(case (node-variant node)
|
|
((reference)
|
|
(if (global-variable? (reference-variable node))
|
|
(simplify-global-reference node)))
|
|
((call)
|
|
(simplify-call node))
|
|
((lambda)
|
|
(simplify-lambda-body node)))
|
|
(loop (vector-ref vec index))))))
|
|
|
|
; Remove any unused arguments to L-NODE
|
|
; Could substitute identical arguments as well...
|
|
|
|
(define (simplify-known-lambda l-node)
|
|
(let ((unused (filter (lambda (var) (not (used? var)))
|
|
(if (eq? 'proc (lambda-type l-node))
|
|
(cdr (lambda-variables l-node))
|
|
(lambda-variables l-node)))))
|
|
(if (not (null? unused))
|
|
(let ((refs (find-calls l-node)))
|
|
(for-each (lambda (var)
|
|
(let ((index (+ 1 (variable-index var))))
|
|
(for-each (lambda (ref)
|
|
(remove-ith-argument (node-parent ref)
|
|
index
|
|
var))
|
|
refs)
|
|
(remove-variable l-node var)))
|
|
unused)))))
|
|
|
|
; VAR is used to get the appropriate representation
|
|
|
|
(define (remove-ith-argument call index var)
|
|
(let ((value (detach (call-arg call index))))
|
|
(remove-call-arg call index)
|
|
(move-body call
|
|
(lambda (call)
|
|
(let-nodes ((c1 (let 1 l1 value))
|
|
(l1 (var) call))
|
|
c1)))))
|