1 ;;;; File: "comp.scm", Time-stamp: <2006-05-08 16:04:37 feeley>
3 ;;;; Copyright (C) 2004-2009 by Marc Feeley and Vincent St-Amour
4 ;;;; All Rights Reserved.
6 (define gen-instruction
7 (lambda (instr nb-pop nb-push ctx)
15 (context-add-instr (context-change-env ctx (env-change-local env stk))
19 (lambda (nparams rest? ctx)
20 (gen-instruction (list 'entry nparams rest?) 0 0 ctx)))
22 (define gen-push-constant
24 (gen-instruction (list 'push-constant val) 0 1 ctx)))
26 (define gen-push-unspecified
28 (gen-push-constant #f ctx)))
30 (define gen-push-local-var
32 ; (pp (list var: var local: (stack-slots (env-local (context-env ctx))) (env-closed (context-env ctx))))
33 (let ((i (find-local-var var (context-env ctx))))
35 (gen-push-stack i ctx)
37 ;; this +1 is needed because closures are in the environment, but
38 ;; don't contain a value, and must therefore be skipped
41 (length (stack-slots (env-local (context-env ctx))))) ctx)))))
43 (define gen-push-stack
45 (gen-instruction (list 'push-stack pos) 0 1 ctx)))
47 (define gen-push-global
49 (gen-instruction (list 'push-global var) 0 1 ctx)))
51 (define gen-set-global
53 (gen-instruction (list 'set-global var) 1 0 ctx)))
57 (gen-instruction (list 'call nargs) (+ nargs 1) 1 ctx)))
61 (gen-instruction (list 'jump nargs) (+ nargs 1) 1 ctx)))
63 (define gen-call-toplevel
64 (lambda (nargs id ctx)
65 (gen-instruction (list 'call-toplevel id) nargs 1 ctx)))
67 (define gen-jump-toplevel
68 (lambda (nargs id ctx)
69 (gen-instruction (list 'jump-toplevel id) nargs 1 ctx)))
73 (gen-instruction (list 'goto label) 0 0 ctx)))
75 (define gen-goto-if-false
76 (lambda (label-false label-true ctx)
77 (gen-instruction (list 'goto-if-false label-false label-true) 1 0 ctx)))
80 (lambda (label-entry ctx)
81 (gen-instruction (list 'closure label-entry) 1 1 ctx)))
84 (lambda (id nargs unspec-result? ctx)
88 (if unspec-result? 0 1)
94 (gen-instruction (list 'shift) 1 0 (gen-shift (- n 1) ctx))
99 (gen-instruction (list 'pop) 1 0 ctx)))
103 (let ((ss (stack-size (env-local (context-env ctx)))))
104 (gen-instruction (list 'return) ss 0 ctx))))
106 ;-----------------------------------------------------------------------------
110 (car (node-children node))))
114 (cadr (node-children node))))
118 (caddr (node-children node))))
123 (cond ((or (cst? node)
129 (let ((var (def-var node)))
130 (if (toplevel-prc-with-non-rest-correct-calls? var)
131 (comp-prc (child1 node) #f ctx)
132 (if (var-needed? var)
133 (let ((ctx2 (comp-push (child1 node) ctx)))
134 (gen-set-global (var-id var) ctx2))
135 (comp-none (child1 node) ctx)))))
138 (let ((var (set-var node)))
139 (if (var-needed? var)
140 (let ((ctx2 (comp-push (child1 node) ctx)))
141 (gen-set-global (var-id var) ctx2))
142 (comp-none (child1 node) ctx))))
146 (context-make-label ctx))
148 (context-last-label ctx2))
150 (context-make-label ctx2))
152 (context-last-label ctx3))
154 (context-make-label ctx3))
156 (context-last-label ctx4))
158 (context-make-label ctx4))
160 (context-last-label ctx5))
162 (context-make-label ctx5))
164 (context-last-label ctx6))
166 (comp-test (child1 node) label-then label-else ctx6))
170 (comp-none (child3 node)
172 (context-add-bb ctx7 label-else)
177 (comp-none (child2 node)
179 (context-add-bb ctx8 label-then)
180 (context-env2 ctx7)))))
184 (context-add-bb ctx9 label-else-join)))
188 (context-add-bb ctx10 label-then-join)))
190 (context-add-bb ctx11 label-join)))
194 (comp-call node 'none ctx))
197 (let ((children (node-children node)))
200 (let loop ((lst children)
202 (if (null? (cdr lst))
203 (comp-none (car lst) ctx)
205 (comp-none (car lst) ctx)))))))
208 (compiler-error "unknown expression type" node)))))
213 (cond ((or (cst? node)
220 (gen-return (comp-push node ctx)))
224 (context-make-label ctx))
226 (context-last-label ctx2))
228 (context-make-label ctx2))
230 (context-last-label ctx3))
232 (comp-test (child1 node) label-then label-else ctx3))
234 (comp-tail (child3 node)
236 (context-add-bb ctx4 label-else)
239 (comp-tail (child2 node)
241 (context-add-bb ctx5 label-then)
242 (context-env2 ctx4)))))
246 (comp-call node 'tail ctx))
249 (let ((children (node-children node)))
251 (gen-return (gen-push-unspecified ctx))
252 (let loop ((lst children)
254 (if (null? (cdr lst))
255 (comp-tail (car lst) ctx)
257 (comp-none (car lst) ctx)))))))
260 (compiler-error "unknown expression type" node)))))
266 (display "--------------\n")
267 (pp (node->expr node))
273 (let ((val (cst-val node)))
274 (gen-push-constant val ctx)))
277 (let ((var (ref-var node)))
278 (if (var-global? var)
279 (if (null? (var-defs var))
280 (compiler-error "undefined variable:" (var-id var))
281 (let ((val (child1 (car (var-defs var)))))
282 (if (and (not (mutable-var? var))
283 (cst? val)) ;; immutable global, counted as cst
284 (gen-push-constant (cst-val val) ctx)
285 (gen-push-global (var-id var) ctx))))
286 (gen-push-local-var (var-id var) ctx))))
290 (gen-push-unspecified (comp-none node ctx)))
294 (context-make-label ctx))
296 (context-last-label ctx2))
298 (context-make-label ctx2))
300 (context-last-label ctx3))
302 (context-make-label ctx3))
304 (context-last-label ctx4))
306 (context-make-label ctx4))
308 (context-last-label ctx5))
310 (context-make-label ctx5))
312 (context-last-label ctx6))
314 (comp-test (child1 node) label-then label-else ctx6))
318 (comp-push (child3 node)
320 (context-add-bb ctx7 label-else)
325 (comp-push (child2 node)
327 (context-add-bb ctx8 label-then)
328 (context-env2 ctx7)))))
332 (context-add-bb ctx9 label-else-join)))
336 (context-add-bb ctx10 label-then-join)))
338 (context-add-bb ctx11 label-join)))
342 (comp-prc node #t ctx))
345 (comp-call node 'push ctx))
348 (let ((children (node-children node)))
350 (gen-push-unspecified ctx)
351 (let loop ((lst children)
353 (if (null? (cdr lst))
354 (comp-push (car lst) ctx)
356 (comp-none (car lst) ctx)))))))
359 (compiler-error "unknown expression type" node)))))
361 (define (build-closure label-entry vars ctx)
363 (define (build vars ctx)
365 (gen-push-constant '() ctx)
370 (gen-push-local-var (car vars) ctx)))))
373 (gen-closure label-entry
374 (gen-push-constant '() ctx))
375 (gen-closure label-entry
379 (lambda (node closure? ctx)
381 (context-make-label ctx))
383 (context-last-label ctx2))
385 (context-make-label ctx2))
387 (context-last-label ctx3))
392 (build-closure label-entry (env-closed body-env) ctx3)
395 (gen-goto label-continue ctx4))
397 (gen-entry (length (prc-params node))
399 (context-add-bb (context-change-env ctx5
403 (comp-tail (child1 node) ctx6)))
404 (prc-entry-label-set! node label-entry)
405 (context-add-bb (context-change-env ctx7 (context-env ctx5))
409 (lambda (node reason ctx)
410 (let* ((op (child1 node))
411 (args (cdr (node-children node)))
412 (nargs (length args)))
413 (let loop ((lst args)
417 (let ((arg (car lst)))
419 (comp-push arg ctx)))
421 (cond ((and (ref? op)
422 (var-primitive (ref-var op)))
423 (let* ((var (ref-var op))
425 (primitive (var-primitive var))
426 (prim-nargs (primitive-nargs primitive)))
430 (cond ((eq? reason 'tail)
432 (if (primitive-unspecified-result? primitive)
433 (gen-push-unspecified ctx2)
436 (if (primitive-unspecified-result? primitive)
437 (gen-push-unspecified ctx2)
440 (if (primitive-unspecified-result? primitive)
445 (if (primitive-inliner primitive)
446 ((primitive-inliner primitive) ctx)
448 (not (= nargs prim-nargs))
450 "primitive called with wrong number of arguments"
455 (primitive-unspecified-result? primitive)
460 (toplevel-prc-with-non-rest-correct-calls?
464 (cond ((eq? reason 'tail)
465 (gen-jump-toplevel nargs prc ctx))
467 (gen-call-toplevel nargs prc ctx))
469 (gen-pop (gen-call-toplevel nargs prc ctx))))))
472 (let ((ctx2 (comp-push op ctx)))
473 (cond ((eq? reason 'tail)
474 (gen-jump nargs ctx2))
476 (gen-call nargs ctx2))
478 (gen-pop (gen-call nargs ctx2))))))))))))
481 (lambda (node label-true label-false ctx)
485 (let ((val (cst-val node)))
490 (context-change-env2 ctx2 (context-env ctx2))))
499 (comp-push node ctx))
501 (gen-goto-if-false label-false label-true ctx2)))
502 (context-change-env2 ctx3 (context-env ctx3))))
506 (gen-goto label-true ctx)))
507 (context-change-env2 ctx2 (context-env ctx2))))
510 (compiler-error "unknown expression type" node)))))
512 ;-----------------------------------------------------------------------------
514 (define toplevel-prc?
516 (and (not (mutable-var? var))
517 (let ((d (var-defs var)))
520 (let ((val (child1 (car d))))
524 (define toplevel-prc-with-non-rest-correct-calls?
526 (let ((prc (toplevel-prc? var)))
528 (not (prc-rest? prc))
530 (let ((parent (node-parent r)))
532 (eq? (child1 parent) r)
533 (= (length (prc-params prc))
534 (- (length (node-children parent)) 1)))))
540 (not (null? (var-sets var)))))
546 (varset->list (fv node))))))
548 (define non-global-fv
551 (keep (lambda (x) (not (var-global? x)))
552 (varset->list (fv node))))))
559 (let ((var (ref-var node)))
560 (varset-singleton var)))
562 (let ((var (def-var node))
565 (varset-singleton var)
568 (let ((var (set-var node))
571 (varset-singleton var)
574 (let ((a (list-ref (node-children node) 0))
575 (b (list-ref (node-children node) 1))
576 (c (list-ref (node-children node) 2)))
577 (varset-union-multi (list (fv a) (fv b) (fv c)))))
579 (let ((body (list-ref (node-children node) 0)))
582 (build-params-varset (prc-params node)))))
584 (varset-union-multi (map fv (node-children node))))
586 (varset-union-multi (map fv (node-children node))))
588 (compiler-error "unknown expression type" node)))))
590 (define build-params-varset
592 (list->varset params)))
594 (define mark-needed-global-vars!
595 (lambda (global-env node)
598 (env-lookup global-env '#%readyq))
602 (if (and (var-global? var)
603 (not (var-needed? var))
604 ;; globals that obey the following conditions are considered
606 (not (and (not (mutable-var? var))
607 ;; to weed out primitives, which have no definitions
608 (> (length (var-defs var)) 0)
609 (cst? (child1 (car (var-defs var)))))))
611 (var-needed?-set! var #t)
614 (let ((val (child1 def)))
615 (if (side-effect-less? val)
621 (env-lookup global-env '#%start-first-process))
623 (env-lookup global-env '#%exit))))))))
625 (define side-effect-less?
635 (let ((var (ref-var node)))
638 (let ((var (def-var node))
640 (if (not (side-effect-less? val))
643 (let ((var (set-var node))
647 (let ((a (list-ref (node-children node) 0))
648 (b (list-ref (node-children node) 1))
649 (c (list-ref (node-children node) 2)))
654 (let ((body (list-ref (node-children node) 0)))
657 (for-each mark! (node-children node)))
659 (for-each mark! (node-children node)))
661 (compiler-error "unknown expression type" node)))))
666 ;-----------------------------------------------------------------------------
670 (define (varset-empty) ; return the empty set
673 (define (varset-singleton x) ; create a set containing only 'x'
676 (define (list->varset lst) ; convert list to set
679 (define (varset->list set) ; convert set to list
682 (define (varset-size set) ; return cardinality of set
685 (define (varset-empty? set) ; is 'x' the empty set?
688 (define (varset-member? x set) ; is 'x' a member of the 'set'?
689 (and (not (null? set))
690 (or (eq? x (car set))
691 (varset-member? x (cdr set)))))
693 (define (varset-adjoin set x) ; add the element 'x' to the 'set'
694 (if (varset-member? x set) set (cons x set)))
696 (define (varset-remove set x) ; remove the element 'x' from 'set'
702 (cons (car set) (varset-remove (cdr set) x)))))
704 (define (varset-equal? s1 s2) ; are 's1' and 's2' equal sets?
705 (and (varset-subset? s1 s2)
706 (varset-subset? s2 s1)))
708 (define (varset-subset? s1 s2) ; is 's1' a subset of 's2'?
711 ((varset-member? (car s1) s2)
712 (varset-subset? (cdr s1) s2))
716 (define (varset-difference set1 set2) ; return difference of sets
719 ((varset-member? (car set1) set2)
720 (varset-difference (cdr set1) set2))
722 (cons (car set1) (varset-difference (cdr set1) set2)))))
724 (define (varset-union set1 set2) ; return union of sets
725 (define (union s1 s2)
728 ((varset-member? (car s1) s2)
731 (cons (car s1) (union (cdr s1) s2)))))
732 (if (varset-smaller? set1 set2)
736 (define (varset-intersection set1 set2) ; return intersection of sets
737 (define (intersection s1 s2)
740 ((varset-member? (car s1) s2)
741 (cons (car s1) (intersection (cdr s1) s2)))
743 (intersection (cdr s1) s2))))
744 (if (varset-smaller? set1 set2)
745 (intersection set1 set2)
746 (intersection set2 set1)))
748 (define (varset-intersects? set1 set2) ; do sets 'set1' and 'set2' intersect?
749 (not (varset-empty? (varset-intersection set1 set2))))
751 (define (varset-smaller? set1 set2)
756 (varset-smaller? (cdr set1) (cdr set2)))))
758 (define (varset-union-multi sets)
761 (n-ary varset-union (car sets) (cdr sets))))
763 (define (n-ary function first rest)
766 (n-ary function (function first (car rest)) (cdr rest))))
768 ;------------------------------------------------------------------------------
772 (let ((v (make-vector (+ (code-last-label code) 1))))
775 (vector-set! v (bb-label bb) bb))
779 (define bbs->ref-counts
781 (let ((ref-counts (make-vector (vector-length bbs) 0)))
785 (let ((ref-count (vector-ref ref-counts label)))
786 (vector-set! ref-counts label (+ ref-count 1))
788 (let* ((bb (vector-ref bbs label))
789 (rev-instrs (bb-rev-instrs bb)))
792 (let ((opcode (car instr)))
793 (cond ((eq? opcode 'goto)
794 (visit (cadr instr)))
795 ((eq? opcode 'goto-if-false)
797 (visit (caddr instr)))
798 ((or (eq? opcode 'closure)
799 (eq? opcode 'call-toplevel)
800 (eq? opcode 'jump-toplevel))
801 (visit (cadr instr))))))
808 (define resolve-toplevel-labels!
811 (if (< i (vector-length bbs))
812 (let* ((bb (vector-ref bbs i))
813 (rev-instrs (bb-rev-instrs bb)))
817 (let ((opcode (car instr)))
818 (cond ((eq? opcode 'call-toplevel)
820 (prc-entry-label (cadr instr))))
821 ((eq? opcode 'jump-toplevel)
823 (prc-entry-label (cadr instr))))
829 (define tighten-jump-cascades!
831 (let ((ref-counts (bbs->ref-counts bbs)))
835 (let* ((bb (vector-ref bbs label))
836 (rev-instrs (bb-rev-instrs bb)))
837 (and (or (null? (cdr rev-instrs))
838 (= (vector-ref ref-counts label) 1))
844 (if (< i (vector-length bbs))
845 (if (> (vector-ref ref-counts i) 0)
846 (let* ((bb (vector-ref bbs i))
847 (rev-instrs (bb-rev-instrs bb))
848 (jump (car rev-instrs))
850 (cond ((eq? opcode 'goto)
851 (let* ((label (cadr jump))
852 (jump-replacement (resolve label)))
858 (make-bb (bb-label bb)
859 (append jump-replacement
865 ((eq? opcode 'goto-if-false)
866 (let* ((label-then (cadr jump))
867 (label-else (caddr jump))
868 (jump-then-replacement (resolve label-then))
869 (jump-else-replacement (resolve label-else)))
870 (if (and jump-then-replacement
871 (null? (cdr jump-then-replacement))
872 jump-else-replacement
873 (null? (cdr jump-else-replacement))
874 (or (eq? (caar jump-then-replacement)
876 (eq? (caar jump-else-replacement)
887 (if (eq? (caar jump-then-replacement)
889 (cadar jump-then-replacement)
891 (if (eq? (caar jump-else-replacement)
893 (cadar jump-else-replacement)
908 (define remove-useless-bbs!
910 (let ((ref-counts (bbs->ref-counts bbs)))
911 (let loop1 ((label 0) (new-label 0))
912 (if (< label (vector-length bbs))
913 (if (> (vector-ref ref-counts label) 0)
914 (let ((bb (vector-ref bbs label)))
918 (make-bb new-label (bb-rev-instrs bb)))
919 (loop1 (+ label 1) (+ new-label 1)))
920 (loop1 (+ label 1) new-label))
921 (renumber-labels bbs ref-counts new-label))))))
923 (define renumber-labels
924 (lambda (bbs ref-counts n)
925 (let ((new-bbs (make-vector n)))
926 (let loop2 ((label 0))
927 (if (< label (vector-length bbs))
928 (if (> (vector-ref ref-counts label) 0)
929 (let* ((bb (vector-ref bbs label))
930 (new-label (bb-label bb))
931 (rev-instrs (bb-rev-instrs bb)))
938 (bb-label (vector-ref bbs label))))
940 (let ((opcode (car instr)))
941 (cond ((eq? opcode 'closure)
943 (new-label (cadr instr))))
944 ((eq? opcode 'call-toplevel)
946 (new-label (cadr instr))))
947 ((eq? opcode 'jump-toplevel)
949 (new-label (cadr instr))))
952 (new-label (cadr instr))))
953 ((eq? opcode 'goto-if-false)
955 (new-label (cadr instr))
956 (new-label (caddr instr))))
963 (make-bb new-label (map fix rev-instrs)))
970 (let* ((done (make-vector (vector-length bbs) #f)))
974 (not (vector-ref done label))))
977 (lambda (instrs todo)
979 (let* ((instr (car instrs))
980 (opcode (car instr)))
981 (cond ((or (eq? opcode 'closure)
982 (eq? opcode 'call-toplevel)
983 (eq? opcode 'jump-toplevel))
984 (label-refs (cdr instrs) (cons (cadr instr) todo)))
986 (label-refs (cdr instrs) todo))))
989 (define schedule-here
990 (lambda (label new-label todo cont)
991 (let* ((bb (vector-ref bbs label))
992 (rev-instrs (bb-rev-instrs bb))
993 (jump (car rev-instrs))
995 (new-todo (label-refs rev-instrs todo)))
996 (vector-set! bbs label (make-bb new-label rev-instrs))
997 (vector-set! done label #t)
998 (cond ((eq? opcode 'goto)
999 (let ((label (cadr jump)))
1000 (if (unscheduled? label)
1001 (schedule-here label
1005 (cont (+ new-label 1)
1007 ((eq? opcode 'goto-if-false)
1008 (let ((label-then (cadr jump))
1009 (label-else (caddr jump)))
1010 (cond ((unscheduled? label-else)
1011 (schedule-here label-else
1013 (cons label-then new-todo)
1015 ((unscheduled? label-then)
1016 (schedule-here label-then
1021 (cont (+ new-label 1)
1024 (cont (+ new-label 1)
1027 (define schedule-somewhere
1028 (lambda (label new-label todo cont)
1029 (schedule-here label new-label todo cont)))
1031 (define schedule-todo
1032 (lambda (new-label todo)
1034 (let ((label (car todo)))
1035 (if (unscheduled? label)
1036 (schedule-somewhere label
1040 (schedule-todo new-label
1044 (schedule-here 0 0 '() schedule-todo)
1046 (renumber-labels bbs
1047 (make-vector (vector-length bbs) 1)
1048 (vector-length bbs)))))
1052 (let loop ((label (- (vector-length bbs) 1))
1055 (let* ((bb (vector-ref bbs label))
1056 (rev-instrs (bb-rev-instrs bb))
1057 (jump (car rev-instrs))
1058 (opcode (car jump)))
1063 (cond ((eq? opcode 'goto)
1064 (if (= (cadr jump) (+ label 1))
1067 ((eq? opcode 'goto-if-false)
1068 (cond ((= (caddr jump) (+ label 1))
1069 (cons (list 'goto-if-false (cadr jump))
1071 ((= (cadr jump) (+ label 1))
1072 (cons (list 'goto-if-not-false (caddr jump))
1075 (cons (list 'goto (caddr jump))
1076 (cons (list 'goto-if-false (cadr jump))
1077 (cdr rev-instrs))))))
1083 (define optimize-code
1085 (let ((bbs (code->vector code)))
1086 (resolve-toplevel-labels! bbs)
1087 (tighten-jump-cascades! bbs)
1088 (let ((bbs (remove-useless-bbs! bbs)))