From 6f6a6aee9d4b40d15aabbb39b4a53e3ef3f380d6 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 Jul 2015 07:44:30 +0200 Subject: [PATCH] Optimize first-order CPS * module/language/cps2/optimize.scm: Move comments here from cps/compile-bytecode.scm. * module/language/cps/compile-bytecode.scm: Remove optimization and closure conversion calls, since CPS2 does this for us. * module/language/cps2/compile-cps.scm (compile-cps): Use set! to save memory at bootstrap-time. Optimize first-order CPS, to get rid of strangeness introduced in closure conversion. --- module/language/cps/compile-bytecode.scm | 83 +----------------------- module/language/cps2/compile-cps.scm | 12 ++-- module/language/cps2/optimize.scm | 10 +++ 3 files changed, 20 insertions(+), 85 deletions(-) diff --git a/module/language/cps/compile-bytecode.scm b/module/language/cps/compile-bytecode.scm index cc696a92f..c07db2621 100644 --- a/module/language/cps/compile-bytecode.scm +++ b/module/language/cps/compile-bytecode.scm @@ -27,85 +27,19 @@ #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:use-module (language cps) - #:use-module (language cps closure-conversion) - #:use-module (language cps contification) - #:use-module (language cps constructors) - #:use-module (language cps cse) - #:use-module (language cps dce) #:use-module (language cps dfg) - #:use-module (language cps elide-values) #:use-module (language cps primitives) - #:use-module (language cps prune-bailouts) - #:use-module (language cps prune-top-level-scopes) #:use-module (language cps reify-primitives) #:use-module (language cps renumber) - #:use-module (language cps self-references) - #:use-module (language cps simplify) #:use-module (language cps slot-allocation) - #:use-module (language cps specialize-primcalls) - #:use-module (language cps type-fold) #:use-module (system vm assembler) #:export (compile-bytecode)) -;; TODO: Local var names. - (define (kw-arg-ref args kw default) (match (memq kw args) ((_ val . _) val) (_ default))) -(define (optimize exp opts) - (define (run-pass! pass kw default) - (set! exp - (if (kw-arg-ref opts kw default) - (pass exp) - exp))) - - ;; The first DCE pass is mainly to eliminate functions that aren't - ;; called. The last is mainly to eliminate rest parameters that - ;; aren't used, and thus shouldn't be consed. - - ;; This series of assignments to `env' used to be a series of let* - ;; bindings of `env', 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 - ;; collector doesn't have to retain so many copies of the term being - ;; optimized. However during bootstrap, the interpreter doesn't do - ;; this optimization, leading to excessive data retention as the terms - ;; are rewritten. To marginally improve bootstrap memory usage, here - ;; we use set! instead. The compiler should produce the same code in - ;; any case, though currently it does not because it doesn't do escape - ;; analysis on the box created for the set!. - - (run-pass! eliminate-dead-code #:eliminate-dead-code? #t) - ;; The prune-top-level-scopes pass doesn't work if CSE has run - ;; beforehand. Since hopefully we will be able to just remove all the - ;; old CPS stuff, let's just disable the pass for now. - ;; (run-pass! prune-top-level-scopes #:prune-top-level-scopes? #t) - (run-pass! simplify #:simplify? #t) - (run-pass! contify #:contify? #t) - (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! eliminate-common-subexpressions #:cse? #t) - (run-pass! type-fold #:type-fold? #t) - (run-pass! resolve-self-references #:resolve-self-references? #t) - (run-pass! eliminate-dead-code #:eliminate-dead-code? #t) - (run-pass! simplify #:simplify? #t) - - ;; Passes that are needed: - ;; - ;; * Abort contification: turning abort primcalls into continuation - ;; calls, and eliding prompts if possible. - ;; - ;; * Loop peeling. Unrolls the first round through a loop if the - ;; loop has effects that CSE can work on. Requires effects - ;; analysis. When run before CSE, loop peeling is the equivalent - ;; of loop-invariant code motion (LICM). - - exp) - (define (compile-fun f asm) (let* ((dfg (compute-dfg f #:global? #f)) (allocation (allocate-slots f dfg))) @@ -509,21 +443,8 @@ (compile-entry))))) (define (compile-bytecode exp env opts) - ;; See comment in `optimize' about the use of set!. - - ;; Since CPS2's optimization pass replaces CPS and uses less memory, - ;; we disable the optimization pass for now. We'll remove it once - ;; we're sure. - ;; - ;; (set! exp (optimize exp opts)) - - (set! exp (if (not (kw-arg-ref opts #:cps2-convert? #t)) - (convert-closures exp) - exp)) - ;; first-order optimization should go here - (set! exp (reify-primitives exp)) - (set! exp (renumber exp)) - (let* ((asm (make-assembler))) + (let* ((exp (renumber (reify-primitives exp))) + (asm (make-assembler))) (match exp (($ $program funs) (for-each (lambda (fun) (compile-fun fun asm)) diff --git a/module/language/cps2/compile-cps.scm b/module/language/cps2/compile-cps.scm index 4c0947be5..85b00c95c 100644 --- a/module/language/cps2/compile-cps.scm +++ b/module/language/cps2/compile-cps.scm @@ -117,7 +117,11 @@ (_ default))) (define (compile-cps exp env opts) - (let ((exp (optimize-higher-order-cps exp opts))) - (if (kw-arg-ref opts #:cps2-convert? #t) - (values (conts->fun* (renumber (convert-closures exp))) env env) - (values (conts->fun (renumber exp)) env env)))) + ;; Use set! to save memory at bootstrap-time. (The interpreter holds + ;; onto all free variables locally bound in a function, so if we used + ;; let*, we'd hold onto earlier copies of the term.) + (set! exp (optimize-higher-order-cps exp opts)) + (set! exp (convert-closures exp)) + (set! exp (optimize-first-order-cps exp opts)) + (set! exp (renumber exp)) + (values (conts->fun* exp) env env)) diff --git a/module/language/cps2/optimize.scm b/module/language/cps2/optimize.scm index 4a19a57b7..9e877b918 100644 --- a/module/language/cps2/optimize.scm +++ b/module/language/cps2/optimize.scm @@ -75,6 +75,16 @@ (verify program) program)) +;; Passes that are needed: +;; +;; * Abort contification: turning abort primcalls into continuation +;; calls, and eliding prompts if possible. +;; +;; * Loop peeling. Unrolls the first round through a loop if the +;; loop has effects that CSE can work on. Requires effects +;; analysis. When run before CSE, loop peeling is the equivalent +;; of loop-invariant code motion (LICM). +;; (define-optimizer optimize-higher-order-cps (split-rec #:split-rec? #t) (eliminate-dead-code #:eliminate-dead-code? #t)