summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el1
-rw-r--r--doc/ref/compiler.texi18
-rw-r--r--module/language/cps.scm13
-rw-r--r--module/language/cps/closure-conversion.scm15
-rw-r--r--module/language/cps/compile-bytecode.scm6
-rw-r--r--module/language/cps/contification.scm8
-rw-r--r--module/language/cps/cse.scm17
-rw-r--r--module/language/cps/dce.scm36
-rw-r--r--module/language/cps/devirtualize-integers.scm8
-rw-r--r--module/language/cps/effects-analysis.scm1
-rw-r--r--module/language/cps/licm.scm7
-rw-r--r--module/language/cps/loop-instrumentation.scm6
-rw-r--r--module/language/cps/peel-loops.scm5
-rw-r--r--module/language/cps/renumber.scm7
-rw-r--r--module/language/cps/rotate-loops.scm6
-rw-r--r--module/language/cps/self-references.scm4
-rw-r--r--module/language/cps/simplify.scm11
-rw-r--r--module/language/cps/slot-allocation.scm8
-rw-r--r--module/language/cps/specialize-numbers.scm2
-rw-r--r--module/language/cps/split-rec.scm4
-rw-r--r--module/language/cps/type-fold.scm39
-rw-r--r--module/language/cps/types.scm19
-rw-r--r--module/language/cps/utils.scm10
-rw-r--r--module/language/cps/verify.scm33
24 files changed, 236 insertions, 48 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index ba48961aa..90257e7bf 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -40,6 +40,7 @@
(eval . (put '$letconst 'scheme-indent-function 1))
(eval . (put '$continue 'scheme-indent-function 2))
(eval . (put '$branch 'scheme-indent-function 3))
+ (eval . (put '$switch 'scheme-indent-function 3))
(eval . (put '$prompt 'scheme-indent-function 3))
(eval . (put '$kargs 'scheme-indent-function 2))
(eval . (put '$kfun 'scheme-indent-function 4))
diff --git a/doc/ref/compiler.texi b/doc/ref/compiler.texi
index 4c0348fab..27964e881 100644
--- a/doc/ref/compiler.texi
+++ b/doc/ref/compiler.texi
@@ -820,8 +820,8 @@ call target at run-time.
To summarize: a @code{$continue} is a CPS term that continues to a
single label. But there are other kinds of CPS terms that can continue
-to a different number of labels: @code{$branch}, @code{$throw}, and
-@code{$prompt}.
+to a different number of labels: @code{$branch}, @code{$switch},
+@code{$throw}, and @code{$prompt}.
@deftp {CPS Term} $branch kf kt src op param args
Evaluate the branching primcall @var{op}, with arguments @var{args} and
@@ -840,6 +840,19 @@ a test expression to a variable, and then make a @code{$branch} on a
the branch if possible.
@end deftp
+@deftp {CPS Term} $switch kf kt* src arg
+Continue to a label in the list @var{k*} according to the index argument
+@var{arg}, or to the default continuation @var{kf} if @var{arg} is
+greater than or equal to the length @var{k*}. The index variable
+@var{arg} is an unboxed, unsigned 64-bit value.
+
+The @code{$switch} term is like C's @code{switch} statement. The
+compiler to CPS can generate a @code{$switch} term directly, if the
+source language has such a concept, or it can rely on the CPS optimizer
+to turn appropriate chains of @code{$branch} statements to
+@code{$switch} instances, which is what the Scheme compiler does.
+@end deftp
+
@deftp {CPS Term} $throw src op param args
Throw a non-resumable exception. Throw terms do not continue at all.
The usual value of @var{op} is @code{throw}, with two arguments
@@ -967,6 +980,7 @@ below for full details.
@deffnx {Scheme Syntax} build-exp ($prompt escape? tag handler)
@deffnx {Scheme Syntax} build-term ($branch kf kt src op param (arg ...))
@deffnx {Scheme Syntax} build-term ($branch kf kt src op param args)
+@deffnx {Scheme Syntax} build-term ($switch kf kt* src arg)
@deffnx {Scheme Syntax} build-term ($throw src op param (arg ...))
@deffnx {Scheme Syntax} build-term ($throw src op param args)
@deffnx {Scheme Syntax} build-term ($prompt k kh src escape? tag)
diff --git a/module/language/cps.scm b/module/language/cps.scm
index 99efc7eb5..9682061c9 100644
--- a/module/language/cps.scm
+++ b/module/language/cps.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013, 2014, 2015, 2017, 2018 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2015,2017-2018,2020 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
@@ -127,7 +127,7 @@
$kreceive $kargs $kfun $ktail $kclause
;; Terms.
- $continue $branch $prompt $throw
+ $continue $branch $switch $prompt $throw
;; Expressions.
$const $prim $fun $rec $const-fun $code
@@ -180,6 +180,7 @@
;; Terms.
(define-cps-type $continue k src exp)
(define-cps-type $branch kf kt src op param args)
+(define-cps-type $switch kf kt* src arg)
(define-cps-type $prompt k kh src escape? tag)
(define-cps-type $throw src op param args)
@@ -221,7 +222,7 @@
(make-$kclause (build-arity arity) kbody kalternate))))
(define-syntax build-term
- (syntax-rules (unquote $continue $branch $prompt $throw)
+ (syntax-rules (unquote $continue $branch $switch $prompt $throw)
((_ (unquote exp))
exp)
((_ ($continue k src exp))
@@ -232,6 +233,8 @@
(make-$branch kf kt src op param (list arg ...)))
((_ ($branch kf kt src op param args))
(make-$branch kf kt src op param args))
+ ((_ ($switch kf kt* src arg))
+ (make-$switch kf kt* src arg))
((_ ($prompt k kh src escape? tag))
(make-$prompt k kh src escape? tag))
((_ ($throw src op param (unquote args)))
@@ -299,6 +302,8 @@
(build-term ($continue k (src exp) ,(parse-cps exp))))
(('branch kf kt op param arg ...)
(build-term ($branch kf kt (src exp) op param arg)))
+ (('switch kf (kt* ...) arg)
+ (build-term ($switch kf kt* (src exp) arg)))
(('prompt k kh escape? tag)
(build-term ($prompt k kh (src exp) escape? tag)))
(('throw op param arg ...)
@@ -350,6 +355,8 @@
`(continue ,k ,(unparse-cps exp)))
(($ $branch kf kt src op param args)
`(branch ,kf ,kt ,op ,param ,@args))
+ (($ $switch kf kt* src arg)
+ `(switch ,kf ,kt* ,arg))
(($ $prompt k kh src escape? tag)
`(prompt ,k ,kh ,escape? ,tag))
(($ $throw src op param args)
diff --git a/module/language/cps/closure-conversion.scm b/module/language/cps/closure-conversion.scm
index 17a81f674..a40d466bd 100644
--- a/module/language/cps/closure-conversion.scm
+++ b/module/language/cps/closure-conversion.scm
@@ -97,6 +97,8 @@ conts."
(add-uses args uses))))
(($ $kargs _ _ ($ $branch kf kt src op param args))
(add-uses args uses))
+ (($ $kargs _ _ ($ $switch kf kt* src arg))
+ (add-use arg uses))
(($ $kargs _ _ ($ $prompt k kh src escape? tag))
(add-use tag uses))
(($ $kargs _ _ ($ $throw src op param args))
@@ -118,6 +120,7 @@ conts."
(let-values (((single multiple) (ref k single multiple)))
(ref k* single multiple))
(ref1 k)))
+ (define (ref* k*) (fold2 ref k* single multiple))
(match (intmap-ref conts label)
(($ $kreceive arity k) (ref1 k))
(($ $kfun src meta self ktail kclause) (ref2 ktail kclause))
@@ -125,6 +128,7 @@ conts."
(($ $kclause arity kbody kalt) (ref2 kbody kalt))
(($ $kargs _ _ ($ $continue k)) (ref1 k))
(($ $kargs _ _ ($ $branch kf kt)) (ref2 kf kt))
+ (($ $kargs _ _ ($ $switch kf kt*)) (ref* (cons kf kt*)))
(($ $kargs _ _ ($ $prompt k kh)) (ref2 k kh))
(($ $kargs _ _ ($ $throw)) (ref0))))
(let*-values (((single multiple) (values empty-intset empty-intset))
@@ -259,6 +263,8 @@ shared closures to use the appropriate 'self' variable, if possible."
($continue k src ,(visit-exp exp)))
(($ $branch kf kt src op param args)
($branch kf kt src op param ,(map subst args)))
+ (($ $switch kf kt* src arg)
+ ($switch kf kt* src (subst arg)))
(($ $prompt k kh src escape? tag)
($prompt k kh src escape? (subst tag)))
(($ $throw src op param args)
@@ -386,6 +392,8 @@ references."
(add-uses args uses))))
(($ $branch kf kt src op param args)
(add-uses args uses))
+ (($ $switch kf kt* src arg)
+ (add-use arg uses))
(($ $prompt k kh src escape? tag)
(add-use tag uses))
(($ $throw src op param args)
@@ -826,6 +834,13 @@ bound to @var{var}, and continue to @var{k}."
(build-term
($branch kf kt src op param args))))))
+ (($ $switch kf kt* src arg)
+ (convert-arg cps arg
+ (lambda (cps arg)
+ (with-cps cps
+ (build-term
+ ($switch kf kt* src arg))))))
+
(($ $prompt k kh src escape? tag)
(convert-arg cps tag
(lambda (cps tag)
diff --git a/module/language/cps/compile-bytecode.scm b/module/language/cps/compile-bytecode.scm
index edf338d08..e7d8abc61 100644
--- a/module/language/cps/compile-bytecode.scm
+++ b/module/language/cps/compile-bytecode.scm
@@ -621,6 +621,12 @@
(compile-test label (skip-elided-conts (1+ label))
(forward-label kf) (forward-label kt)
op param args))
+ (($ $switch kf kt* src arg)
+ (when src
+ (emit-source asm src))
+ (emit-jtable asm (from-sp (slot arg))
+ (list->vector (map forward-label
+ (append kt* (list kf))))))
(($ $prompt k kh src escape? tag)
(when src
(emit-source asm src))
diff --git a/module/language/cps/contification.scm b/module/language/cps/contification.scm
index 7587fa3a7..031b0cd13 100644
--- a/module/language/cps/contification.scm
+++ b/module/language/cps/contification.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -62,6 +62,8 @@ predecessor."
(($ $kclause arity kbody kalt) (ref2 kbody kalt))
(($ $kargs names syms ($ $continue k)) (ref1 k))
(($ $kargs names syms ($ $branch kf kt)) (ref2 kf kt))
+ (($ $kargs names syms ($ $switch kf kt*))
+ (fold2 ref (cons kf kt*) single multiple))
(($ $kargs names syms ($ $prompt k kh)) (ref2 k kh))
(($ $kargs names syms ($ $throw)) (ref0))))
(let*-values (((single multiple) (values empty-intset empty-intset))
@@ -193,6 +195,8 @@ $call, and are always called with a compatible arity."
(exclude-vars functions args))))
(($ $kargs _ _ ($ $branch kf kt src op param args))
(exclude-vars functions args))
+ (($ $kargs _ _ ($ $switch kf kt* src arg))
+ (exclude-var functions arg))
(($ $kargs _ _ ($ $prompt k kh src escape? tag))
(exclude-var functions tag))
(($ $kargs _ _ ($ $throw src op param args))
@@ -465,7 +469,7 @@ function set."
(match term
(($ $continue k src exp)
(visit-exp cps k src exp))
- ((or ($ $branch) ($ $prompt) ($ $throw))
+ ((or ($ $branch) ($ $switch) ($ $prompt) ($ $throw))
(with-cps cps term))))
;; Renumbering is not strictly necessary but some passes may not be
diff --git a/module/language/cps/cse.scm b/module/language/cps/cse.scm
index 3cc48cdf7..1966467ec 100644
--- a/module/language/cps/cse.scm
+++ b/module/language/cps/cse.scm
@@ -114,12 +114,19 @@ false. It could be that both true and false proofs are available."
(propagate boolv succ1
(intset-add in (true-idx label)))))
(values (append changed0 changed1) boolv)))
+ (define (propagate* succs)
+ (fold2 (lambda (succ changed boolv)
+ (call-with-values (lambda () (propagate boolv succ in))
+ (lambda (changed* boolv)
+ (values (append changed* changed) boolv))))
+ succs '() boolv))
(match (intmap-ref conts label)
(($ $kargs names vars term)
(match term
(($ $continue k) (propagate1 k))
(($ $branch kf kt) (propagate-branch kf kt))
+ (($ $switch kf kt*) (propagate* (cons kf kt*)))
(($ $prompt k kh) (propagate2 k kh))
(($ $throw) (propagate0))))
(($ $kreceive arity k)
@@ -179,6 +186,8 @@ false. It could be that both true and false proofs are available."
($kargs names vals ($continue (rename k) src ,exp)))
(($ $kargs names vals ($ $branch kf kt src op param args))
($kargs names vals ($branch (rename kf) (rename kt) src op param args)))
+ (($ $kargs names vals ($ $switch kf kt* src arg))
+ ($kargs names vals ($switch (rename kf) (map rename kt*) src arg)))
(($ $kargs names vals ($ $prompt k kh src escape? tag))
($kargs names vals ($prompt (rename k) (rename kh) src escape? tag)))
(($ $kreceive ($ $arity req () rest () #f) kbody)
@@ -272,9 +281,12 @@ false. It could be that both true and false proofs are available."
(intmap-replace truthy-labels label bool-in)))))))
(define (term-successors term)
+ (define (list->intset ls)
+ (fold1 (lambda (elt set) (intset-add set elt)) ls empty-intset))
(match term
(($ $continue k) (intset k))
(($ $branch kf kt) (intset kf kt))
+ (($ $switch kf kt*) (list->intset (cons kf kt*)))
(($ $prompt k kh) (intset k kh))
(($ $throw) empty-intset)))
@@ -346,6 +358,7 @@ false. It could be that both true and false proofs are available."
(match term
(($ $continue k src exp) (compute-expr-key exp))
(($ $branch) (compute-branch-key term))
+ (($ $switch) #f)
(($ $prompt) #f)
(($ $throw) #f)))
@@ -424,6 +437,8 @@ false. It could be that both true and false proofs are available."
(rewrite-term term
(($ $branch kf kt src op param args)
($branch kf kt src op param ,(map subst-var args)))
+ (($ $switch kf kt* src arg)
+ ($switch kf kt* src (subst-var arg)))
(($ $continue k src exp)
($continue k src ,(rename-exp exp)))
(($ $prompt k kh src escape? tag)
@@ -530,7 +545,7 @@ false. It could be that both true and false proofs are available."
,(visit-exp label exp analysis)))))
substs
analysis))
- ((or ($ $prompt) ($ $throw))
+ ((or ($ $switch) ($ $prompt) ($ $throw))
(values (intmap-add! out label (build-cont ($kargs names vars ,term)))
substs
analysis)))))
diff --git a/module/language/cps/dce.scm b/module/language/cps/dce.scm
index 5be573d0e..aa52611af 100644
--- a/module/language/cps/dce.scm
+++ b/module/language/cps/dce.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -80,10 +80,11 @@ sites."
(causes-effect? fx &allocation))
(values (intset-add! known k) unknown)
(values known (intset-add! unknown k)))))
- (($ $kargs _ _ (or ($ $branch) ($ $prompt) ($ $throw)))
- ;; Branches and prompts pass no values to
- ;; their continuations, and throw terms don't
- ;; continue at all.
+ (($ $kargs _ _ (or ($ $branch) ($ $switch)
+ ($ $prompt) ($ $throw)))
+ ;; Branches, switches, and prompts pass no
+ ;; values to their continuations, and throw
+ ;; terms don't continue at all.
(values known unknown))
(($ $kreceive arity kargs)
(values known (intset-add! unknown kargs)))
@@ -204,7 +205,8 @@ sites."
;; Still dead.
(values live-labels live-vars))))
- (define (visit-branch label kf kt args live-labels live-vars)
+ ;; Note, this is for $branch or $switch.
+ (define (visit-branch label kf kt* args live-labels live-vars)
(define (next-live-term k)
;; FIXME: For a chain of dead branches, this is quadratic.
(let lp ((seen empty-intset) (k k))
@@ -216,12 +218,23 @@ sites."
(($ $kargs _ _ ($ $continue k*))
(lp (intset-add seen k) k*))
(_ k))))))
+ (define (distinct-continuations?)
+ (let ((kf' (next-live-term kf)))
+ (let lp ((kt* kt*))
+ (match kt*
+ (() #f)
+ ((kt . kt*)
+ (cond
+ ((or (eqv? kf kt)
+ (eqv? kf' (next-live-term kt)))
+ (lp kt*))
+ (else #t)))))))
(cond
((intset-ref live-labels label)
;; Branch live already.
(values live-labels (adjoin-vars args live-vars)))
((or (causes-effect? (intmap-ref effects label) &type-check)
- (not (eqv? (next-live-term kf) (next-live-term kt))))
+ (distinct-continuations?))
;; The branch is live if its continuations are not the same, or
;; if the branch itself causes type checks.
(values (intset-add live-labels label)
@@ -238,7 +251,9 @@ sites."
(($ $kargs _ _ ($ $continue k src exp))
(visit-exp label k exp live-labels live-vars))
(($ $kargs _ _ ($ $branch kf kt src op param args))
- (visit-branch label kf kt args live-labels live-vars))
+ (visit-branch label kf (list kt) args live-labels live-vars))
+ (($ $kargs _ _ ($ $switch kf kt* src arg))
+ (visit-branch label kf kt* (list arg) live-labels live-vars))
(($ $kargs _ _ ($ $prompt k kh src escape? tag))
;; Prompts need special elision passes that would contify
;; aborts and remove corresponding "unwind" primcalls.
@@ -357,6 +372,11 @@ sites."
;; Dead branches continue to the same continuation
;; (eventually).
(values cps (build-term ($continue kf src ($values ()))))))
+ (($ $switch kf kt* src arg)
+ ;; Same as in $branch case.
+ (if (label-live? label)
+ (values cps term)
+ (values cps (build-term ($continue kf src ($values ()))))))
(($ $prompt)
(values cps term))
(($ $throw)
diff --git a/module/language/cps/devirtualize-integers.scm b/module/language/cps/devirtualize-integers.scm
index e7efd2137..471ca81f9 100644
--- a/module/language/cps/devirtualize-integers.scm
+++ b/module/language/cps/devirtualize-integers.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2017-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2020 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
@@ -75,6 +75,8 @@
(add-uses use-counts args))))
(($ $branch kf kt src op param args)
(add-uses use-counts args))
+ (($ $switch kf kt* src arg)
+ (add-use use-counts arg))
(($ $prompt k kh src escape? tag)
(add-use use-counts tag))
(($ $throw src op param args)
@@ -191,6 +193,10 @@ the trace should be referenced outside of it."
label*))
(else
(fail)))))
+ (($ $switch)
+ ;; Don't know how to peel past a switch. The arg of a
+ ;; switch is unboxed anyway.
+ (fail))
(($ $continue k src exp)
(match exp
(($ $const)
diff --git a/module/language/cps/effects-analysis.scm b/module/language/cps/effects-analysis.scm
index f5021c86e..d9e883c4f 100644
--- a/module/language/cps/effects-analysis.scm
+++ b/module/language/cps/effects-analysis.scm
@@ -629,6 +629,7 @@ the LABELS that are clobbered by the effects of LABEL."
(expression-effects exp))
(($ $kargs names syms ($ $branch kf kt src op param args))
(primitive-effects param op args))
+ (($ $kargs names syms ($ $switch)) &no-effects)
(($ $kargs names syms ($ $prompt))
;; Although the "main" path just writes &prompt, we don't know
;; what nonlocal predecessors of the handler do, so we
diff --git a/module/language/cps/licm.scm b/module/language/cps/licm.scm
index 698c2d8c8..80d073ac1 100644
--- a/module/language/cps/licm.scm
+++ b/module/language/cps/licm.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013, 2014, 2015, 2017, 2018 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2014, 2015, 2017, 2018, 2020 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
@@ -204,7 +204,7 @@
($values fresh-vars))))))
(values cps cont loop-vars loop-effects
pre-header-label always-reached?)))))))))
- ((or ($ $branch) ($ $throw))
+ ((or ($ $branch) ($ $switch) ($ $throw))
(let* ((cont (build-cont ($kargs names vars ,term)))
(always-reached? #f))
(values cps cont loop-vars loop-effects
@@ -260,6 +260,9 @@
(($ $kargs names vars ($ $branch kf kt src op param args))
($kargs names vars
($branch (rename kf) (rename kt) src op param args)))
+ (($ $kargs names vars ($ $switch kf kt* src arg))
+ ($kargs names vars
+ ($switch (rename kf) (map rename kt*) src arg)))
(($ $kargs names vars ($ $prompt k kh src escape? tag))
($kargs names vars
($prompt (rename k) (rename kh) src escape? tag)))
diff --git a/module/language/cps/loop-instrumentation.scm b/module/language/cps/loop-instrumentation.scm
index 845a35a6c..2f5f1fe26 100644
--- a/module/language/cps/loop-instrumentation.scm
+++ b/module/language/cps/loop-instrumentation.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2016, 2017, 2018 Free Software Foundation, Inc.
+;; Copyright (C) 2016, 2017, 2018, 2020 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
@@ -44,6 +44,10 @@
(maybe-add-header label k headers))
(($ $kargs names vars ($ $branch kf kt))
(maybe-add-header label kf (maybe-add-header label kt headers)))
+ (($ $kargs names vars ($ $switch kf kt*))
+ (fold1 (lambda (k headers) (maybe-add-header label k headers))
+ (cons kf kt*)
+ headers))
(_ headers)))
(persistent-intset (intmap-fold visit-cont cps empty-intset)))
diff --git a/module/language/cps/peel-loops.scm b/module/language/cps/peel-loops.scm
index b1bb39606..c28654f62 100644
--- a/module/language/cps/peel-loops.scm
+++ b/module/language/cps/peel-loops.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -158,6 +158,9 @@
(($ $branch kf kt src op param args)
($branch (rename-label kf) (rename-label kt) src
op param ,(map rename-var args)))
+ (($ $switch kf kt* src arg)
+ ($switch (rename-label kf) (map rename-label kt*) src
+ (rename-var arg)))
(($ $prompt k kh src escape? tag)
($prompt (rename-label k) (rename-label kh) src
escape? (rename-var tag)))
diff --git a/module/language/cps/renumber.scm b/module/language/cps/renumber.scm
index 19080c502..c170f5c82 100644
--- a/module/language/cps/renumber.scm
+++ b/module/language/cps/renumber.scm
@@ -93,6 +93,10 @@
(if (visit-kf-first? kf kt)
(visit2 kf kt order visited)
(visit2 kt kf order visited)))
+ (($ $switch kf kt*)
+ (fold2 visit
+ (stable-sort (cons kf kt*) visit-kf-first?)
+ order visited))
(($ $prompt k kh)
(visit2 k kh order visited))
(($ $throw)
@@ -211,6 +215,9 @@
(($ $branch kf kt src op param args)
($branch (rename-label kf) (rename-label kt) src
op param ,(map rename-var args)))
+ (($ $switch kf kt* src arg)
+ ($switch (rename-label kf) (map rename-label kt*) src
+ (rename-var arg)))
(($ $prompt k kh src escape? tag)
($prompt (rename-label k) (rename-label kh) src
escape? (rename-var tag)))
diff --git a/module/language/cps/rotate-loops.scm b/module/language/cps/rotate-loops.scm
index d80a2723b..caa1da3bd 100644
--- a/module/language/cps/rotate-loops.scm
+++ b/module/language/cps/rotate-loops.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -121,6 +121,8 @@ corresponding var from REPLACEMENTS; otherwise return VAR."
($primcall name param ,(rename* args))))))
(($ $branch kf kt src op param args)
($branch kf kt src op param ,(rename* args)))
+ (($ $switch kf kt* src arg)
+ ($switch kf kt* src (rename arg)))
(($ $prompt k kh src escape? tag)
($prompt k kh src escape? (rename tag)))
(($ $throw src op param args)
@@ -194,7 +196,7 @@ corresponding var from REPLACEMENTS; otherwise return VAR."
(intset-fold (lambda (label rotate?)
(match (intmap-ref cps label)
(($ $kreceive) #f)
- (($ $kargs _ _ ($ $branch)) #f)
+ (($ $kargs _ _ (or ($ $branch) ($ $switch))) #f)
(($ $kargs _ _ ($ $continue)) rotate?)))
edges #t))
(let* ((succs (compute-successors cps kfun))
diff --git a/module/language/cps/self-references.scm b/module/language/cps/self-references.scm
index 8f678616a..0ac16f93f 100644
--- a/module/language/cps/self-references.scm
+++ b/module/language/cps/self-references.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -54,6 +54,8 @@
($continue k src ,(rename-exp exp)))
(($ $branch kf kt src op param args)
($branch kf kt src op param ,(map subst args)))
+ (($ $switch kf kt* src arg)
+ ($switch kf kt* src (subst arg)))
(($ $prompt k kh src escape? tag)
($prompt k kh src escape? (subst tag)))
(($ $throw src op param args)
diff --git a/module/language/cps/simplify.scm b/module/language/cps/simplify.scm
index 5bb8f4bd2..4515915c7 100644
--- a/module/language/cps/simplify.scm
+++ b/module/language/cps/simplify.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2015, 2017-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2015, 2017-2020 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
@@ -80,6 +80,8 @@
(ref* args))))
(($ $kargs _ _ ($ $branch kf kt src op param args))
(ref* args))
+ (($ $kargs _ _ ($ $switch kf kt* src arg))
+ (ref arg))
(($ $kargs _ _ ($ $prompt k kh src escape? tag))
(ref tag))
(($ $kargs _ _ ($ $throw src op param args))
@@ -149,6 +151,9 @@
(($ $kargs names syms ($ $branch kf kt src op param args))
($kargs names syms
($branch (subst kf) (subst kt) src op param args)))
+ (($ $kargs names syms ($ $switch kf kt* src arg))
+ ($kargs names syms
+ ($switch (subst kf) (map subst kt*) src arg)))
(($ $kargs names syms ($ $prompt k kh src escape? tag))
($kargs names syms
($prompt (subst k) (subst kh) src escape? tag)))
@@ -195,6 +200,8 @@
(($ $kclause arity kbody kalt) (ref2 kbody kalt))
(($ $kargs names syms ($ $continue k)) (ref1 k))
(($ $kargs names syms ($ $branch kf kt)) (ref2 kf kt))
+ (($ $kargs names syms ($ $switch kf kt*))
+ (fold2 ref (cons kf kt*) single multiple))
(($ $kargs names syms ($ $prompt k kh)) (ref2 k kh))
(($ $kargs names syms ($ $throw)) (ref0))))
(let*-values (((single multiple) (values empty-intset empty-intset))
@@ -266,6 +273,8 @@
($values ,(map subst args))))))
(($ $branch kf kt src op param args)
($branch kf kt src op param ,(map subst args)))
+ (($ $switch kf kt* src arg)
+ ($switch kf kt* src (subst arg)))
(($ $prompt k kh src escape? tag)
($prompt k kh src escape? (subst tag)))
(($ $throw src op param args)
diff --git a/module/language/cps/slot-allocation.scm b/module/language/cps/slot-allocation.scm
index f3800f3ed..6a90db05d 100644
--- a/module/language/cps/slot-allocation.scm
+++ b/module/language/cps/slot-allocation.scm
@@ -159,6 +159,8 @@ by a label, respectively."
(return (get-defs k) (vars->intset args)))))
(($ $kargs _ _ ($ $branch kf kt src op param args))
(return empty-intset (vars->intset args)))
+ (($ $kargs _ _ ($ $switch kf kt* src arg))
+ (return empty-intset (intset arg)))
(($ $kargs _ _ ($ $prompt k kh src escape? tag))
(return empty-intset (intset tag)))
(($ $kargs _ _ ($ $throw src op param args))
@@ -236,6 +238,10 @@ body continuation in the prompt."
(visit-cont k level labels))
(($ $kargs names syms ($ $branch kf kt))
(visit-cont kf level (visit-cont kt level labels)))
+ (($ $kargs names syms ($ $switch kf kt*))
+ (fold1 (lambda (label labels)
+ (visit-cont label level labels))
+ (cons kf kt*) labels))
(($ $kargs names syms ($ $prompt k kh src escape? tag))
(visit-cont kh level (visit-cont k (1+ level) labels)))
(($ $kargs names syms ($ $throw)) labels))))))))
@@ -788,7 +794,7 @@ are comparable with eqv?. A tmp slot may be used."
(intmap-add representations var
(intmap-ref representations arg)))
representations args vars))))))
- (($ $kargs _ _ (or ($ $branch) ($ $prompt) ($ $throw)))
+ (($ $kargs _ _ (or ($ $branch) ($ $switch) ($ $prompt) ($ $throw)))
representations)
(($ $kfun src meta self)
(if self
diff --git a/module/language/cps/specialize-numbers.scm b/module/language/cps/specialize-numbers.scm
index 7fa8741bb..574962421 100644
--- a/module/language/cps/specialize-numbers.scm
+++ b/module/language/cps/specialize-numbers.scm
@@ -370,6 +370,8 @@ BITS indicating the significant bits needed for a variable. BITS may be
(add-unknown-uses out args))))))
(($ $branch kf kt src op param args)
(add-unknown-uses out args))
+ (($ $switch kf kt src arg)
+ (add-unknown-use out arg))
(($ $prompt k kh src escape? tag)
(add-unknown-use out tag))
(($ $throw src op param args)
diff --git a/module/language/cps/split-rec.scm b/module/language/cps/split-rec.scm
index ee5f2f2e4..07bf7d908 100644
--- a/module/language/cps/split-rec.scm
+++ b/module/language/cps/split-rec.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2020 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
@@ -93,6 +93,8 @@ references."
(add-uses args uses))))
(($ $branch kf kt src op param args)
(add-uses args uses))
+ (($ $switch kf kt* src arg)
+ (add-use arg uses))
(($ $prompt k kh src escape? tag)
(add-use tag uses))
(($ $throw src op param args)
diff --git a/module/language/cps/type-fold.scm b/module/language/cps/type-fold.scm
index b87730c8d..e09cc6966 100644
--- a/module/language/cps/type-fold.scm
+++ b/module/language/cps/type-fold.scm
@@ -677,6 +677,11 @@
(with-cps cps
(setk label
($kargs names vars ,term)))))))))))))))
+ (define (branch-folded cps label names vars src k)
+ (with-cps cps
+ (setk label
+ ($kargs names vars
+ ($continue k src ($values ()))))))
(define (fold-unary-branch cps label names vars kf kt src op param arg)
(and=>
(hashq-ref *branch-folders* op)
@@ -687,11 +692,8 @@
(lambda (f? v)
;; (when f? (pk 'folded-unary-branch label op arg v))
(and f?
- (with-cps cps
- (setk label
- ($kargs names vars
- ($continue (if v kt kf) src
- ($values ())))))))))))))
+ (branch-folded cps label names vars src
+ (if v kt kf))))))))))
(define (fold-binary-branch cps label names vars kf kt src op param arg0 arg1)
(and=>
(hashq-ref *branch-folders* op)
@@ -705,11 +707,8 @@
(lambda (f? v)
;; (when f? (pk 'folded-binary-branch label op arg0 arg1 v))
(and f?
- (with-cps cps
- (setk label
- ($kargs names vars
- ($continue (if v kt kf) src
- ($values ())))))))))))))))
+ (branch-folded cps label names vars src
+ (if v kt kf))))))))))))
(define (fold-branch cps label names vars kf kt src op param args)
(match args
((x)
@@ -729,6 +728,24 @@
(or (fold-branch cps label names vars kf kt src op param args)
(reduce-branch cps label names vars kf kt src op param args)
cps))
+ (define (visit-switch cps label names vars kf kt* src arg)
+ ;; We might be able to fold or reduce a switch.
+ (let ((ntargets (length kt*)))
+ (call-with-values (lambda () (lookup-pre-type types label arg))
+ (lambda (type min max)
+ (cond
+ ((<= ntargets min)
+ (branch-folded cps label names vars src kf))
+ ((= min max)
+ (branch-folded cps label names vars src (list-ref kt* min)))
+ (else
+ ;; There are two more optimizations we could do here: one,
+ ;; if max is less than ntargets, we can prune targets at
+ ;; the end of the switch, and perhaps reduce the switch
+ ;; back to a branch; and two, if min is greater than 0,
+ ;; then we can subtract off min and prune targets at the
+ ;; beginning. Not done yet though.
+ cps))))))
(let lp ((label start) (cps cps))
(if (<= label end)
(lp (1+ label)
@@ -738,6 +755,8 @@
(visit-primcall cps label names vars k src op param args))
(($ $kargs names vars ($ $branch kf kt src op param args))
(visit-branch cps label names vars kf kt src op param args))
+ (($ $kargs names vars ($ $switch kf kt* src arg))
+ (visit-switch cps label names vars kf kt* src arg))
(_ cps)))
cps))))
diff --git a/module/language/cps/types.scm b/module/language/cps/types.scm
index 1c85da112..6364b703b 100644
--- a/module/language/cps/types.scm
+++ b/module/language/cps/types.scm
@@ -1870,6 +1870,7 @@ where (A0 <= A <= A1) and (B0 <= B <= B1)."
(($ $kargs _ _ ($ $throw)) 0)
(($ $kargs _ _ ($ $continue)) 1)
(($ $kargs _ _ (or ($ $branch) ($ $prompt))) 2)
+ (($ $kargs _ _ ($ $switch kf kt*)) (1+ (length kt*)))
(($ $kfun src meta self tail clause) (if clause 1 0))
(($ $kclause arity body alt) (if alt 2 1))
(($ $kreceive) 1)
@@ -2066,6 +2067,24 @@ maximum, where type is a bitset as a fixnum."
;; The "normal" continuation is the #f branch.
(propagate2 kf (infer-primcall types 0 op param args #f)
kt (infer-primcall types 1 op param args #f)))
+ (($ $kargs names vars ($ $switch kf kt* src arg))
+ (define (restrict-index min max)
+ (restrict-var types arg (make-type-entry &u64 min max)))
+ (define (visit-default typev)
+ (let ((types (restrict-index (length kt*) &u64-max)))
+ (propagate-types label typev 0 kf types)))
+ (define (visit-target typev k i)
+ (let ((types (restrict-index i i)))
+ (propagate-types label typev (1+ i) k types)))
+ (call-with-values (lambda () (visit-default typev))
+ (lambda (changed typev)
+ (let lp ((kt* kt*) (i 0) (changed changed) (typev typev))
+ (match kt*
+ (() (values changed typev))
+ ((kt . kt*)
+ (call-with-values (lambda () (visit-target typev kt i))
+ (lambda (changed* typev)
+ (lp kt* (1+ i) (append changed* changed) typev)))))))))
(($ $kargs names vars ($ $prompt k kh src escape? tag))
;; The "normal" continuation enters the prompt.
(propagate2 k types kh types))
diff --git a/module/language/cps/utils.scm b/module/language/cps/utils.scm
index fff88ab75..e1f5e3a78 100644
--- a/module/language/cps/utils.scm
+++ b/module/language/cps/utils.scm
@@ -1,6 +1,6 @@
;;; Continuation-passing style (CPS) intermediate language (IL)
-;; Copyright (C) 2013, 2014, 2015, 2017, 2018, 2019 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2014, 2015, 2017, 2018, 2019, 2020 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
@@ -122,6 +122,8 @@
(visit-cont k labels))
(($ $branch kf kt)
(visit-cont kf (visit-cont kt labels)))
+ (($ $switch kf kt*)
+ (visit-cont kf (fold1 visit-cont kt* labels)))
(($ $prompt k kh)
(visit-cont k (visit-cont kh labels)))
(($ $throw)
@@ -176,6 +178,10 @@ intset."
(define (propagate2 succ0 succ1)
(let ((succs (intmap-add! succs label (intset succ0 succ1))))
(visit succ1 (visit succ0 succs))))
+ (define (propagate* k*)
+ (define (list->intset ls)
+ (fold1 (lambda (elt set) (intset-add set elt)) ls empty-intset))
+ (fold1 visit k* (intmap-add! succs label (list->intset k*))))
(if (intmap-ref succs label (lambda (_) #f))
succs
(match (intmap-ref conts label)
@@ -183,6 +189,7 @@ intset."
(match term
(($ $continue k) (propagate1 k))
(($ $branch kf kt) (propagate2 kf kt))
+ (($ $switch kf kt*) (propagate* (cons kf kt*)))
(($ $prompt k kh) (propagate2 k kh))
(($ $throw) (propagate0))))
(($ $kreceive arity k)
@@ -218,6 +225,7 @@ intset."
(match term
(($ $continue k) (add-pred k preds))
(($ $branch kf kt) (add-pred kf (add-pred kt preds)))
+ (($ $switch kf kt*) (fold1 add-pred (cons kf kt*) preds))
(($ $prompt k kh) (add-pred k (add-pred kh preds)))
(($ $throw) preds)))))
(persistent-intmap
diff --git a/module/language/cps/verify.scm b/module/language/cps/verify.scm
index cacde9ec5..88dcbc0c0 100644
--- a/module/language/cps/verify.scm
+++ b/module/language/cps/verify.scm
@@ -1,5 +1,5 @@
;;; Diagnostic checker for CPS
-;;; Copyright (C) 2014-2019 Free Software Foundation, Inc.
+;;; Copyright (C) 2014-2020 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
@@ -97,6 +97,13 @@ definitions that are available at LABEL."
(let*-values (((changed0 defs) (propagate defs succ0 out))
((changed1 defs) (propagate defs succ1 out)))
(values (append changed0 changed1) defs)))
+ (define (propagate* succs out)
+ (let lp ((succs succs) (changed '()) (defs defs))
+ (match succs
+ (() (values changed defs))
+ ((succ . succs)
+ (let-values (((changed* defs) (propagate defs succ out)))
+ (lp succs (append changed* changed) defs))))))
(match (intmap-ref conts label)
(($ $kargs names vars term)
@@ -106,6 +113,8 @@ definitions that are available at LABEL."
(propagate1 k out))
(($ $branch kf kt)
(propagate2 kf kt out))
+ (($ $switch kf kt*)
+ (propagate* (cons kf kt*) out))
(($ $prompt k kh)
(propagate2 k kh out))
(($ $throw)
@@ -208,6 +217,9 @@ definitions that are available at LABEL."
(($ $branch kf kt src name param args)
(for-each check-use args)
first-order)
+ (($ $switch kf kt* src arg)
+ (check-use arg)
+ first-order)
(($ $prompt k kh src escape? tag)
(check-use tag)
first-order)
@@ -290,20 +302,21 @@ definitions that are available at LABEL."
(($ $primcall 'call-thunk/no-inline #f (thunk)) #t)
(_ (cont (error "bad continuation" exp cont)))))))))
(define (check-term term)
+ (define (assert-nullary k)
+ (match (intmap-ref conts k)
+ (($ $kargs () ()) #t)
+ (cont (error "expected nullary cont" cont))))
(match term
(($ $continue k src exp)
(check-arity exp (intmap-ref conts k)))
(($ $branch kf kt src op param args)
- (match (intmap-ref conts kf)
- (($ $kargs () ()) #t)
- (cont (error "bad kf" cont)))
- (match (intmap-ref conts kt)
- (($ $kargs () ()) #t)
- (cont (error "bad kt" cont))))
+ (assert-nullary kf)
+ (assert-nullary kt))
+ (($ $switch kf kt* src arg)
+ (assert-nullary kf)
+ (for-each assert-nullary kt*))
(($ $prompt k kh src escape? tag)
- (match (intmap-ref conts k)
- (($ $kargs () ()) #t)
- (cont (error "bad prompt body" cont)))
+ (assert-nullary k)
(match (intmap-ref conts kh)
(($ $kreceive) #t)
(cont (error "bad prompt handler" cont))))