summaryrefslogtreecommitdiff
path: root/src/ChezScheme/s/cpnanopass.ss
diff options
context:
space:
mode:
Diffstat (limited to 'src/ChezScheme/s/cpnanopass.ss')
-rw-r--r--src/ChezScheme/s/cpnanopass.ss666
1 files changed, 623 insertions, 43 deletions
diff --git a/src/ChezScheme/s/cpnanopass.ss b/src/ChezScheme/s/cpnanopass.ss
index 27c0c34626..cd7af1f5d7 100644
--- a/src/ChezScheme/s/cpnanopass.ss
+++ b/src/ChezScheme/s/cpnanopass.ss
@@ -217,6 +217,8 @@
(annotation-expression x)
x)))
+ (define rtd-ancestors (csv7:record-field-accessor #!base-rtd 'ancestors))
+
(let ()
(import (nanopass) np-languages)
@@ -548,7 +550,7 @@
arg-offset fp-offset rextra* rfpextra*)
(if (eq? (syntax->datum (car other-type*)) 'fp)
(f (cdr other*) (cdr other-type*) (cons fp-offset rtc-disp*)
- arg-offset (fx+ fp-offset 8) rextra* (cons other rfpextra*))
+ arg-offset (fx+ fp-offset (constant double-bytes)) rextra* (cons other rfpextra*))
(f (cdr other*) (cdr other-type*) (cons arg-offset rtc-disp*)
(fx+ arg-offset (constant ptr-bytes)) fp-offset (cons other rextra*) rfpextra*))))))]
[_ (syntax-error x "missing or out-of-order required registers")])]
@@ -855,7 +857,7 @@
(define-record-type info-lambda (nongenerative)
(parent info)
(sealed #t)
- (fields src sexpr libspec interface* (mutable dcl*) (mutable flags) (mutable fv*) (mutable name)
+ (fields src sexpr libspec (mutable interface*) (mutable dcl*) (mutable flags) (mutable fv*) (mutable name)
(mutable well-known?) (mutable closure-rep) ctci (mutable pinfo*) seqno)
(protocol
(lambda (pargs->new)
@@ -1147,7 +1149,8 @@
`(letrec ([,uvar* ,e*] ...) ,(Expr body))))]
[(call ,preinfo ,e ,[e*] ...)
(unless (preinfo-call? preinfo) (error 'preinfo-call "oops"))
- `(call ,(make-info-call (preinfo-src preinfo) (preinfo-sexpr preinfo) (preinfo-call-check? preinfo) #f #f)
+ `(call ,(make-info-call (preinfo-src preinfo) (preinfo-sexpr preinfo) (preinfo-call-check? preinfo) #f
+ (and (preinfo-call-no-return? preinfo) (not (preinfo-call-check? preinfo))))
,(Expr e) ,e* ...)]
[(foreign (,conv* ...) ,name ,[e] (,arg-type* ...) ,result-type)
(let ([info (make-info-foreign conv* arg-type* result-type #f)])
@@ -2098,6 +2101,367 @@
`(closures ([,(map binding-x b*) (,(map binding-x* b*) ...) ,(map binding-le b*)] ...)
,(f (cdr b**)))))))]))
+ ;;; This pass lifts all internal well-known closures to a intermost lambda body with a lift barrier
+ (module (np-lift-well-known-closures)
+ (define-syntax with-level
+ (syntax-rules ()
+ [(_ [?x* ?level] ?e1 ?e2 ...)
+ (let ([x* ?x*] [level ?level])
+ (for-each (lambda (x) (var-index-set! x level)) x*)
+ (let ([v (begin ?e1 ?e2 ...)])
+ (for-each (lambda (x) (var-index-set! x #f)) x*)
+ v))]))
+
+ (define-syntax with-lifts
+ (syntax-rules ()
+ [(_ ?x* ?e1 ?e2 ...)
+ (with-level [?x* 'lifted] ?e1 ?e2 ...)]))
+
+ ;; defined in or lifted to outer lambda body
+ (define outer?
+ (case-lambda
+ [(target x)
+ (let ([index (var-index x)])
+ (or (eq? index 'lifted)
+ (fx<= index target)))]
+ [(target)
+ (lambda (x) (outer? target x))]))
+
+ (define (lifted? x)
+ (eq? 'lifted (var-index x)))
+
+ (define-record-type lift-info
+ (nongenerative)
+ (sealed #t)
+ (fields (mutable le**))
+ (protocol (lambda (n) (lambda () (n '())))))
+
+ (define-record-type le-info
+ (nongenerative)
+ (sealed #t)
+ (fields x fv* cle))
+
+ (define cle-info
+ (lambda (cle)
+ (nanopass-case (L6 CaseLambdaExpr) cle
+ [(case-lambda ,info ,cl* ...) info])))
+
+ ;; simply a eq-hashtable, but can retrieve the keys deterministically
+ (define-record-type uvar-set
+ (nongenerative)
+ (sealed #t)
+ (fields ht (mutable ls))
+ (protocol
+ (lambda (n)
+ (lambda (ls)
+ (define ht (make-eq-hashtable))
+ (for-each (lambda (x) (eq-hashtable-set! ht x #t)) ls)
+ (n ht ls)))))
+
+ (define uvar-set-has?
+ (lambda (us x)
+ (eq-hashtable-contains? (uvar-set-ht us) x)))
+
+ (define uvar-set-add!
+ (lambda (us x)
+ (cond
+ [(null? x) (void)]
+ [(pair? x)
+ (for-each (lambda (x) (uvar-set-add! us x)) x)]
+ [(eq-hashtable-contains? (uvar-set-ht us) x)
+ (void)]
+ [else
+ (eq-hashtable-set! (uvar-set-ht us) x #t)
+ (uvar-set-ls-set! us (cons x (uvar-set-ls us)))])))
+
+ (define partition3
+ (lambda (proc l1 l2 l3)
+ (let f ([l1 l1] [l2 l2] [l3 l3])
+ (cond
+ [(null? l1) (values '()'())]
+ [(proc (car l1) (car l2) (car l3))
+ (let-values ([(a b) (f (cdr l1) (cdr l2) (cdr l3))])
+ (values (cons (car l1) a) b))]
+ [else
+ (let-values ([(a b) (f (cdr l1) (cdr l2) (cdr l3))])
+ (values a (cons (car l1) b)))]))))
+
+ (define info-lambda-lift-barrier?
+ (lambda (info)
+ (fx= (bitwise-and (info-lambda-flags info) (constant code-flag-lift-barrier))
+ (constant code-flag-lift-barrier))))
+
+ (define-pass np-lift : L6 (ir) -> L6 ()
+ (definitions
+ (define partition-liftable
+ (lambda (x* fv** cle*)
+ (partition3
+ (lambda (x fv* cle)
+ (info-lambda-well-known? (cle-info cle)))
+ x* fv** cle*)))
+
+ (define find-extra-arg*
+ (lambda (x arg-info)
+ (and (lifted? x)
+ (let ([info (uvar-info-lambda x)])
+ (and info
+ (assq x arg-info))))))
+
+ (define partition-lift
+ (lambda (x* x** le* target)
+ (let f ([x* x*] [x** x**] [le* le*])
+ (cond
+ [(null? x*) (values '() '() '())]
+ [(lifted? (car x*))
+ ;; any free variables other than
+ ;; procedures lifted or defined in outermost lambda body
+ ;; are moved to extra arguments
+ (let*-values ([(new-fv* extra-arg*) (partition (outer? target) (car x**))]
+ [(rest* lift* extra-arg**) (f (cdr x*) (cdr x**) (cdr le*))])
+ (values rest*
+ (cons (make-le-info (car x*) new-fv* (car le*))
+ lift*)
+ (cons extra-arg* extra-arg**)))]
+ [else
+ (let-values ([(rest* lift* extra-arg**)
+ (f (cdr x*) (cdr x**) (cdr le*))])
+ (values (cons (make-le-info (car x*) (car x**) (car le*))
+ rest*)
+ lift*
+ extra-arg**))]))))
+
+ (define rename
+ (case-lambda
+ [(rename-info)
+ (lambda (x)
+ (rename rename-info x))]
+ [(rename-info x)
+ (cond
+ [(assq x rename-info) => cdr]
+ [else x])]))
+
+ (define (make-renamed x)
+ (make-tmp (uvar-name x)))
+
+ (define-syntax (recur stx)
+ (syntax-case stx ()
+ [(_ ?f ?e ...)
+ (identifier? #'?f)
+ (with-implicit (?f lift-info arg-info rename-info level target)
+ #'(?f ?e ... lift-info arg-info rename-info level target))]))
+
+ (define rewrite-rest-body
+ (lambda (le-info lift-info arg-info rename-info level target)
+ (define new-lift-info (make-lift-info))
+ (define le (let ([level (fx+ level 1)]
+ [lift-info new-lift-info])
+ (recur CaseLambdaExpr (le-info-cle le-info))))
+ (define lift-x* (map le-info-x (apply append (lift-info-le** new-lift-info))))
+ (lift-info-le**-set! lift-info (append (lift-info-le** new-lift-info) (lift-info-le** lift-info)))
+ ;; add newly lifted procedures as free variables
+ (values (append lift-x* (le-info-fv* le-info)) le)))
+
+ (define rewrite-rest-le
+ (lambda (le-info lift-info arg-info rename-info level target)
+ (define-values (new-fv* new-le) (recur rewrite-rest-body le-info))
+ (define us (make-uvar-set new-fv*))
+
+ ;; also add extra arguments from free lifted procedures as free variables
+ ;; there is no need to recur since extra arguments of a lifted procedure would not be lifted procedures
+ (for-each
+ (lambda (fv)
+ (cond
+ [(find-extra-arg* fv arg-info)
+ =>
+ (lambda (xe*)
+ (uvar-set-add! us (cdr xe*)))]
+ [else (void)]))
+ new-fv*)
+
+ (make-le-info (le-info-x le-info)
+ (map (rename rename-info) (uvar-set-ls us))
+ new-le)))
+
+ (define union-extra-arg*
+ (lambda (le-info* arg-info extra-arg**)
+ (define us (make-uvar-set '()))
+ ;; simply computes a union since lambdas are strongly-connected after np-identify-scc
+ (for-each
+ (lambda (le-info extra-arg*)
+ (uvar-set-add! us extra-arg*)
+ (for-each
+ (lambda (fv)
+ (cond
+ [(find-extra-arg* fv arg-info)
+ =>
+ (lambda (x+e*)
+ (uvar-set-add! us (cdr x+e*)))]
+ [else (void)]))
+ (le-info-fv* le-info)))
+ le-info* extra-arg**)
+
+ ;;if rules in filter-liftable are changed, lambdas passed as extra arguments would no longer be well-known
+ (for-each
+ (lambda (x)
+ (let ([info (uvar-info-lambda x)])
+ (and info
+ (when (info-lambda-well-known? info)
+ (info-lambda-well-known?-set! info #f)))))
+ (uvar-set-ls us))
+
+ (uvar-set-ls us)))
+
+ (define rewrite-lifted-le
+ (lambda (le-info extra-arg* lift-info arg-info rename-info level target)
+ (define-values (new-le lift-x*)
+ (recur LiftedCaseLambdaExpr (le-info-cle le-info) extra-arg*))
+ (nanopass-case (L6 CaseLambdaExpr) new-le
+ [(case-lambda ,info (clause (,x** ...) ,mcp* ,interface* ,body*) ...)
+ (let* ()
+ (info-lambda-interface*-set! info interface*)
+ (make-le-info (le-info-x le-info)
+ ;; add newly lifted procedures as free variables
+ (append lift-x* (map (rename rename-info) (le-info-fv* le-info)))
+ new-le))])))
+ )
+
+ ;; arg-info : lifted-x -> unrenamed extra-arg*
+ ;; rename-info : unrenamed x -> renamed x
+ (Expr : Expr (ir lift-info arg-info rename-info level target) -> Expr ()
+ [,x (rename rename-info x)]
+
+ [(call ,info ,mdcl ,x ,[e*] ...)
+ (cond
+ [(find-extra-arg* x arg-info)
+ =>
+ (lambda (x+extra-arg*)
+ `(call ,info ,mdcl ,(rename rename-info x)
+ ,(append (map (rename rename-info) (cdr x+extra-arg*)) e*) ...))]
+ [else
+ `(call ,info ,mdcl ,(rename rename-info x) ,e* ...)])]
+
+ [(let ([,x* ,[e*]] ...) ,body)
+ (with-level [x* level]
+ `(let ([,x* ,e*] ...) ,(recur Expr body)))]
+
+ [(mvlet ,[e] ((,x** ...) ,interface* ,body*) ...)
+ `(mvlet ,e
+ ((,x** ...)
+ ,interface*
+ ,(map (lambda (x* body)
+ (with-level [x* level]
+ (recur Expr body)))
+ x** body*))
+ ...)]
+ [(loop ,x (,x* ...) ,body)
+ (with-level [(list x) level]
+ `(loop ,x (,x* ...) ,(recur Expr body)))]
+
+ ;; a lift barrier on this level
+ [(closures ([,x* (,x** ...) ,le*] ...) ,body)
+ (guard (fx= level target))
+ (with-level [x* level]
+ (let f ([x* x*] [x** x**] [le* le*] [rx* '()] [rfv** '()] [rle* '()])
+ (cond
+ [(null? x*)
+ `(closures ([,(reverse rx*) (,(reverse rfv**) ...) ,(reverse rle*)] ...)
+ ,(recur Expr body))]
+ [else
+ (let*-values ([(new-lift-info) (make-lift-info)]
+ [(new-le) (let ([level (fx+ level 1)] [lift-info new-lift-info])
+ (recur CaseLambdaExpr (car le*)))]
+ [(lift*) (apply append (lift-info-le** new-lift-info))])
+ (f (cdr x*) (cdr x**) (cdr le*)
+ (append (map le-info-x lift*) (cons (car x*) rx*))
+ (append (map le-info-fv* lift*) (cons (append (car x**) (map le-info-x lift*)) rfv**))
+ (append (map le-info-cle lift*) (cons new-le rle*))))])))]
+
+ [(closures ([,x* (,x** ...) ,le*] ...) ,body)
+ (let-values ([(lift-x* non-lift-x*) (partition-liftable x* x** le*)])
+ (with-level [non-lift-x* level]
+ (with-lifts lift-x*
+ (let*-values ([(rest-le* lift-le* extra-arg**) (partition-lift x* x** le* target)]
+ [(extra-arg*) (union-extra-arg* lift-le* arg-info extra-arg**)]
+ [(arg-info) (append (map (lambda (le-info)
+ (cons (le-info-x le-info) extra-arg*))
+ lift-le*)
+ arg-info)]
+ [(rest-le*)
+ (map (lambda (le-info) (recur rewrite-rest-le le-info))
+ rest-le*)]
+ [(lift-le*)
+ (map (lambda (le-info)
+ (recur rewrite-lifted-le le-info extra-arg*))
+ lift-le*)])
+ (unless (null? lift-le*)
+ (lift-info-le**-set! lift-info (cons lift-le* (lift-info-le** lift-info))))
+ (let ([body (recur Expr body)])
+ (cond
+ [(null? rest-le*) body]
+ [else
+ `(closures ([,(map le-info-x rest-le*) (,(map le-info-fv* rest-le*) ...)
+ ,(map le-info-cle rest-le*)] ...)
+ ,body)]))))))])
+
+ (CaseLambdaClause : CaseLambdaClause (ir lift-info arg-info rename-info level target) -> CaseLambdaClause ()
+ [(clause (,x* ...) ,mcp ,interface ,body)
+ (with-level [x* level]
+ (let* ([old-le** (lift-info-le** lift-info)]
+ [new-body (recur Expr body)])
+ `(clause (,x* ...)
+ ,(or mcp
+ ;;introduce a cpvar if something lifted from this clause
+ (and (not (eq? (lift-info-le** lift-info) old-le**))
+ (make-cpvar)))
+ ,interface ,new-body)))])
+ (CaseLambdaExpr : CaseLambdaExpr (ir lift-info arg-info rename-info level target) -> CaseLambdaExpr ()
+ [(case-lambda ,info ,cl* ...)
+ `(case-lambda
+ ,info
+ ,(if (info-lambda-lift-barrier? info)
+ (let ([target level])
+ (map (lambda (cl) (recur CaseLambdaClause cl)) cl*))
+ (map (lambda (cl) (recur CaseLambdaClause cl)) cl*))
+ ...)])
+
+ (LiftedCaseLambdaClause : CaseLambdaClause (ir extra-arg* lift-info arg-info rename-info level target) -> CaseLambdaClause ()
+ [(clause (,x* ...) ,mcp ,interface ,body)
+ (with-level [x* level]
+ (let* ([new-extra-arg* (map make-renamed extra-arg*)]
+ [n (length new-extra-arg*)]
+ [new-rename-info (append (map cons extra-arg* new-extra-arg*) rename-info)]
+ [old-le** (lift-info-le** lift-info)]
+ [new-body (let ([rename-info new-rename-info])
+ (recur Expr body))]
+ [new-interface (cond
+ [(fx< interface 0) (fx- interface n)]
+ [else (fx+ interface n)])])
+ `(clause (,(append new-extra-arg* x*) ...)
+ ,(or mcp
+ ;;introduce a cpvar if something lifted from this clause
+ (and (not (eq? (lift-info-le** lift-info) old-le**))
+ (make-cpvar)))
+ ,new-interface ,new-body)))])
+
+ (LiftedCaseLambdaExpr : CaseLambdaExpr (ir extra-arg* lift-info arg-info rename-info level target) -> CaseLambdaExpr (lift-x*)
+ [(case-lambda ,info ,cl* ...)
+ (let* ([new-lift-info (make-lift-info)]
+ [cl* (let ([lift-info new-lift-info])
+ (if (info-lambda-lift-barrier? info)
+ (let ([target level])
+ (map (lambda (cl) (recur LiftedCaseLambdaClause cl extra-arg*)) cl*))
+ (map (lambda (cl) (recur LiftedCaseLambdaClause cl extra-arg*)) cl*)))]
+ [lift-x* (map le-info-x (apply append (lift-info-le** new-lift-info)))])
+ (lift-info-le**-set! lift-info (append (lift-info-le** new-lift-info) (lift-info-le** lift-info)))
+ (values `(case-lambda ,info ,cl* ...) lift-x*))])
+
+ (CaseLambdaExpr ir (make-lift-info) '() '() 0 0))
+
+ (define np-lift-well-known-closures
+ (lambda (ir)
+ (let ([ir (np-lift ir)])
+ (np-identify-scc ir)))))
+
(module (np-expand-closures np-expand/optimize-closures)
(define sort-bindings
; sort-bindings uses the otherwise unneeded info-lambda-seqno to put labels
@@ -3048,6 +3412,10 @@
(guard (eq? 'bytevector-ieee-double-native-set! (primref-name pr)))
(Expr e3 #t)
#f]
+ [(call ,info ,mdcl ,pr ,[e1 #f -> * fp?1] ,[e2 #f -> * fp?2] ,e3)
+ (guard (eq? 'flvector-set! (primref-name pr)))
+ (Expr e3 #t)
+ #f]
[(call ,info ,mdcl ,pr ,[e* #f -> * fp?] ...)
(primref-flonum-result? pr)]
[(loop ,x (,x* ...) ,body)
@@ -3587,6 +3955,12 @@
(define build-fix
(lambda (e)
(%inline sll ,e ,(%constant fixnum-offset))))
+ (define build-double-scale
+ (lambda (e)
+ (constant-case ptr-bits
+ [(32) (%inline sll ,e (immediate 1))]
+ [(64) e]
+ [else ($oops 'build-double-scale "unknown ptr-bit size ~s" (constant ptr-bits))])))
(define build-unfix
(lambda (e)
(nanopass-case (L7 Expr) e
@@ -3727,6 +4101,8 @@
[(base index offset e build-assign build-barrier-seq)
(if (nanopass-case (L7 Expr) e
[(quote ,d) (ptr->imm d)]
+ [(call ,info ,mdcl ,pr ,e* ...)
+ (eq? 'fixnum ($sgetprop (primref-name pr) '*result-type* #f))]
[else #f])
(build-assign base index offset e)
(let ([a (if (eq? index %zero)
@@ -3805,7 +4181,7 @@
,(constant-case ptr-bytes
[(4)
(case elt-bytes
- [(1) (let ([imm (logand imm #xff)])
+ [(1) (let ([imm (logand imm #xff)])<
(let ([imm (logor (ash imm 8) imm)])
(logor (ash imm 16) imm)))]
[(2) (let ([imm (logand imm #xffff)])
@@ -4588,7 +4964,8 @@
[(e) (ensure-single-valued e #f)])
(define-inline 2 eq?
[(e1 e2)
- (or (relop-length RELOP= e1 e2)
+ (or (eqvop-null-fptr e1 e2)
+ (relop-length RELOP= e1 e2)
(%inline eq? ,e1 ,e2))])
(define-inline 2 keep-live
[(e) (%seq ,(%inline keep-live ,e) ,(%constant svoid))])
@@ -4780,6 +5157,8 @@
[(e1 . e*) (reduce src sexpr moi e1 e*)])
(define-inline 3 r6rs:fx+ ; limited to two arguments
[(e1 e2) (%inline + ,e1 ,e2)])
+ (define-inline 3 fx+/wraparound
+ [(e1 e2) (%inline + ,e1 ,e2)])
(define-inline 3 fx1+
[(e) (%inline + ,e (immediate ,(fix 1)))])
(define-inline 2 $fx+?
@@ -4825,7 +5204,13 @@
(goto ,Llib))))]
[(e1 . e*) #f])
(define-inline 2 r6rs:fx+ ; limited to two arguments
- [(e1 e2) (go src sexpr e1 e2)]))
+ [(e1 e2) (go src sexpr e1 e2)])
+ (define-inline 2 fx+/wraparound
+ [(e1 e2)
+ (bind #t (e1 e2)
+ `(if ,(build-fixnums? (list e1 e2))
+ ,(%inline + ,e1 ,e2)
+ ,(build-libcall #t src sexpr fx+/wraparound e1 e2)))]))
(define-inline 3 fx-
[(e) (%inline - (immediate 0) ,e)]
@@ -4834,6 +5219,8 @@
(define-inline 3 r6rs:fx- ; limited to one or two arguments
[(e) (%inline - (immediate 0) ,e)]
[(e1 e2) (%inline - ,e1 ,e2)])
+ (define-inline 3 fx-/wraparound
+ [(e1 e2) (%inline - ,e1 ,e2)])
(define-inline 3 fx1-
[(e) (%inline - ,e (immediate ,(fix 1)))])
(define-inline 2 $fx-?
@@ -4875,7 +5262,13 @@
[(e1 . e*) #f])
(define-inline 2 r6rs:fx- ; limited to one or two arguments
[(e) (go src sexpr `(immediate ,(fix 0)) e)]
- [(e1 e2) (go src sexpr e1 e2)]))
+ [(e1 e2) (go src sexpr e1 e2)])
+ (define-inline 2 fx-/wraparound
+ [(e1 e2)
+ (bind #t (e1 e2)
+ `(if ,(build-fixnums? (list e1 e2))
+ ,(%inline - ,e1 ,e2)
+ ,(build-libcall #t src sexpr fx-/wraparound e1 e2)))]))
(define-inline 2 fx1-
[(e) (let ([Llib (make-local-label 'Llib)])
(bind #t (e)
@@ -4960,6 +5353,8 @@
[(e1 . e*) (reduce src sexpr moi e1 e*)])
(define-inline 3 r6rs:fx* ; limited to two arguments
[(e1 e2) (build-fx* e1 e2 #f)])
+ (define-inline 3 fx*/wraparound
+ [(e1 e2) (build-fx* e1 e2 #f)])
(let ()
(define (go src sexpr e1 e2)
(let ([Llib (make-local-label 'Llib)])
@@ -4993,7 +5388,13 @@
(goto ,Llib))))]
[(e1 . e*) #f])
(define-inline 2 r6rs:fx* ; limited to two arguments
- [(e1 e2) (go src sexpr e1 e2)]))
+ [(e1 e2) (go src sexpr e1 e2)])
+ (define-inline 2 fx*/wraparound
+ [(e1 e2)
+ (bind #t (e1 e2)
+ `(if ,(build-fixnums? (list e1 e2))
+ ,(build-fx* e1 e2 #f)
+ ,(build-libcall #t src sexpr fx*/wraparound e1 e2)))]))
(let ()
(define build-fx/p2
(lambda (e1 p2)
@@ -5148,6 +5549,8 @@
(define-inline 3 fxsll
[(e1 e2) (do-fxsll e1 e2)])
(define-inline 3 fxarithmetic-shift-left
+ [(e1 e2) (do-fxsll e1 e2)])
+ (define-inline 3 fxsll/wraparound
[(e1 e2) (do-fxsll e1 e2)]))
(define-inline 3 fxsrl
[(e1 e2)
@@ -5624,8 +6027,7 @@
(typed-object-pred $code? mask-code type-code)
(typed-object-pred $exactnum? mask-exactnum type-exactnum)
(typed-object-pred fxvector? mask-fxvector type-fxvector)
- (typed-object-pred mutable-fxvector? mask-mutable-fxvector type-mutable-fxvector)
- (typed-object-pred immutable-fxvector? mask-mutable-fxvector type-immutable-fxvector)
+ (typed-object-pred flvector? mask-flvector type-flvector)
(typed-object-pred $inexactnum? mask-inexactnum type-inexactnum)
(typed-object-pred $rtd-counts? mask-rtd-counts type-rtd-counts)
(typed-object-pred phantom-bytevector? mask-phantom type-phantom)
@@ -5814,6 +6216,28 @@
(let ([n (length e*)])
(list-bind #f (e*)
(bind #t ([t (%constant-alloc type-typed-object
+ (fx+ (constant header-size-flvector) (fx* n (constant flonum-bytes))))])
+ (let loop ([e* e*] [i 0])
+ (if (null? e*)
+ `(seq
+ (set! ,(%mref ,t ,(constant flvector-type-disp))
+ (immediate ,(+ (fx* n (constant flvector-length-factor))
+ (constant type-flvector))))
+ ,t)
+ `(seq
+ (set! ,(%mref ,t ,%zero ,(fx+ i (constant flvector-data-disp)) fp) ,(car e*))
+ ,(loop (cdr e*) (fx+ i (constant flonum-bytes))))))))))
+ (define-inline 2 flvector
+ [() `(quote #vfl())]
+ [e* (and (andmap (lambda (x) (constant? flonum? x)) e*) (go e*))])
+ (define-inline 3 flvector
+ [() `(quote #vfl())]
+ [e* (go e*)]))
+ (let ()
+ (define (go e*)
+ (let ([n (length e*)])
+ (list-bind #f (e*)
+ (bind #t ([t (%constant-alloc type-typed-object
(fx+ (constant header-size-string) (fx* n (constant string-char-bytes))))])
(let loop ([e* e*] [i 0])
(if (null? e*)
@@ -6054,6 +6478,7 @@
[(e) (extract-length (%mref ,e ,(constant type-disp)) (constant length-offset))])]))
(def-len vector-length vector-type-disp vector-length-offset)
(def-len fxvector-length fxvector-type-disp fxvector-length-offset)
+ (def-len flvector-length flvector-type-disp flvector-length-offset)
(def-len string-length string-type-disp string-length-offset)
(def-len bytevector-length bytevector-type-disp bytevector-length-offset)
(def-len $bignum-length bignum-type-disp bignum-length-offset)
@@ -6073,6 +6498,7 @@
(label ,Lerr ,(build-libcall #t #f sexpr prim e)))))])]))
(def-len vector-length mask-vector type-vector vector-type-disp vector-length-offset)
(def-len fxvector-length mask-fxvector type-fxvector fxvector-type-disp fxvector-length-offset)
+ (def-len flvector-length mask-flvector type-flvector flvector-type-disp flvector-length-offset)
(def-len string-length mask-string type-string string-type-disp string-length-offset)
(def-len bytevector-length mask-bytevector type-bytevector bytevector-type-disp bytevector-length-offset)
(def-len stencil-vector-mask mask-stencil-vector type-stencil-vector stencil-vector-type-disp stencil-vector-mask-offset))
@@ -6553,6 +6979,8 @@
(when-feature pthreads
(define-inline 2 $raw-tc-mutex
[() `(literal ,(make-info-literal #f 'entry (lookup-c-entry raw-tc-mutex) 0))])
+ (define-inline 2 $raw-terminated-cond
+ [() `(literal ,(make-info-literal #f 'entry (lookup-c-entry raw-terminated-cond) 0))])
(define-inline 2 $raw-collect-cond
[() `(literal ,(make-info-literal #f 'entry (lookup-c-entry raw-collect-cond) 0))])
(define-inline 2 $raw-collect-thread0-cond
@@ -6762,6 +7190,19 @@
[(e0 e1) (build-libcall #f src sexpr fxsll e0 e1)])
(define-inline 2 fxarithmetic-shift-left
[(e0 e1) (build-libcall #f src sexpr fxarithmetic-shift-left e0 e1)])
+ (define-inline 2 fxsll/wraparound
+ [(e1 e2)
+ (bind #t (e1 e2)
+ `(if ,(nanopass-case (L7 Expr) e2
+ [(quote ,d)
+ (guard (target-fixnum? d)
+ ($fxu< d (fx+ 1 (constant fixnum-bits))))
+ (build-fixnums? (list e1 e2))]
+ [else
+ (build-and (build-fixnums? (list e1 e2))
+ (%inline u< ,e2 (immediate ,(fix (fx+ 1 (constant fixnum-bits))))))])
+ ,(%inline sll ,e1 ,(build-unfix e2))
+ ,(build-libcall #t src sexpr fxsll/wraparound e1 e2)))])
(define-inline 3 display-string
[(e-s) (build-libcall #f src sexpr display-string e-s (%tc-ref current-output))]
[(e-s e-op) (build-libcall #f src sexpr display-string e-s e-op)])
@@ -9122,8 +9563,8 @@
[(e-name e-handler e-ib e-ob) (go e-name e-handler e-ib e-ob `(quote #f))]
[(e-name e-handler e-ib e-ob e-info) (go e-name e-handler e-ib e-ob e-info)]))))
(let ()
- (define build-fxvector-ref-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-fxvector mask-fxvector fxvector-immutable-flag))
- (define build-fxvector-set!-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-mutable-fxvector mask-mutable-fxvector fxvector-immutable-flag))
+ (define build-fxvector-ref-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-fxvector mask-fxvector never-immutable-flag))
+ (define build-fxvector-set!-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-fxvector mask-fxvector never-immutable-flag))
(define-inline 2 $fxvector-ref-check?
[(e-fv e-i) (bind #t (e-fv e-i) (build-fxvector-ref-check e-fv e-i #f))])
(define-inline 2 $fxvector-set!-check?
@@ -9162,9 +9603,55 @@
(bind #t (e-fv e-i e-new)
`(if ,(build-fxvector-set!-check e-fv e-i e-new)
,(go e-fv e-i e-new)
- ,(build-libcall #t src sexpr fxvector-set! e-fv e-i e-new)))])
- (define-inline 3 $fxvector-set-immutable!
- [(e-fv) ((build-set-immutable! fxvector-type-disp fxvector-immutable-flag) e-fv)])))
+ ,(build-libcall #t src sexpr fxvector-set! e-fv e-i e-new)))])))
+ (let ()
+ (define build-flvector-ref-check (build-ref-check flvector-type-disp maximum-flvector-length flvector-length-offset type-flvector mask-flvector never-immutable-flag))
+ (define build-flvector-set!-check (build-ref-check flvector-type-disp maximum-flvector-length flvector-length-offset type-flvector mask-flvector never-immutable-flag))
+ (define-inline 2 $flvector-ref-check?
+ [(e-fv e-i) (bind #t (e-fv e-i) (build-flvector-ref-check e-fv e-i #f))])
+ (define-inline 2 $flvector-set!-check?
+ [(e-fv e-i) (bind #t (e-fv e-i) (build-flvector-set!-check e-fv e-i #f))])
+ (let ()
+ (define (go e-fv e-i)
+ (cond
+ [(expr->index e-i 1 (constant maximum-flvector-length)) =>
+ (lambda (index)
+ `(unboxed-fp ,(%mref ,e-fv ,%zero ,(+ (fx* index (constant flonum-bytes)) (constant flvector-data-disp)) fp)))]
+ [else `(unboxed-fp ,(%mref ,e-fv ,(build-double-scale e-i) ,(constant flvector-data-disp) fp))]))
+ (define-inline 3 flvector-ref
+ [(e-fv e-i) (go e-fv e-i)])
+ (define-inline 2 flvector-ref
+ [(e-fv e-i)
+ (bind #t (e-fv e-i)
+ `(if ,(build-flvector-ref-check e-fv e-i #f)
+ ,(go e-fv e-i)
+ ,(build-libcall #t src sexpr flvector-ref e-fv e-i)))]))
+ (let ()
+ (define (go e-fv e-i e-new)
+ `(set!
+ ,(cond
+ [(expr->index e-i 1 (constant maximum-flvector-length)) =>
+ (lambda (index)
+ (%mref ,e-fv ,%zero ,(+ (fx* index (constant flonum-bytes)) (constant flvector-data-disp)) fp))]
+ [else (%mref ,e-fv ,(build-double-scale e-i) ,(constant flvector-data-disp) fp)])
+ ,e-new))
+ (define (checked-go src sexpr e-fv e-i e-new add-check)
+ `(if ,(add-check (build-flvector-set!-check e-fv e-i #f))
+ ,(go e-fv e-i e-new)
+ ,(build-libcall #t src sexpr flvector-set! e-fv e-i e-new)))
+ (define-inline 3 flvector-set!
+ [(e-fv e-i e-new)
+ (go e-fv e-i e-new)])
+ (define-inline 2 flvector-set!
+ [(e-fv e-i e-new)
+ (bind #t (e-fv e-i)
+ (if (known-flonum-result? e-new)
+ (bind #t fp (e-new)
+ (checked-go src sexpr e-fv e-i e-new values))
+ (bind #t (e-new)
+ (checked-go src sexpr e-fv e-i e-new
+ (lambda (e)
+ (build-and e (build-flonums? (list e-new))))))))])))
(let ()
(define build-string-ref-check
(lambda (e-s e-i)
@@ -9465,7 +9952,14 @@
,(%mref ,e-bv ,(constant bytevector-type-disp))
,(%constant bytevector-length-offset))
e-fill)
- ,(%constant svoid)))]))
+ ,(%constant svoid)))])
+ (define-inline 2 bytevector->immutable-bytevector
+ [(e-bv)
+ (nanopass-case (L7 Expr) e-bv
+ [(quote ,d)
+ (guard (bytevector? d) (= 0 (bytevector-length d)))
+ `(literal ,(make-info-literal #f 'entry (lookup-c-entry null-immutable-bytevector) 0))]
+ [else #f])]))
(let ()
(define build-bytevector
@@ -10011,7 +10505,14 @@
(constant string-length-offset)
(constant string-char-offset))
e-fill))
- ,(%constant svoid))]))
+ ,(%constant svoid))])
+ (define-inline 2 string->immutable-string
+ [(e-str)
+ (nanopass-case (L7 Expr) e-str
+ [(quote ,d)
+ (guard (string? d) (= 0 (string-length d)))
+ `(literal ,(make-info-literal #f 'entry (lookup-c-entry null-immutable-string) 0))]
+ [else #f])]))
(let ()
(define build-fxvector-fill
@@ -10085,6 +10586,59 @@
,(%constant svoid))]))
(let ()
+ ;; Used only to fill with 0s:
+ (define build-flvector-fill
+ (make-build-fill (constant ptr-bytes) (constant flvector-data-disp)))
+ (meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset)))
+ (let ()
+ (define do-make-flvector
+ (lambda (e-length)
+ (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x 10000))) e-length)
+ (let ([n (constant-value e-length)])
+ (if (fx= n 0)
+ `(quote ,(flvector))
+ (let ([bytes (fx* n (constant flonum-bytes))])
+ (bind #t ([t (%constant-alloc type-typed-object
+ (fx+ (constant header-size-flvector) bytes))])
+ `(seq
+ (set! ,(%mref ,t ,(constant flvector-type-disp))
+ (immediate ,(fx+ (fx* n (constant flvector-length-factor))
+ (constant type-flvector))))
+ ,(build-flvector-fill t `(immediate ,bytes) `(immediate 0)))))))
+ (bind #t (e-length) ; fixnum length doubles as byte count
+ (let ([t-fxv (make-tmp 'tfxv)])
+ `(if ,(%inline eq? ,e-length (immediate 0))
+ (quote ,(flvector))
+ (let ([,t-fxv (alloc ,(make-info-alloc (constant type-typed-object) #f #f)
+ ,(%inline logand
+ ,(%inline + ,(build-double-scale e-length)
+ (immediate ,(fx+ (constant header-size-flvector)
+ (fx- (constant byte-alignment) 1))))
+ (immediate ,(- (constant byte-alignment)))))])
+ (seq
+ (set! ,(%mref ,t-fxv ,(constant flvector-type-disp))
+ ,(build-type/length e-length
+ (constant type-flvector)
+ (constant fixnum-offset)
+ (constant flvector-length-offset)))
+ ,(build-flvector-fill t-fxv (build-double-scale e-length) `(immediate 0))))))))))
+ (define-inline 3 make-flvector
+ [(e-length) (do-make-flvector e-length)]
+ [(e-length e-init) #f])
+ (let ()
+ (define (valid-length? e-length)
+ (constant?
+ (lambda (x)
+ (and (or (fixnum? x) (bignum? x))
+ (<= 0 x (constant maximum-flvector-length))))
+ e-length))
+ (define-inline 2 make-flvector
+ [(e-length)
+ (and (valid-length? e-length)
+ (do-make-flvector e-length))]
+ [(e-length e-init) #f]))))
+
+ (let ()
(define build-vector-fill
(make-build-fill (constant ptr-bytes) (constant vector-data-disp)))
(meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset)))
@@ -10138,7 +10692,14 @@
[(e-length e-fill)
(and (valid-length? e-length)
(constant? fixnum? e-fill)
- (do-make-vector e-length e-fill))]))))
+ (do-make-vector e-length e-fill))]))
+ (define-inline 2 vector->immutable-vector
+ [(e-vec)
+ (nanopass-case (L7 Expr) e-vec
+ [(quote ,d)
+ (guard (vector? d) (fx= 0 (vector-length d)))
+ `(literal ,(make-info-literal #f 'entry (lookup-c-entry null-immutable-vector) 0))]
+ [else #f])])))
(let ()
(meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset)))
@@ -10540,23 +11101,34 @@
,e-rtd))))))
(define build-unsealed-isa?
(lambda (e e-rtd)
- (let ([t (make-assigned-tmp 't)] [Ltop (make-local-label 'Ltop)])
- (bind #t (e e-rtd)
- (build-and
- (%type-check mask-typed-object type-typed-object ,e)
- `(let ([,t ,(%mref ,e ,(constant typed-object-type-disp))])
- ,(build-simple-or
- (%inline eq? ,t ,e-rtd)
- (build-and
+ (let ([t (make-tmp 't)] [a (make-tmp 'a)])
+ (let ([known-depth (nanopass-case (L7 Expr) e-rtd
+ [(quote ,d) (and (record-type-descriptor? d)
+ (vector-length (rtd-ancestors d)))]
+ [else #f])])
+ (bind #t (e e-rtd)
+ (build-and
+ (%type-check mask-typed-object type-typed-object ,e)
+ `(let ([,t ,(%mref ,e ,(constant typed-object-type-disp))])
+ ,(build-simple-or
+ (%inline eq? ,t ,e-rtd)
+ (build-and
(%type-check mask-record type-record ,t)
- `(label ,Ltop
- (seq
- (set! ,t ,(%mref ,t ,(constant record-type-parent-disp)))
- ,(build-simple-or
- (%inline eq? ,t ,e-rtd)
- `(if ,(%inline eq? ,t ,(%constant sfalse))
- ,(%constant sfalse)
- (goto ,Ltop)))))))))))))
+ `(let ([,a ,(%mref ,t ,(constant record-type-ancestry-disp))])
+ ,(begin
+ ;; take advantage of being able to use the type field of a vector
+ ;; as a pointer offset with just shifting:
+ (safe-assert (zero? (constant type-vector)))
+ (bind #f ([d (%inline -/pos ,(%mref ,a ,(constant vector-type-disp))
+ ,(if known-depth
+ `(immediate ,(fxsll known-depth (constant vector-length-offset)))
+ (%mref ,(%mref ,e-rtd ,(constant record-type-ancestry-disp))
+ ,(constant vector-type-disp))))])
+ `(if (inline ,(make-info-condition-code 'positive #f #t) ,%condition-code)
+ ,(%inline eq? ,e-rtd ,(%mref ,a
+ ,(translate d (constant vector-length-offset) (constant log2-ptr-bytes))
+ ,(fx- (constant vector-data-disp) (constant ptr-bytes))))
+ ,(%constant sfalse))))))))))))))
(define-inline 3 record?
[(e) (build-record? e)]
[(e e-rtd)
@@ -11115,7 +11687,7 @@
(lambda (ir setup*)
(if (var? ir)
(values ir setup*)
- (let ([tmp (make-tmp 't 'uptr)])
+ (let ([tmp (make-tmp 't 'ptr)])
(values tmp (cons (Rhs ir tmp) setup*))))))
(define Lvalue?
(lambda (x)
@@ -11168,7 +11740,7 @@
(literal ,(make-info-literal #t 'object '$oops (constant symbol-value-disp)))
,(%constant sfalse)
(literal ,(make-info-literal #f 'object
- (format "returned ~r values to single value return context"
+ (format "returned ~a values to single value return context"
(length t*)) 0)))
(set! ,lvalue ,(%constant svoid)))]
[else (sorry! who "unexpected Rhs expression ~s" e)])))))))
@@ -11586,7 +12158,7 @@
(literal ,(make-info-literal #t 'object '$oops (constant symbol-value-disp)))
,(%constant sfalse)
(literal ,(make-info-literal #f 'object
- (format "returned ~r values to single value return context"
+ (format "returned ~a values to single value return context"
(length t*)) 0))
())
(true))])
@@ -16311,12 +16883,15 @@
(define asm-rp-compact-header
(lambda (code* err? fs lpm func code-size)
(let ([size (constant-case ptr-bits [(32) 'long] [(64) 'quad])])
- (let* ([code* (cons* `(,size . ,(fxior (constant compact-header-mask)
- (if err?
- (constant compact-header-values-error-mask)
- 0)
- (fxsll fs (constant compact-frame-words-offset))
- (fxsll lpm (constant compact-frame-mask-offset))))
+ (let* ([code* (cons* `(,size . ,(let ([v (bitwise-ior
+ (constant compact-header-mask)
+ (if err?
+ (constant compact-header-values-error-mask)
+ 0)
+ (bitwise-arithmetic-shift-left fs (constant compact-frame-words-offset))
+ (bitwise-arithmetic-shift-left lpm (constant compact-frame-mask-offset)))])
+ (safe-assert (target-fixnum? v))
+ v))
(aop-cons* `(asm "mrv pt:" (,lpm ,fs ,(if err? 'error 'continue)))
code*))]
[code* (cons*
@@ -18561,6 +19136,9 @@
(pass np-convert-closures unparse-L6)
(pass np-optimize-direct-call unparse-L6)
(pass np-identify-scc unparse-L6)
+ (if ($lift-closures)
+ (pass np-lift-well-known-closures unparse-L6)
+ (lambda (ir) ir))
(if ($optimize-closures)
(pass np-expand/optimize-closures unparse-L7)
(pass np-expand-closures unparse-L7))
@@ -18606,4 +19184,6 @@
(set! $track-static-closure-counts track-static-closure-counts)
(set! $optimize-closures (make-parameter #t (lambda (x) (and x #t))))
+
+ (set! $lift-closures (make-parameter #t (lambda (x) (and x #t))))
)