diff --git a/module/Makefile.am b/module/Makefile.am index bf706b992..d144b798b 100644 --- a/module/Makefile.am +++ b/module/Makefile.am @@ -154,6 +154,7 @@ CPS2_LANG_SOURCES = \ language/cps2/dce.scm \ language/cps2/effects-analysis.scm \ language/cps2/elide-values.scm \ + language/cps2/prune-bailouts.scm \ language/cps2/prune-top-level-scopes.scm \ language/cps2/renumber.scm \ language/cps2/optimize.scm \ diff --git a/module/language/cps2/optimize.scm b/module/language/cps2/optimize.scm index 151196f76..adae8bb94 100644 --- a/module/language/cps2/optimize.scm +++ b/module/language/cps2/optimize.scm @@ -29,6 +29,7 @@ #:use-module (language cps2 dce) #:use-module (language cps2 elide-values) #:use-module (language cps2 prune-top-level-scopes) + #:use-module (language cps2 prune-bailouts) #:use-module (language cps2 simplify) #:use-module (language cps2 specialize-primcalls) #:export (optimize)) @@ -45,7 +46,7 @@ (pass program) program))) - ;; This series of assignments to `env' used to be a series of let* + ;; This series of assignments to `program' used to be a series of let* ;; bindings of `program', as you would imagine. In compiled code this ;; is fine because the compiler is able to allocate all let*-bound ;; variable to the same slot, which also means that the garbage @@ -64,7 +65,7 @@ (run-pass! inline-constructors #:inline-constructors? #t) (run-pass! specialize-primcalls #:specialize-primcalls? #t) (run-pass! elide-values #:elide-values? #t) - ;; (run-pass! prune-bailouts #:prune-bailouts? #t) + (run-pass! prune-bailouts #:prune-bailouts? #t) ;; (run-pass! eliminate-common-subexpressions #:cse? #t) ;; (run-pass! type-fold #:type-fold? #t) ;; (run-pass! resolve-self-references #:resolve-self-references? #t) diff --git a/module/language/cps2/prune-bailouts.scm b/module/language/cps2/prune-bailouts.scm new file mode 100644 index 000000000..f33d2aeb4 --- /dev/null +++ b/module/language/cps2/prune-bailouts.scm @@ -0,0 +1,86 @@ +;;; 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: +;;; +;;; A pass that prunes successors of expressions that bail out. +;;; +;;; Code: + +(define-module (language cps2 prune-bailouts) + #:use-module (ice-9 match) + #:use-module (language cps2) + #:use-module (language cps2 utils) + #:use-module (language cps2 with-cps) + #:use-module (language cps intmap) + #:use-module (language cps intset) + #:export (prune-bailouts)) + +(define (compute-tails conts) + "For each LABEL->CONT entry in the intmap CONTS, compute a +LABEL->TAIL-LABEL indicating the tail continuation of each expression's +containing function. In some cases TAIL-LABEL might not be available, +for example if there is a stale $kfun pointing at a body, or for +unreferenced terms. In that case TAIL-LABEL is either absent or #f." + (intmap-fold + (lambda (label cont out) + (match cont + (($ $kfun src meta self tail clause) + (intset-fold (lambda (label out) + (intmap-add out label tail (lambda (old new) #f))) + (compute-function-body conts label) + out)) + (_ out))) + conts + empty-intmap)) + +(define (prune-bailout out tails k src exp) + (match (intmap-ref out k) + (($ $ktail) + (with-cps out #f)) + (_ + (match (intmap-ref tails k (lambda (_) #f)) + (#f + (with-cps out #f)) + (ktail + (with-cps out + (letv prim rest) + (letk kresult ($kargs ('rest) (rest) + ($continue ktail src ($values ())))) + (letk kreceive ($kreceive '() 'rest kresult)) + (build-term ($continue kreceive src ,exp)))))))) + +(define (prune-bailouts conts) + (let ((tails (compute-tails conts))) + (with-fresh-name-state conts + (persistent-intmap + (intmap-fold + (lambda (label cont out) + (match cont + (($ $kargs names vars + ($ $continue k src + (and exp ($ $primcall (or 'error 'scm-error 'throw))))) + (call-with-values (lambda () (prune-bailout out tails k src exp)) + (lambda (out term) + (if term + (let ((cont (build-cont ($kargs names vars ,term)))) + (intmap-replace! out label cont)) + out)))) + (_ out))) + conts + conts)))))