Major redesign of front end of compiler. Continuations are now
authorChris Hanson <org/chris-hanson/cph>
Fri, 4 Dec 1987 19:28:21 +0000 (19:28 +0000)
committerChris Hanson <org/chris-hanson/cph>
Fri, 4 Dec 1987 19:28:21 +0000 (19:28 +0000)
modeled more exactly by means of a CPS-style analysis.  Poppers have
been flushed in favor of dynamic links, and optimizations have been
added that eliminate the use of static and dynamic links in many
cases.

v7/src/compiler/fggen/fggen.scm [new file with mode: 0644]
v7/src/compiler/fgopt/closan.scm [new file with mode: 0644]
v7/src/compiler/fgopt/contan.scm [new file with mode: 0644]
v7/src/compiler/fgopt/desenv.scm [new file with mode: 0644]
v7/src/compiler/fgopt/operan.scm [new file with mode: 0644]
v7/src/compiler/fgopt/order.scm [new file with mode: 0644]
v7/src/compiler/fgopt/simple.scm [new file with mode: 0644]

diff --git a/v7/src/compiler/fggen/fggen.scm b/v7/src/compiler/fggen/fggen.scm
new file mode 100644 (file)
index 0000000..261faaf
--- /dev/null
@@ -0,0 +1,596 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fggen/fggen.scm,v 4.1 1987/12/04 19:27:53 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Flow Graph Generation
+
+(declare (usual-integrations))
+\f
+(define (construct-graph scode)
+  (fluid-let ((*virtual-continuations* '()))
+    (let ((block (make-block false 'EXPRESSION)))
+      (let ((continuation (make-continuation-variable block)))
+       (let ((expression
+              (make-expression
+               block
+               continuation
+               (transmit-values
+                   (if (scode/open-block? scode)
+                       (scode/open-block-components scode
+                         (lambda (names declarations body)
+                           (return-3 (make-variables block names)
+                                     declarations
+                                     (unscan-defines names '() body))))
+                       (return-3 '() '() scode))
+                 (lambda (variables declarations scode)
+                   (set-block-bound-variables! block variables)
+                   (generate/body block continuation declarations scode))))))
+         (for-each (lambda (procedure)
+                     (if (procedure-continuation? procedure)
+                         (set-procedure-entry-node!
+                          procedure
+                          (snode-next (procedure-entry-node procedure)))))
+                   *procedures*)
+         (for-each (lambda (continuation)
+                     (set-virtual-continuation/parent! continuation false))
+                   *virtual-continuations*)
+         expression)))))
+
+(define (make-variables block names)
+  (map (lambda (name) (make-variable block name)) names))
+
+(define (generate/body block continuation declarations expression)
+  ;; The call to `process-declarations!' must come after the
+  ;; expression is generated because it can refer to the set of free
+  ;; variables in the expression.
+  (let ((node (generate/expression block continuation expression)))
+    (process-declarations! block declarations)
+    node))
+
+(define (continue/rvalue block continuation rvalue)
+  ((continuation/case continuation
+     (lambda ()
+       (make-return block (make-reference block continuation true) rvalue))
+     (lambda ()
+       (make-null-cfg))
+     (lambda ()
+       (make-true-test rvalue))
+     (lambda ()
+       (if (not (virtual-continuation? continuation))
+          (error "Continuation should be virtual" continuation))
+       (make-subproblem (make-null-cfg) continuation rvalue)))))
+\f
+;;;; Continuations
+
+(define (continuation/case continuation unknown effect predicate value)
+  (cond ((variable? continuation) unknown)
+       ((procedure? continuation)
+        (let ((type (continuation/type continuation)))
+          (cond ((eq? type continuation-type/effect) effect)
+                ((eq? type continuation-type/predicate) predicate)
+                ((eq? type continuation-type/value) value)
+                (else (error "Illegal continuation type" type)))))
+       ((virtual-continuation? continuation)
+        (let ((type (virtual-continuation/type continuation)))
+          (cond ((eq? type continuation-type/effect) effect)
+                ((eq? type continuation-type/predicate) predicate)
+                ((eq? type continuation-type/value) value)
+                (else (error "Illegal virtual continuation type" type)))))
+       (else (error "Illegal continuation" continuation))))
+
+(define (continuation/type? continuation type)
+  (cond ((variable? continuation) false)
+       ((procedure? continuation)
+        (eq? (continuation/type continuation) type))
+       ((virtual-continuation? continuation)
+        (eq? (virtual-continuation/type continuation) type))
+       (else
+        (error "Illegal continuation" continuation))))
+
+(define-integrable (continuation/effect? continuation)
+  (continuation/type? continuation continuation-type/effect))
+
+(define-integrable (continuation/predicate? continuation)
+  (continuation/type? continuation continuation-type/predicate))
+
+(define (continuation/rvalue continuation)
+  (make-reference (continuation/block continuation)
+                 (continuation/parameter continuation)
+                 true))
+
+(define-integrable (continuation/next-hooks continuation)
+  (list (make-hook (continuation/entry-node continuation)
+                  set-snode-next-edge!)))
+
+(define-integrable (continuation-reference block continuation)
+  (cond ((variable? continuation) (make-reference block continuation true))
+       ((procedure? continuation) continuation)
+       (else (error "Illegal continuation" continuation))))
+\f
+;;;; Subproblems
+
+(define (subproblem-canonicalize subproblem)
+  (if (subproblem-canonical? subproblem)
+      subproblem
+      (let ((continuation
+            (continuation/reify! (subproblem-continuation subproblem))))
+       (make-subproblem/canonical
+        (scfg*scfg->scfg! (subproblem-prefix subproblem)
+                          (make-return (subproblem-block subproblem)
+                                       continuation
+                                       (subproblem-rvalue subproblem)))
+        continuation))))
+
+(define (continuation/reify! continuation)
+  (if (virtual-continuation? continuation)
+      (virtual-continuation/reify! continuation)
+      continuation))
+
+(define (make-subproblem/canonical prefix continuation)
+  (make-subproblem prefix
+                  continuation
+                  (continuation/rvalue continuation)))
+
+(define (scfg*subproblem->subproblem! scfg subproblem)
+  (make-subproblem (scfg*scfg->scfg! scfg (subproblem-prefix subproblem))
+                  (subproblem-continuation subproblem)
+                  (subproblem-rvalue subproblem)))
+
+(define (pcfg*subproblem->subproblem! predicate consequent alternative)
+  ;; This depends on the fact that, after canonicalizing two
+  ;; subproblems which were generated with the same continuation, the
+  ;; block, continuation, and rvalue of each subproblem are identical.
+  (let ((consequent (subproblem-canonicalize consequent))
+       (alternative (subproblem-canonicalize alternative)))
+    (make-subproblem (pcfg*scfg->scfg! predicate
+                                      (subproblem-prefix consequent)
+                                      (subproblem-prefix alternative))
+                    (subproblem-continuation consequent)
+                    (subproblem-rvalue consequent))))
+\f
+(define (generator/subproblem type scfg*value->value!)
+  (lambda (block continuation expression)
+    (let ((continuation (virtual-continuation/make block continuation type)))
+      (let ((value (generate/expression block continuation expression)))
+       (if (virtual-continuation/reified? continuation)
+           (scfg*value->value!
+            (make-push block (virtual-continuation/reification continuation))
+            value)
+           value)))))
+
+(define *virtual-continuations*)
+
+(define (virtual-continuation/make block parent type)
+  (let ((continuation (virtual-continuation/%make block parent type)))
+    (set! *virtual-continuations* (cons continuation *virtual-continuations*))
+    continuation))
+
+(define generate/subproblem/effect
+  (generator/subproblem continuation-type/effect scfg*scfg->scfg!))
+
+(define generate/subproblem/predicate
+  (generator/subproblem continuation-type/predicate scfg*pcfg->pcfg!))
+
+(define generate/subproblem/value
+  (generator/subproblem continuation-type/value scfg*subproblem->subproblem!))
+\f
+;;;; Values
+
+(define (generate/constant block continuation expression)
+  (continue/rvalue block continuation (make-constant expression)))
+
+(define (generate/the-environment block continuation expression)
+  (continue/rvalue block continuation block))
+
+(define (generate/variable block continuation expression)
+  (continue/rvalue block
+                  continuation
+                  (make-reference block
+                                  (find-name block
+                                             (scode/variable-name expression))
+                                  false)))
+
+(define (generate/safe-variable block continuation expression)
+  (continue/rvalue
+   block
+   continuation
+   (make-reference block
+                  (find-name block (scode/safe-variable-name expression))
+                  true)))
+
+(define-integrable (scode/make-safe-variable name)
+  (cons safe-variable-tag name))
+
+(define-integrable (scode/safe-variable-name reference)
+  (cdr reference))
+
+(define safe-variable-tag
+  "safe-variable")
+
+(define (generate/unassigned? block continuation expression)
+  (if (continuation/predicate? continuation)
+      (continue/rvalue block
+                      continuation
+                      (make-unassigned-test
+                       block
+                       (find-name block (scode/unassigned?-name expression))))
+      (generate/conditional block
+                           continuation
+                           (scode/make-conditional expression #T #F))))
+
+(define (find-name block name)
+  (define (search block)
+    (or (variable-assoc name (block-bound-variables block))
+       (variable-assoc name (block-free-variables block))
+       (let ((variable
+              (if (block-parent block)
+                  (search (block-parent block))
+                  (make-variable block name))))
+         (set-block-free-variables! block
+                                    (cons variable
+                                          (block-free-variables block)))
+         variable)))
+  (search block))
+\f
+(define (generate/lambda block continuation expression)
+  (continue/rvalue
+   block
+   continuation
+   (scode/lambda-components expression
+     (lambda (name required optional rest auxiliary declarations body)
+       (transmit-values (parse-procedure-body auxiliary body)
+        (lambda (names values body)
+          (let ((block (make-block block 'PROCEDURE)))
+            (let ((continuation (make-continuation-variable block))
+                  (required (make-variables block required))
+                  (optional (make-variables block optional))
+                  (rest (and rest (make-variable block rest)))
+                  (names (make-variables block names)))
+              (set-block-bound-variables! block
+                                          `(,continuation
+                                            ,@required
+                                            ,@optional
+                                            ,@(if rest (list rest) '())
+                                            ,@names))
+              (make-procedure
+               continuation-type/procedure
+               block name (cons continuation required) optional rest names
+               (map (lambda (value)
+                      ;; The other parts of this subproblem are not
+                      ;; interesting since `value' is guaranteed to
+                      ;; be either a constant or a procedure.
+                      (subproblem-rvalue
+                       (generate/subproblem/value block continuation value)))
+                    values)
+               (generate/body block continuation declarations body))))))))))
+\f
+(define (parse-procedure-body auxiliary body)
+  (transmit-values
+      (parse-procedure-body* auxiliary (scode/sequence-actions body))
+    (lambda (names values auxiliary actions)
+      (if (null? auxiliary)
+         (return-3 names values (scode/make-sequence actions))
+         (return-3 '() '()
+                   (scode/make-combination
+                    (scode/make-lambda
+                     lambda-tag:let auxiliary '() false names '()
+                     (scode/make-sequence
+                      (map* actions scode/make-assignment names values)))
+                    (map (lambda (name) (scode/make-unassigned-object))
+                         auxiliary)))))))
+
+(define (parse-procedure-body* names actions)
+  ;; Extract any definitions that do not depend on the order of
+  ;; events.
+  (cond ((null? names)
+        (return-4 '() '() '() actions))
+       ((null? actions)
+        (error "Extraneous auxiliaries" names))
+
+       ;; Because `scan-defines' returns the auxiliary names in a
+       ;; particular order, we can expect to encounter them in that
+       ;; same order when looking through the body's actions.
+
+       ((and (scode/assignment? (car actions))
+             (eq? (scode/assignment-name (car actions)) (car names)))
+        (transmit-values (parse-procedure-body* (cdr names) (cdr actions))
+          (let ((value (scode/assignment-value (car actions))))
+            (if (or (scode/lambda? value)
+                    (scode/delay? value)
+                    (scode/constant? value))
+                (lambda (names* values auxiliary actions*)
+                  (return-4 (cons (car names) names*)
+                            (cons value values)
+                            auxiliary
+                            (if (null? actions*)
+                                (list undefined-conditional-branch)
+                                actions*)))
+                (lambda (names* values auxiliary actions*)
+                  (return-4 names*
+                            values
+                            (cons (car names) auxiliary)
+                            (cons (car actions) actions*)))))))
+       (else
+        (transmit-values (parse-procedure-body* names (cdr actions))
+          (lambda (names* values auxiliary actions*)
+            (return-4 names*
+                      values
+                      auxiliary
+                      (cons (car actions) actions*)))))))
+\f
+;;;; Combinators
+
+(define (generate/combination block continuation expression)
+  (let ((continuation (continuation/reify! continuation)))
+    (let ((generator
+          (lambda (expression)
+            (generate/subproblem/value block #|(make-block block 'JOIN)|#
+                                       continuation
+                                       expression))))
+      (scode/combination-components expression
+       (lambda (operator operands)
+         (let ((combination
+                (make-combination block
+                                  (continuation-reference block continuation)
+                                  (generator operator)
+                                  (map generator operands))))
+           ((continuation/case continuation
+              (lambda ()
+                combination)
+              (lambda ()
+                (make-scfg (cfg-entry-node combination)
+                           (continuation/next-hooks continuation)))
+              (lambda ()
+                (scfg*pcfg->pcfg!
+                 (make-scfg (cfg-entry-node combination)
+                            (continuation/next-hooks continuation))
+                 (make-true-test (continuation/rvalue continuation))))
+              (lambda ()
+                (make-subproblem/canonical combination continuation))))))))))
+
+(define (generate/sequence block continuation expression)
+  (let ((join
+        (continuation/case continuation
+                           scfg*scfg->scfg!
+                           scfg*scfg->scfg!
+                           scfg*pcfg->pcfg!
+                           scfg*subproblem->subproblem!)))
+    (let loop ((actions (scode/sequence-actions expression)))
+      (if (null? (cdr actions))
+         (generate/expression block continuation (car actions))
+         (join (generate/subproblem/effect block continuation (car actions))
+               (loop (cdr actions)))))))
+
+(define (generate/conditional block continuation expression)
+  (scode/conditional-components expression
+    (lambda (predicate consequent alternative)
+      ((continuation/case continuation
+                         pcfg*scfg->scfg!
+                         pcfg*scfg->scfg!
+                         pcfg*pcfg->pcfg!
+                         pcfg*subproblem->subproblem!)
+       (generate/subproblem/predicate block continuation predicate)
+       (generate/expression block continuation consequent)
+       (generate/expression block continuation alternative)))))
+\f
+;;;; Assignments
+
+(define (generate/assignment* maker find-name block continuation name value)
+  (let ((subproblem (generate/subproblem/value block continuation value)))
+    (scfg*scfg->scfg!
+     (if (subproblem-canonical? subproblem)
+        (make-scfg
+         (cfg-entry-node (subproblem-prefix subproblem))
+         (continuation/next-hooks (subproblem-continuation subproblem)))
+        (subproblem-prefix subproblem))
+     (maker block (find-name block name) (subproblem-rvalue subproblem)))))
+
+(define (generate/assignment block continuation expression)
+  (scode/assignment-components expression
+    (lambda (name value)
+      (if (continuation/effect? continuation)
+         (generate/assignment* make-assignment find-name
+                               block continuation name value)
+         (generate/combination
+          block
+          continuation
+          (let ((old-value-temp (generate-uninterned-symbol))
+                (new-value-temp (generate-uninterned-symbol)))
+            (scode/make-let (list old-value-temp new-value-temp)
+                            (list (scode/make-safe-variable name) value)
+                            (scode/make-assignment
+                             name
+                             (scode/make-variable new-value-temp))
+                            (scode/make-variable old-value-temp))))))))
+\f
+(define (generate/definition block continuation expression)
+  (scode/definition-components expression
+    (lambda (name value)
+      (if (continuation/effect? continuation)
+         (generate/assignment* make-definition make-definition-variable
+                               block continuation name
+                               (insert-letrec name value))
+         (generate/sequence block
+                            continuation
+                            (scode/make-sequence
+                             (list (scode/make-definition name value)
+                                   name)))))))
+
+(define (make-definition-variable block name)
+  (let ((bound (block-bound-variables block)))
+    (or (variable-assoc name bound)
+       (let ((variable (make-variable block name)))
+         (set-block-bound-variables! block (cons variable bound))
+         variable))))
+
+(define (insert-letrec name value)
+  (if (and compiler:implicit-self-static?
+          (scode/lambda? value))
+      (scode/make-let '() '()
+                     (scode/make-definition name value)
+                     (scode/make-variable name))
+      value))
+\f
+;;;; Rewrites
+
+(define (generate/access block continuation expression)
+  (scode/access-components expression
+    (lambda (environment name)
+      (generate/combination
+       block
+       continuation
+       (scode/make-combination (ucode-primitive lexical-reference)
+                              (list environment name))))))
+
+(define (generate/comment block continuation expression)
+  (generate/expression block
+                      continuation
+                      (scode/comment-expression expression)))
+
+(define (generate/delay block continuation expression)
+  (generate/lambda block
+                  continuation
+                  (scode/make-lambda lambda-tag:delay '() '() false '() '()
+                                     (scode/delay-expression expression))))
+
+(define (generate/disjunction block continuation expression)
+  (scode/disjunction-components expression
+    (lambda (predicate alternative)
+      (generate/combination
+       block
+       continuation
+       (let ((temp (generate-uninterned-symbol)))
+        (scode/make-let (list temp)
+                        (list predicate)
+                        (let ((predicate (scode/make-variable temp)))
+                          (scode/make-conditional predicate
+                                                  predicate
+                                                  alternative))))))))
+
+(define (generate/error-combination block continuation expression)
+  (scode/error-combination-components expression
+    (lambda (message irritants)
+      (generate/combination
+       block
+       continuation
+       (scode/make-combination compiled-error-procedure
+                              (cons message irritants))))))
+\f
+(define (generate/in-package block continuation expression)
+  (warn "IN-PACKAGE not supported; body will be interpreted" expression)
+  (scode/in-package-components expression
+    (lambda (environment expression)
+      (generate/combination
+       block
+       continuation
+       (scode/make-combination (ucode-primitive scode-eval)
+                              (list (scode/make-quotation expression)
+                                    environment))))))
+
+(define (generate/quotation block continuation expression)
+  (generate/combination
+   block
+   continuation
+   (scode/make-combination
+    (ucode-primitive car)
+    (list (list (scode/quotation-expression expression))))))
+
+(define (scode/make-let names values . body)
+  (scan-defines (scode/make-sequence body)
+    (lambda (auxiliary declarations body)
+      (scode/make-combination
+       (scode/make-lambda lambda-tag:let names '() false
+                         auxiliary declarations body)
+       values))))
+\f
+;;;; Dispatcher
+
+(define generate/expression
+  (let ((dispatch-vector
+        (make-vector number-of-microcode-types generate/constant))
+       (generate/combination
+        (lambda (block continuation expression)
+          (let ((operator (scode/combination-operator expression))
+                (operands (scode/combination-operands expression)))
+            (cond ((and (eq? operator (ucode-primitive lexical-unassigned?))
+                        (the-environment? (car operands))
+                        (scode/symbol? (cadr operands)))
+                   (generate/unassigned? block continuation expression))
+                  ((or (eq? operator (ucode-primitive error-procedure))
+                       (and (scode/absolute-reference? operator)
+                            (eq? (scode/absolute-reference-name operator)
+                                 'ERROR-PROCEDURE)))
+                   (generate/error-combination block continuation expression))
+                  (else
+                   (generate/combination block continuation expression))))))
+       (generate/pair
+        (lambda (block continuation expression)
+          (if (eq? (car expression) safe-variable-tag)
+              (generate/safe-variable block continuation expression)
+              (generate/constant block continuation expression)))))
+\f
+    (let-syntax
+       ((dispatch-entry
+         (macro (type handler)
+           `(VECTOR-SET! DISPATCH-VECTOR ,(microcode-type type) ,handler)))
+        (dispatch-entries
+         (macro (types handler)
+           `(BEGIN ,@(map (lambda (type)
+                            `(DISPATCH-ENTRY ,type ,handler))
+                          types))))
+        (standard-entry
+         (macro (name)
+           `(DISPATCH-ENTRY ,name ,(symbol-append 'GENERATE/ name)))))
+      (standard-entry access)
+      (standard-entry assignment)
+      (standard-entry conditional)
+      (standard-entry definition)
+      (standard-entry delay)
+      (standard-entry disjunction)
+      (standard-entry in-package)
+      (standard-entry pair)
+      (standard-entry quotation)
+      (standard-entry the-environment)
+      (standard-entry variable)
+      (dispatch-entries (lambda lexpr extended-lambda) generate/lambda)
+      (dispatch-entries (sequence-2 sequence-3) generate/sequence)
+      (dispatch-entries (combination-1 combination-2 combination
+                                      primitive-combination-0
+                                      primitive-combination-1
+                                      primitive-combination-2
+                                      primitive-combination-3)
+                       generate/combination)
+      (dispatch-entry comment generate/comment))
+    (named-lambda (generate/expression block continuation expression)
+      ((vector-ref dispatch-vector (primitive-type expression))
+       block continuation expression))))
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/closan.scm b/v7/src/compiler/fgopt/closan.scm
new file mode 100644 (file)
index 0000000..06652be
--- /dev/null
@@ -0,0 +1,118 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/closan.scm,v 4.1 1987/12/04 19:27:30 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Closure Analysis
+
+(declare (usual-integrations))
+\f
+#|
+
+The closure analysis operates by identifying the "closing limit" of
+each procedure, which is defined as the nearest ancestor of the
+procedure's closing block which is active during the procedure's
+lifetime.  The closing limit is false whenever the extent of the
+procedure is not fully known, or if the procedure must be fully closed
+for any reason (including canonicalization).
+
+Procedures that are called from a closed procedure must inherit that
+procedure's closing limit since only the blocks farther away than the
+closing limit can be assumed to exist when those procedures are
+called.
+
+The procedure's free variables which are bound in blocks up to the
+closing limit (exclusive) must be consed in the heap.  Other free
+variables don't necessarily need to be allocated on the heap, provided
+that there is a known way to get to them.
+
+This analysis is maximal in that it is required for ANY closure
+construction mechanism that optimizes by means of a stack, because use
+of a stack associates procedure extent with block scope.  For many
+simple techniques it generates more information than is needed.
+
+|#
+\f
+(package (identify-closure-limits!)
+
+(define-export (identify-closure-limits! procedures applications assignments)
+  (for-each initialize-closure-limit! procedures)
+  (for-each close-application-arguments! applications)
+  (for-each close-assignment-values! assignments))
+
+(define (initialize-closure-limit! procedure)
+  (if (not (procedure-continuation? procedure))
+      (set-procedure-closing-limit!
+       procedure
+       (and (not (procedure-passed-out? procedure))
+           (procedure-closing-block procedure)))))
+
+(define (close-application-arguments! application)
+  (close-values!
+   (application-operand-values application)
+   (let ((procedure (rvalue-known-value (application-operator application))))
+     (and procedure
+         (rvalue/procedure? procedure)
+         (procedure-always-known-operator? procedure)
+         (procedure-block procedure)))))
+
+(define (close-assignment-values! assignment)
+  (close-rvalue! (assignment-rvalue assignment)
+                (variable-block (assignment-lvalue assignment))))
+
+(define-integrable (close-rvalue! rvalue binding-block)
+  (close-values! (rvalue-values rvalue) binding-block))
+
+(define (close-values! values binding-block)
+  (for-each (lambda (value)
+             (if (and (rvalue/procedure? value)
+                      (not (procedure-continuation? value)))
+                 (close-procedure! value binding-block)))
+           values))
+
+(define (close-procedure! procedure binding-block)
+  (let ((closing-limit (procedure-closing-limit procedure)))
+    (let ((new-closing-limit
+          (and binding-block
+               closing-limit
+               (block-nearest-common-ancestor binding-block closing-limit))))
+      (if (not (eq? new-closing-limit closing-limit))
+         (begin
+           (set-procedure-closing-limit! procedure new-closing-limit)
+           (for-each-block-descendent! (procedure-block procedure)
+             (lambda (block)
+               (for-each (lambda (application)
+                           (close-rvalue! (application-operator application)
+                                          new-closing-limit))
+                         (block-applications block)))))))))
+
+)
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/contan.scm b/v7/src/compiler/fgopt/contan.scm
new file mode 100644 (file)
index 0000000..5f26f83
--- /dev/null
@@ -0,0 +1,168 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/contan.scm,v 4.1 1987/12/04 19:27:35 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Continuation Analysis
+
+(declare (usual-integrations))
+\f
+(package (continuation-analysis)
+
+;;; Determine when static or dynamic links are to be used.  For static
+;;; links, we compute the `block-stack-link' which is the set of
+;;; blocks which might be immediately adjacent (away from the top of
+;;; the stack) to the given block on the stack.  If it is possible to
+;;; find the parent in a consistent way with any one of these adjacent
+;;; blocks, we do not need a static link.  Otherwise, we set
+;;; `block-stack-link' to the empty list and use a static link.
+
+;;; For dynamic links, we compute the popping limit of a procedure's
+;;; continuation variable, which is the farthest ancestor of the
+;;; procedure's block that is be popped when invoking the
+;;; continuation.  If we cannot compute the limit statically (value is
+;;; #F), we must use a dynamic link.
+
+;;; This code takes advantage of the fact that the continuation
+;;; variable is not referenced in blocks other than the procedure's
+;;; block.  This may change if call/cc is handled specially.
+
+(define-export (continuation-analysis blocks procedures)
+  (for-each (lambda (procedure)
+             (if (procedure-continuation? procedure)
+                 (begin
+                   (set-continuation/lvalues! procedure '())
+                   (set-continuation/dynamic-link?! procedure false))))
+           procedures)
+  (for-each (lambda (block)
+             (if (stack-block? block)
+                 (analyze-continuation block)))
+           blocks)
+  (for-each (lambda (block)
+             (if (stack-block? block)
+                 (let ((lvalue (stack-block/continuation-lvalue block)))
+                   (if (not (variable-popping-limit lvalue))
+                       (force-dynamic-link! lvalue)))))
+           blocks)
+  (for-each (lambda (block)
+             (if (stack-block? block)
+                 (lvalue-mark-clear! (stack-block/continuation-lvalue block)
+                                     dynamic-link-marker)))
+           blocks))
+\f
+(define (force-dynamic-link! lvalue)
+  (if (not (lvalue-mark-set? lvalue dynamic-link-marker))
+      (begin
+       (lvalue-mark-set! lvalue dynamic-link-marker)
+       (for-each (lambda (continuation)
+                   (if (not (continuation/dynamic-link? continuation))
+                       (begin
+                         (set-continuation/dynamic-link?! continuation true)
+                         (for-each (lambda (lvalue)
+                                     (if (variable-popping-limit lvalue)
+                                         (force-dynamic-link! lvalue)))
+                                   (continuation/lvalues continuation)))))
+                 (lvalue-values lvalue)))))
+
+(define dynamic-link-marker
+  "dynamic-link")
+
+(define (analyze-continuation block)
+  (let ((lvalue (stack-block/continuation-lvalue block)))
+    (for-each (lambda (continuation)
+               (set-continuation/lvalues!
+                continuation
+                (cons lvalue (continuation/lvalues continuation))))
+             (lvalue-values lvalue))
+    (set-variable-popping-limit!
+     lvalue
+     (if (stack-parent? block)
+        (let ((external (stack-block/external-ancestor block)))
+          (let ((joins (continuation-join-blocks block lvalue external)))
+            (set-block-stack-link! block (adjacent-blocks block lvalue joins))
+            (and (not (null? joins))
+                 (null? (cdr joins))
+                 (or (car joins) external))))
+        block))))
+\f
+(define (adjacent-blocks block lvalue joins)
+  (let ((parent (block-parent block)))
+    (transmit-values
+       (discriminate-items joins
+                           (lambda (join)
+                             (or (eq? join block)
+                                 (eq? join parent))))
+      (lambda (internal external)
+       (cond ((null? internal)
+              ;; The procedure is never invoked as a subproblem.
+              ;; Therefore its ancestor frame and all intermediate
+              ;; frames are always immediately adjacent on the stack.
+              (list parent))
+             ((and (null? external)
+                   (null? (cdr internal))
+                   ;; Eliminate pathological case of procedure which
+                   ;; is always invoked as a subproblem of itself.
+                   ;; This can be written but the code can never be
+                   ;; invoked.
+                   (not (block-ancestor-or-self? (car internal) block)))
+              ;; The procedure is always invoked as a subproblem, and
+              ;; all of the continuations are closed in the same
+              ;; block.  Therefore we can reach the ancestor frame by
+              ;; reference to that block.
+              (map continuation/block (lvalue-values lvalue)))
+             (else
+              ;; The relative position of the ancestor frame is not
+              ;; statically determinable.
+              '()))))))
+
+(define (continuation-join-blocks block lvalue external)
+  (let ((ancestry (memq external (block-ancestry block '()))))
+    (let ((blocks
+          (map->eq-set
+           (lambda (block*)
+             (let ((ancestry* (memq external (block-ancestry block* '()))))
+               (and ancestry*
+                    (let loop
+                        ((ancestry (cdr ancestry))
+                         (ancestry* (cdr ancestry*)))
+                      (cond ((null? ancestry) block)
+                            ((and (not (null? ancestry*))
+                                  (eq? (car ancestry) (car ancestry*)))
+                             (loop (cdr ancestry) (cdr ancestry*)))
+                            (else (car ancestry)))))))
+           (map->eq-set continuation/closing-block
+                        (lvalue-values lvalue)))))
+      (if (lvalue-passed-in? lvalue)
+         (eq-set-adjoin false blocks)
+         blocks))))
+
+)
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/desenv.scm b/v7/src/compiler/fgopt/desenv.scm
new file mode 100644 (file)
index 0000000..4a72868
--- /dev/null
@@ -0,0 +1,227 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/desenv.scm,v 4.1 1987/12/04 19:27:45 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Environment Design
+
+(declare (usual-integrations))
+\f
+;;;; Frame Layout
+
+#|
+
+Layout of stack frames.  The top of each frame is where the frame
+pointer points to, which is the most recently pushed item in the
+frame (i.e. the item closest to the top of stack).  There are two
+kinds of frames, depending on what kind of procedure this is.
+
+Open procedure frame:
+
++-------+-------+-------+-------+
+|         Auxiliary 1          |
++-------+-------+-------+-------+
+:              :               :
++-------+-------+-------+-------+
+|         Auxiliary M          |
++-------+-------+-------+-------+
+|          Argument 1          |
++-------+-------+-------+-------+
+:              :               :
++-------+-------+-------+-------+
+|          Argument N          |
++-------+-------+-------+-------+
+|        Rest Argument         |       (omitted if none)
++-------+-------+-------+-------+
+|    Pointer to parent frame   |       (omitted if known)
++-------+-------+-------+-------+
+
+Closed procedure frame:
+
++-------+-------+-------+-------+
+|         Auxiliary 1          |
++-------+-------+-------+-------+
+:              :               :
++-------+-------+-------+-------+
+|         Auxiliary M          |
++-------+-------+-------+-------+
+|           Operator           |       (omitted if not needed)
++-------+-------+-------+-------+
+|          Argument 1          |
++-------+-------+-------+-------+
+:              :               :
++-------+-------+-------+-------+
+|          Argument N          |
++-------+-------+-------+-------+
+|        Rest Argument         |       (omitted if none)
++-------+-------+-------+-------+
+
+|#
+\f
+(package (design-environment-frames!)
+
+(define-export (design-environment-frames! blocks)
+  (for-each (lambda (block)
+             (enumeration-case block-type (block-type block)
+               ((IC)
+                (if (rvalue/procedure? (block-procedure block))
+                    (setup-ic-block-offsets! block)))
+               ((STACK)
+                (delete-integrated-parameters! block)
+                (for-each (lambda (variable)
+                            (if (variable-assigned? variable)
+                                (set-variable-in-cell?! variable true)))
+                          (block-bound-variables block))
+                (setup-stack-block-offsets! block))
+               ((CONTINUATION)
+                (set-block-frame-size!
+                 block
+                 (continuation/frame-size (block-procedure block))))
+               ((CLOSURE) 'DONE)
+               (else
+                (error "Illegal block type" block))))
+           blocks))
+\f
+(package (delete-integrated-parameters!)
+
+(define-export (delete-integrated-parameters! block)
+  (let ((deletions '())
+       (procedure (block-procedure block)))
+    (if (procedure-interface-optimizible? procedure)
+       (begin
+         (let ((delete-integrations
+                (lambda (get-names set-names!)
+                  (transmit-values
+                      (find-integrated-variables (get-names procedure))
+                    (lambda (not-integrated integrated)
+                      (if (not (null? integrated))
+                          (begin
+                            (set-names! procedure not-integrated)
+                            (set! deletions
+                                  (eq-set-union deletions integrated)))))))))
+           (delete-integrations (lambda (procedure)
+                                  (cdr (procedure-required procedure)))
+                                (lambda (procedure required)
+                                  (set-cdr! (procedure-required procedure)
+                                            required)))
+           (delete-integrations procedure-optional set-procedure-optional!))
+         (let ((rest (procedure-rest procedure)))
+           (if (and rest (lvalue-integrated? rest))
+               (begin (set! deletions (eq-set-adjoin deletions rest))
+                      (set-procedure-rest! procedure false))))))
+    (transmit-values
+       (find-integrated-bindings (procedure-names procedure)
+                                 (procedure-values procedure))
+      (lambda (names values integrated)
+       (set-procedure-names! procedure names)
+       (set-procedure-values! procedure values)
+       (set! deletions (eq-set-union deletions integrated))))
+    (if (not (null? deletions))
+       (set-block-bound-variables!
+        block
+        (eq-set-difference (block-bound-variables block) deletions)))))
+\f
+(define (find-integrated-bindings names values)
+  (if (null? names)
+      (return-3 '() '() '())
+      (transmit-values (find-integrated-bindings (cdr names) (cdr values))
+       (lambda (names* values* integrated)
+         (if (lvalue-integrated? (car names))
+             (return-3 names* values* (cons (car names) integrated))
+             (return-3 (cons (car names) names*)
+                       (cons (car values) values*)
+                       integrated))))))
+
+(define (find-integrated-variables variables)
+  (if (null? variables)
+      (return-2 '() '())
+      (transmit-values (find-integrated-variables (cdr variables))
+       (lambda (not-integrated integrated)
+         (if (lvalue-integrated? (car variables))
+             (return-2 not-integrated
+                       (cons (car variables) integrated))
+             (return-2 (cons (car variables) not-integrated)
+                       integrated))))))
+
+)
+\f
+(package (setup-ic-block-offsets! setup-stack-block-offsets!)
+
+(define-export (setup-ic-block-offsets! block)
+  (let ((procedure (block-procedure block)))
+    (setup-variable-offsets!
+     (procedure-names procedure)
+     (setup-variable-offset!
+      (procedure-rest procedure)
+      (setup-variable-offsets!
+       (procedure-optional procedure)
+       (setup-variable-offsets! (cdr (procedure-required procedure))
+                               ic-block-first-parameter-offset))))))
+
+(define-export (setup-stack-block-offsets! block)
+  (let ((procedure (block-procedure block)))
+    (set-block-frame-size!
+     block
+     (let ((offset
+           (setup-variable-offset!
+            (procedure-rest procedure)
+            (setup-variable-offsets!
+             (procedure-optional procedure)
+             (setup-variable-offsets!
+              (cdr (procedure-required procedure))
+              (let ((offset
+                     (setup-variable-offsets! (procedure-names procedure) 0)))
+                (if (and (procedure/closure? procedure)
+                         (closure-procedure-needs-operator? procedure))
+                    (begin (set-procedure-closure-offset! procedure offset)
+                           (1+ offset))
+                    offset)))))))
+       (if (or (procedure/closure? procedure)
+              (not (stack-block/static-link? block)))
+          offset
+          (1+ offset))))))
+
+(define (setup-variable-offsets! variables offset)
+  (if (null? variables)
+      offset
+      (begin (set-variable-normal-offset! (car variables) offset)
+            (setup-variable-offsets! (cdr variables) (1+ offset)))))
+
+(define (setup-variable-offset! variable offset)
+  (if variable
+      (begin (set-variable-normal-offset! variable offset)
+            (1+ offset))
+      offset))
+
+)
+
+)
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/operan.scm b/v7/src/compiler/fgopt/operan.scm
new file mode 100644 (file)
index 0000000..f43e60b
--- /dev/null
@@ -0,0 +1,105 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/operan.scm,v 4.1 1987/12/04 19:28:06 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Operator Analysis
+
+(declare (usual-integrations))
+\f
+(package (operator-analysis)
+
+(define-export (operator-analysis procedures applications)
+  (for-each (lambda (procedure)
+             (if (procedure-continuation? procedure)
+                 (set-continuation/combinations! procedure '())))
+           procedures)
+  (for-each (lambda (application)
+             (if (eq? (application-type application) 'COMBINATION)
+                 (analyze/combination application)))
+           applications)
+  (for-each (lambda (procedure)
+             (if (procedure-continuation? procedure)
+                 (set-continuation/passed-out?!
+                  procedure
+                  (continuation-passed-out? procedure))))
+           procedures)
+  (for-each (lambda (procedure)
+             (set-procedure-always-known-operator?!
+              procedure
+              (if (procedure-continuation? procedure)
+                  (analyze/continuation procedure)
+                  (analyze/procedure procedure))))
+           procedures))
+
+(define (analyze/combination combination)
+  (for-each (lambda (continuation)
+             (set-continuation/combinations!
+              continuation
+              (cons combination
+                    (continuation/combinations continuation))))
+           (rvalue-values (combination/continuation combination))))
+\f
+(define (continuation-passed-out? continuation)
+  (there-exists? (continuation/combinations continuation)
+    (lambda (combination)
+      (and (not (combination/inline? combination))
+          (there-exists? (rvalue-values (combination/operator combination))
+            (lambda (rvalue) (not (rvalue/procedure? rvalue))))))))
+
+(define (analyze/continuation continuation)
+  (and (not (continuation/passed-out? continuation))
+       (let ((returns (continuation/returns continuation))
+            (combinations (continuation/combinations continuation)))
+        (and (or (not (null? returns))
+                 (not (null? combinations)))
+             (for-all? returns
+               (lambda (return)
+                 (eq? (rvalue-known-value (return/operator return))
+                      continuation)))
+             (for-all? combinations
+               (lambda (combination)
+                 (eq? (rvalue-known-value
+                       (combination/continuation combination))
+                      continuation)))))))
+
+(define (analyze/procedure procedure)
+  (and (not (procedure-passed-out? procedure))
+       (let ((combinations (procedure-applications procedure)))
+        (and (not (null? combinations))
+             (for-all? combinations
+               (lambda (combination)
+                 (eq? (rvalue-known-value (combination/operator combination))
+                      procedure)))))))
+
+;;; end OPERATOR-ANALYSIS
+)
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/order.scm b/v7/src/compiler/fgopt/order.scm
new file mode 100644 (file)
index 0000000..bed72ef
--- /dev/null
@@ -0,0 +1,269 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/order.scm,v 4.1 1987/12/04 19:28:12 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Argument Ordering Analysis
+
+(declare (usual-integrations))
+\f
+(package (subproblem-ordering)
+
+(define-export (subproblem-ordering parallels)
+  (for-each (lambda (parallel)
+             (let ((previous-edges (node-previous-edges parallel))
+                   (next-edge (snode-next-edge parallel)))
+               (let ((rest
+                      (or (edge-next-node next-edge)
+                          (error "PARALLEL node missing next" parallel))))
+                 (edges-disconnect-right! previous-edges)
+                 (edge-disconnect! next-edge)
+                 (edges-connect-right!
+                  previous-edges
+                  (parallel-replacement-node parallel rest)))))
+           parallels))
+
+(define (parallel-replacement-node parallel rest)
+  (transmit-values
+      (order-subproblems/application (parallel-application-node parallel)
+                                    (parallel-subproblems parallel))
+    (lambda (subproblems suffix)
+      (linearize-subproblems subproblems (scfg*node->node! suffix rest)))))
+
+(define (linearize-subproblems subproblems rest)
+  (let loop ((subproblems subproblems))
+    (if (null? subproblems)
+       rest
+       (linearize-subproblem (car subproblems)
+                             (loop (cdr subproblems))))))
+
+(define (linearize-subproblem subproblem rest)
+  (let ((continuation (subproblem-continuation subproblem))
+       (prefix (subproblem-prefix subproblem)))
+    (if (subproblem-canonical? subproblem)
+       (begin
+         (if (continuation/entry-node continuation)
+             (error "Attempt to reattach continuation body"
+                    continuation))
+         (set-continuation/entry-node! continuation rest)
+         (cfg-entry-node prefix))
+       (scfg*node->node!
+        prefix
+        (scfg*node->node!
+         (if (eq? continuation-type/effect
+                  (virtual-continuation/type continuation))
+             (make-null-cfg)
+             (make-virtual-return continuation
+                                  (subproblem-rvalue subproblem)))
+         rest)))))
+\f
+(define (order-subproblems/application application subproblems)
+  (case (application-type application)
+    ((COMBINATION)
+     (if (combination/inline? application)
+        (order-subproblems/combination/inline application subproblems)
+        (return-2 (order-subproblems/combination/out-of-line application
+                                                             subproblems)
+                  (make-null-cfg))))
+    ((RETURN)
+     (set-subproblem-types! subproblems continuation-type/effect)
+     (return-2 subproblems (make-null-cfg)))
+    (else
+     (error "Unknown application type" application))))
+
+(define (order-subproblems/combination/inline combination subproblems)
+  (let ((inliner (combination/inliner combination)))
+    (let ((operands
+          (list-filter-indices (cdr subproblems) (inliner/operands inliner))))
+      (set-inliner/operands! inliner (map subproblem-continuation operands))
+      (order-subproblems/inline (car subproblems) operands))))
+
+(define (order-subproblems/inline operator operands)
+  (set-subproblem-type! operator continuation-type/effect)
+  (transmit-values (discriminate-items operands subproblem-simple?)
+    (lambda (simple complex)
+      (if (null? complex)
+         (begin
+           (set-subproblem-types! simple continuation-type/value)
+           (return-2 (cons operator operands) (make-null-cfg)))
+         (let ((push-set (cdr complex))
+               (value-set (cons (car complex) simple)))
+           (set-subproblem-types! push-set continuation-type/push)
+           (set-subproblem-types! value-set continuation-type/register)
+           (return-2 (cons operator (append! push-set value-set))
+                     (scfg*->scfg!
+                      (reverse!
+                       (map (lambda (subproblem)
+                              (make-pop (subproblem-continuation subproblem)))
+                            push-set)))))))))
+\f
+(define (order-subproblems/combination/out-of-line combination subproblems)
+  (let ((subproblems
+        (order-subproblems/out-of-line
+         (combination/block combination)
+         (car subproblems)
+         (cdr subproblems)
+         (rvalue-known-value (combination/operator combination)))))
+    (set-combination/frame-size!
+     combination
+     (let loop ((subproblems subproblems) (accumulator 0))
+       (if (null? subproblems)
+          accumulator
+          (loop (cdr subproblems)
+                (if (eq? (subproblem-type (car subproblems))
+                         continuation-type/push)
+                    (1+ accumulator)
+                    accumulator)))))
+    subproblems))
+
+(define (order-subproblems/out-of-line block operator operands callee)
+  (set-subproblem-type! operator (operator-type (subproblem-rvalue operator)))
+  (if (and callee
+          (rvalue/procedure? callee)
+          (procedure/open? callee))
+      (generate/static-link
+       block
+       callee
+       (if (procedure-interface-optimizible? callee)
+          (optimized-combination-ordering block operator operands callee)
+          (standard-combination-ordering operator operands)))
+      (standard-combination-ordering operator operands)))
+\f
+(define (optimized-combination-ordering block operator operands callee)
+  (transmit-values (sort-subproblems/out-of-line operands callee)
+    (lambda (prefix integrated non-integrated)
+      (set-subproblem-types! integrated continuation-type/effect)
+      (set-subproblem-types! non-integrated continuation-type/push)
+      (push-unassigned block
+                      prefix
+                      (append! integrated non-integrated (list operator))))))
+
+(define (standard-combination-ordering operator operands)
+  (set-subproblem-types! operands continuation-type/push)
+  (reverse (cons operator operands)))
+
+(define (generate/static-link block procedure rest)
+  (if (stack-block/static-link? (procedure-block procedure))
+      (cons (make-push block (block-parent (procedure-block procedure))) rest)
+      rest))
+
+(define (push-unassigned block n rest)
+  (let ((unassigned (make-constant (scode/make-unassigned-object))))
+    (let loop ((n n) (rest rest))
+      (if (zero? n)
+         rest
+         (loop (-1+ n)
+               (cons (make-push block unassigned) rest))))))
+
+(define (make-push block rvalue)
+  (make-subproblem (make-null-cfg)
+                  (virtual-continuation/make block continuation-type/push)
+                  rvalue))
+
+(define (set-subproblem-types! subproblems type)
+  (for-each (lambda (subproblem)
+             (set-subproblem-type! subproblem type))
+           subproblems))
+\f
+(define (sort-subproblems/out-of-line subproblems callee)
+  (transmit-values
+      (sort-integrated (procedure-original-required callee)
+                      subproblems
+                      '()
+                      '())
+    (lambda (required subproblems integrated non-integrated)
+      (if (null? required)
+         (transmit-values
+             (sort-integrated (procedure-original-optional callee)
+                              subproblems
+                              integrated
+                              non-integrated)
+           (lambda (optional subproblems integrated non-integrated)
+             (let ((rest (procedure-original-rest callee)))
+               (cond ((not (null? optional))
+                      (return-3 (if rest
+                                    0
+                                    ;; In this case the caller will
+                                    ;; make slots for the optionals.
+                                    (length optional))
+                                integrated
+                                non-integrated))
+                     ((and rest (lvalue-integrated? rest))
+                      (return-3 0
+                                (append! (reverse subproblems) integrated)
+                                non-integrated))
+                     (else
+                      (return-3 0
+                                integrated
+                                (append! (reverse subproblems)
+                                         non-integrated)))))))
+         ;; This is a wrong number of arguments case, so the code
+         ;; we generate will not be any good.
+         (return-3 0 integrated non-integrated)))))
+
+(define (sort-integrated lvalues subproblems integrated non-integrated)
+  (cond ((or (null? lvalues) (null? subproblems))
+        (return-4 lvalues subproblems integrated non-integrated))
+       ((lvalue-integrated? (car lvalues))
+        (sort-integrated (cdr lvalues)
+                         (cdr subproblems)
+                         (cons (car subproblems) integrated)
+                         non-integrated))
+       (else
+        (sort-integrated (cdr lvalues)
+                         (cdr subproblems)
+                         integrated
+                         (cons (car subproblems) non-integrated)))))
+\f
+(define (operator-type operator)
+  (let ((callee (rvalue-known-value operator)))
+    (cond ((not callee)
+          (if (reference? operator)
+              continuation-type/effect
+              continuation-type/apply))
+         ((rvalue/constant? callee)
+          (if (normal-primitive-procedure? (constant-value callee))
+              continuation-type/effect
+              continuation-type/apply))
+         ((rvalue/procedure? callee)
+          (case (procedure/type callee)
+            ((OPEN-EXTERNAL OPEN-INTERNAL) continuation-type/effect)
+            ((CLOSURE) continuation-type/push)
+            ((IC) continuation-type/apply)
+            (else (error "Unknown procedure type" callee))))
+         (else
+          continuation-type/apply))))
+
+(define-integrable continuation-type/apply
+  continuation-type/push)
+
+)
\ No newline at end of file
diff --git a/v7/src/compiler/fgopt/simple.scm b/v7/src/compiler/fgopt/simple.scm
new file mode 100644 (file)
index 0000000..2c688c2
--- /dev/null
@@ -0,0 +1,130 @@
+#| -*-Scheme-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/fgopt/simple.scm,v 4.1 1987/12/04 19:28:21 cph Exp $
+
+Copyright (c) 1987 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; Argument Simplicity Analysis
+
+(declare (usual-integrations))
+\f
+(package (simplicity-analysis)
+
+(define-export (simplicity-analysis parallels)
+  (for-each (lambda (parallel)
+             (for-each (lambda (subproblem)
+                         (set-subproblem-simple?! subproblem 'UNKNOWN))
+                       (parallel-subproblems parallel)))
+           parallels)
+  (for-each (lambda (parallel)
+             (if (let ((application (parallel-application-node parallel)))
+                   (and application
+                        (application/combination? application)
+                        (combination/inline? application)))
+                 (for-each %subproblem-simple?
+                           (parallel-subproblems parallel))))
+           parallels))
+
+(define (%subproblem-simple? subproblem)
+  (let ((simple? (subproblem-simple? subproblem)))
+    (if (eq? simple? 'UNKNOWN)
+       (let ((simple?
+              (and (rvalue-simple? (subproblem-rvalue subproblem))
+                   (or (not (subproblem-canonical? subproblem))
+                       (node-simple? (subproblem-entry-node subproblem)
+                                     (subproblem-continuation subproblem))))))
+         (set-subproblem-simple?! subproblem simple?)
+         simple?)
+       simple?)))
+
+(define (node-simple? node continuation)
+  ((cfg-node-case (tagged-vector/tag node)
+     ((PARALLEL) parallel-simple?)
+     ((APPLICATION)
+      (case (application-type node)
+       ((COMBINATION) combination-simple?)
+       ((RETURN) return-simple?)
+       (else (error "Unknown application type" node))))
+     ((VIRTUAL-RETURN) virtual-return-simple?)
+     ((ASSIGNMENT) assignment-simple?)
+     ((DEFINITION) definition-simple?)
+     ((TRUE-TEST) true-test-simple?)
+     ((FG-NOOP) fg-noop-simple?))
+   node continuation))
+\f
+(define (parallel-simple? parallel continuation)
+  (and (for-all? (parallel-subproblems parallel) %subproblem-simple?)
+       (node-simple? (snode-next parallel) continuation)))
+
+(define (combination-simple? combination continuation)
+  (and (combination/inline? combination)
+       (continuation-simple? (combination/continuation combination)
+                            continuation)))
+
+(define (return-simple? return continuation)
+  (continuation-simple? (return/operator return) continuation))
+
+(define (virtual-return-simple? return continuation)
+  (continuation-simple? (virtual-return-operator return) continuation))
+
+(define (continuation-simple? rvalue continuation)
+  (or (eq? rvalue continuation)
+      (and (rvalue/continuation? rvalue)
+          (node-simple? (continuation/entry-node rvalue) continuation))))
+
+(define (assignment-simple? assignment continuation)
+  (and (lvalue-simple? (assignment-lvalue assignment))
+       (rvalue-simple? (assignment-rvalue assignment))
+       (node-simple? (snode-next assignment) continuation)))
+
+(define (definition-simple? definition continuation)
+  (and (lvalue-simple? (definition-lvalue definition))
+       (rvalue-simple? (definition-rvalue definition))
+       (node-simple? (snode-next definition) continuation)))
+
+(define (true-test-simple? true-test continuation)
+  (and (rvalue-simple? (true-test-rvalue true-test))
+       (node-simple? (pnode-consequent true-test) continuation)
+       (node-simple? (pnode-alternative true-test) continuation)))
+
+(define (fg-noop-simple? fg-noop continuation)
+  (node-simple? (snode-next fg-noop) continuation))
+
+(define (rvalue-simple? rvalue)
+  (or (not (rvalue/reference? rvalue))
+      (let ((lvalue (reference-lvalue rvalue)))
+       (or (lvalue-known-value lvalue)
+           (lvalue-simple? lvalue)))))
+
+(define (lvalue-simple? lvalue)
+  (not (block-passed-out? (variable-block lvalue))))
+
+)
\ No newline at end of file