diff options
Diffstat (limited to 'module/language/cps/dce.scm')
-rw-r--r-- | module/language/cps/dce.scm | 363 |
1 files changed, 0 insertions, 363 deletions
diff --git a/module/language/cps/dce.scm b/module/language/cps/dce.scm deleted file mode 100644 index 34ffc3a47..000000000 --- a/module/language/cps/dce.scm +++ /dev/null @@ -1,363 +0,0 @@ -;;; Continuation-passing style (CPS) intermediate language (IL) - -;; Copyright (C) 2013, 2014, 2015 Free Software Foundation, Inc. - -;;;; This library is free software; you can redistribute it and/or -;;;; modify it under the terms of the GNU Lesser General Public -;;;; License as published by the Free Software Foundation; either -;;;; version 3 of the License, or (at your option) any later version. -;;;; -;;;; This library is distributed in the hope that it will be useful, -;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;;;; Lesser General Public License for more details. -;;;; -;;;; You should have received a copy of the GNU Lesser General Public -;;;; License along with this library; if not, write to the Free Software -;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -;;; Commentary: -;;; -;;; Various optimizations can inline calls from one continuation to some -;;; other continuation, usually in response to information about the -;;; return arity of the call. That leaves us with dangling -;;; continuations that aren't reachable any more from the procedure -;;; entry. This pass will remove them. -;;; -;;; This pass also kills dead expressions: code that has no side -;;; effects, and whose value is unused. It does so by marking all live -;;; values, and then discarding other values as dead. This happens -;;; recursively through procedures, so it should be possible to elide -;;; dead procedures as well. -;;; -;;; Code: - -(define-module (language cps dce) - #:use-module (ice-9 match) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-9) - #:use-module (language cps) - #:use-module (language cps dfg) - #:use-module (language cps effects-analysis) - #:use-module (language cps renumber) - #:use-module (language cps types) - #:export (eliminate-dead-code)) - -(define-record-type $fun-data - (make-fun-data min-label effects live-conts defs) - fun-data? - (min-label fun-data-min-label) - (effects fun-data-effects) - (live-conts fun-data-live-conts) - (defs fun-data-defs)) - -(define (compute-defs dfg min-label label-count) - (define (cont-defs k) - (match (lookup-cont k dfg) - (($ $kargs names vars) vars) - (_ #f))) - (define (idx->label idx) (+ idx min-label)) - (let ((defs (make-vector label-count #f))) - (let lp ((n 0)) - (when (< n label-count) - (vector-set! - defs - n - (match (lookup-cont (idx->label n) dfg) - (($ $kargs _ _ body) - (match (find-call body) - (($ $continue k src exp) - (match exp - (($ $branch) #f) - (_ (cont-defs k)))))) - (($ $kreceive arity kargs) - (cont-defs kargs)) - (($ $kclause arity ($ $cont kargs ($ $kargs names syms))) - syms) - (($ $kfun src meta self) (list self)) - (($ $ktail) #f))) - (lp (1+ n)))) - defs)) - -(define (elide-type-checks! fun dfg effects min-label label-count) - (match fun - (($ $cont kfun ($ $kfun src meta min-var)) - (let ((typev (infer-types fun dfg))) - (define (idx->label idx) (+ idx min-label)) - (define (var->idx var) (- var min-var)) - (define (visit-primcall lidx fx name args) - (when (primcall-types-check? typev (idx->label lidx) name args) - (vector-set! effects lidx - (logand fx (lognot &type-check))))) - (let lp ((lidx 0)) - (when (< lidx label-count) - (let ((fx (vector-ref effects lidx))) - (unless (causes-all-effects? fx) - (when (causes-effect? fx &type-check) - (match (lookup-cont (idx->label lidx) dfg) - (($ $kargs _ _ term) - (match (find-call term) - (($ $continue k src ($ $primcall name args)) - (visit-primcall lidx fx name args)) - (($ $continue k src ($ $branch _ ($primcall name args))) - (visit-primcall lidx fx name args)) - (_ #f))) - (_ #f))))) - (lp (1+ lidx)))))))) - -(define (compute-live-code fun) - (let* ((fun-data-table (make-hash-table)) - (dfg (compute-dfg fun #:global? #t)) - (live-vars (make-bitvector (dfg-var-count dfg) #f)) - (changed? #f)) - (define (mark-live! var) - (unless (value-live? var) - (set! changed? #t) - (bitvector-set! live-vars var #t))) - (define (value-live? var) - (bitvector-ref live-vars var)) - (define (ensure-fun-data fun) - (or (hashq-ref fun-data-table fun) - (call-with-values (lambda () - ((make-local-cont-folder label-count max-label) - (lambda (k cont label-count max-label) - (values (1+ label-count) (max k max-label))) - fun 0 -1)) - (lambda (label-count max-label) - (let* ((min-label (- (1+ max-label) label-count)) - (effects (compute-effects dfg min-label label-count)) - (live-conts (make-bitvector label-count #f)) - (defs (compute-defs dfg min-label label-count)) - (fun-data (make-fun-data - min-label effects live-conts defs))) - (elide-type-checks! fun dfg effects min-label label-count) - (hashq-set! fun-data-table fun fun-data) - (set! changed? #t) - fun-data))))) - (define (visit-fun fun) - (match (ensure-fun-data fun) - (($ $fun-data min-label effects live-conts defs) - (define (idx->label idx) (+ idx min-label)) - (define (label->idx label) (- label min-label)) - (define (known-allocation? var dfg) - (match (lookup-predecessors (lookup-def var dfg) dfg) - ((def-exp-k) - (match (lookup-cont def-exp-k dfg) - (($ $kargs _ _ term) - (match (find-call term) - (($ $continue k src ($ $values (var))) - (known-allocation? var dfg)) - (($ $continue k src ($ $primcall)) - (let ((kidx (label->idx def-exp-k))) - (and (>= kidx 0) - (causes-effect? (vector-ref effects kidx) - &allocation)))) - (_ #f))) - (_ #f))) - (_ #f))) - (define (visit-grey-exp n exp) - (let ((defs (vector-ref defs n)) - (fx (vector-ref effects n))) - (or - ;; No defs; perhaps continuation is $ktail. - (not defs) - ;; Do we have a live def? - (or-map value-live? defs) - ;; Does this expression cause all effects? If so, it's - ;; definitely live. - (causes-all-effects? fx) - ;; Does it cause a type check, but we weren't able to - ;; prove that the types check? - (causes-effect? fx &type-check) - ;; We might have a setter. If the object being assigned - ;; to is live or was not created by us, then this - ;; expression is live. Otherwise the value is still dead. - (and (causes-effect? fx &write) - (match exp - (($ $primcall - (or 'vector-set! 'vector-set!/immediate - 'set-car! 'set-cdr! - 'box-set!) - (obj . _)) - (or (value-live? obj) - (not (known-allocation? obj dfg)))) - (_ #t)))))) - (let lp ((n (1- (vector-length effects)))) - (unless (< n 0) - (let ((cont (lookup-cont (idx->label n) dfg))) - (match cont - (($ $kargs _ _ body) - (let lp ((body body)) - (match body - (($ $letk conts body) (lp body)) - (($ $continue k src exp) - (unless (bitvector-ref live-conts n) - (when (visit-grey-exp n exp) - (set! changed? #t) - (bitvector-set! live-conts n #t))) - (when (bitvector-ref live-conts n) - (match exp - ((or ($ $const) ($ $prim)) - #f) - (($ $fun body) - (visit-fun body)) - (($ $rec names syms funs) - (for-each (lambda (sym fun) - (when (value-live? sym) - (match fun - (($ $fun body) - (visit-fun body))))) - syms funs)) - (($ $prompt escape? tag handler) - (mark-live! tag)) - (($ $call proc args) - (mark-live! proc) - (for-each mark-live! args)) - (($ $callk k proc args) - (mark-live! proc) - (for-each mark-live! args)) - (($ $primcall name args) - (for-each mark-live! args)) - (($ $branch k ($ $primcall name args)) - (for-each mark-live! args)) - (($ $branch k ($ $values (arg))) - (mark-live! arg)) - (($ $values args) - (match (vector-ref defs n) - (#f (for-each mark-live! args)) - (defs (for-each (lambda (use def) - (when (value-live? def) - (mark-live! use))) - args defs)))))))))) - (($ $kreceive arity kargs) #f) - (($ $kclause arity ($ $cont kargs ($ $kargs names syms body))) - (for-each mark-live! syms)) - (($ $kfun src meta self) - (mark-live! self)) - (($ $ktail) #f)) - (lp (1- n)))))))) - (unless (= (dfg-var-count dfg) (var-counter)) - (error "internal error" (dfg-var-count dfg) (var-counter))) - (let lp () - (set! changed? #f) - (visit-fun fun) - (when changed? (lp))) - (values fun-data-table live-vars))) - -(define (process-eliminations fun fun-data-table live-vars) - (define (value-live? var) - (bitvector-ref live-vars var)) - (define (make-adaptor name k defs) - (let* ((names (map (lambda (_) 'tmp) defs)) - (syms (map (lambda (_) (fresh-var)) defs)) - (live (filter-map (lambda (def sym) - (and (value-live? def) - sym)) - defs syms))) - (build-cps-cont - (name ($kargs names syms - ($continue k #f ($values live))))))) - (define (visit-fun fun) - (match (hashq-ref fun-data-table fun) - (($ $fun-data min-label effects live-conts defs) - (define (label->idx label) (- label min-label)) - (define (visit-cont cont) - (match (visit-cont* cont) - ((cont) cont))) - (define (visit-cont* cont) - (match cont - (($ $cont label cont) - (match cont - (($ $kargs names syms body) - (match (filter-map (lambda (name sym) - (and (value-live? sym) - (cons name sym))) - names syms) - (((names . syms) ...) - (list - (build-cps-cont - (label ($kargs names syms - ,(visit-term body label)))))))) - (($ $kfun src meta self tail clause) - (list - (build-cps-cont - (label ($kfun src meta self ,tail - ,(and clause (visit-cont clause))))))) - (($ $kclause arity body alternate) - (list - (build-cps-cont - (label ($kclause ,arity - ,(visit-cont body) - ,(and alternate - (visit-cont alternate))))))) - (($ $kreceive ($ $arity req () rest () #f) kargs) - (let ((defs (vector-ref defs (label->idx label)))) - (if (and-map value-live? defs) - (list (build-cps-cont (label ,cont))) - (let-fresh (adapt) () - (list (make-adaptor adapt kargs defs) - (build-cps-cont - (label ($kreceive req rest adapt)))))))) - (_ (list (build-cps-cont (label ,cont)))))))) - (define (visit-conts conts) - (append-map visit-cont* conts)) - (define (visit-term term term-k) - (match term - (($ $letk conts body) - (let ((body (visit-term body term-k))) - (match (visit-conts conts) - (() body) - (conts (build-cps-term ($letk ,conts ,body)))))) - (($ $continue k src ($ $values args)) - (match (vector-ref defs (label->idx term-k)) - (#f term) - (defs - (let ((args (filter-map (lambda (use def) - (and (value-live? def) use)) - args defs))) - (build-cps-term - ($continue k src ($values args))))))) - (($ $continue k src exp) - (if (bitvector-ref live-conts (label->idx term-k)) - (match exp - (($ $fun body) - (build-cps-term - ($continue k src ($fun ,(visit-fun body))))) - (($ $rec names syms funs) - (rewrite-cps-term - (filter-map - (lambda (name sym fun) - (and (value-live? sym) - (match fun - (($ $fun body) - (list name - sym - (build-cps-exp - ($fun ,(visit-fun body)))))))) - names syms funs) - (() - ($continue k src ($values ()))) - (((names syms funs) ...) - ($continue k src ($rec names syms funs))))) - (_ - (match (vector-ref defs (label->idx term-k)) - ((or #f ((? value-live?) ...)) - (build-cps-term - ($continue k src ,exp))) - (syms - (let-fresh (adapt) () - (build-cps-term - ($letk (,(make-adaptor adapt k syms)) - ($continue adapt src ,exp)))))))) - (build-cps-term ($continue k src ($values ()))))))) - (visit-cont fun)))) - (visit-fun fun)) - -(define (eliminate-dead-code fun) - (call-with-values (lambda () (renumber fun)) - (lambda (fun nlabels nvars) - (parameterize ((label-counter nlabels) - (var-counter nvars)) - (call-with-values (lambda () (compute-live-code fun)) - (lambda (fun-data-table live-vars) - (process-eliminations fun fun-data-table live-vars))))))) |