; 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)))))