refactor np-expand-primitives unboxing

Shift addition of boxing as needed into the main loop, infer unboxed
variables and `mref`s, and centralize lifting of the `unboxed-fp`
declaration.

original commit: ed8ca4b6c77bdd436b0dee467a8350a450a44fb3
This commit is contained in:
Matthew Flatt 2020-06-12 09:21:46 -06:00
parent 1ce6d97369
commit d26b54dd52
2 changed files with 143 additions and 153 deletions

View File

@ -1126,6 +1126,7 @@
(fl= 66.0 (many-add 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0)))
(eqv? (let ([x 4.0]) (fl+ x)) 4.0)
(eqv? (let ([x 4.0]) (fl+ (fl- x 1.0))) 3.0)
(eqv? (let ([x 5.0]) (fl* x)) 5.0)
)

View File

@ -2919,7 +2919,7 @@
[(seq ,e0 ,e1) (flonum-result? e1 (fx- fuel 1))]
[(let ([,x* ,e*] ...) ,body) (flonum-result? body (fx- fuel 1))]
[else #f]))))
(define-pass np-unbox-fp-vars! : L7 (ir) -> L7 ()
(definitions
(define unify-boxed!
@ -3074,10 +3074,10 @@
(define ht2 (make-hashtable symbol-hash eq?))
(define ht3 (make-hashtable symbol-hash eq?))
(define handle-prim
(lambda (src sexpr can-unbox-fp? level name e*)
(lambda (src sexpr level name e*)
(let ([handler (or (and (fx= level 3) (symbol-hashtable-ref ht3 name #f))
(symbol-hashtable-ref ht2 name #f))])
(and handler (handler src sexpr can-unbox-fp? e*)))))
(and handler (handler src sexpr e*)))))
(define-syntax Symref
(lambda (x)
(syntax-case x ()
@ -3132,6 +3132,14 @@
(define Expr*
(lambda (e*)
(map Expr1 e*)))
(define unboxed-fp->boxed
(lambda (e)
(let ([t (make-tmp 't)])
(with-output-language (L9 Expr)
`(let ([,t ,(%constant-alloc type-flonum (constant size-flonum))])
(seq
(set! ,(%mref ,t ,%zero ,(constant flonum-data-disp) fp) ,e)
,t))))))
(define (fp-lvalue? lvalue)
(nanopass-case (L9 Lvalue) lvalue
[,x (and (uvar? x) (eq? (uvar-type x) 'fp))]
@ -3145,6 +3153,9 @@
(CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause ()
[(clause (,x* ...) ,mcp ,interface ,[body #f -> body unboxed-fp?])
`(clause (,x* ...) ,mcp ,interface ,body)])
;; The result of `Expr` can be unboxed (second result is #t) only
;; if the `can-unbox-fp?` argument is #t, but the result can always
;; be a boxed expression (even if `can-unbox-fp?` is #t)
(Expr : Expr (ir [can-unbox-fp? #f]) -> Expr (#f)
[(quote ,d)
(values (cond
@ -3152,9 +3163,10 @@
[else `(literal ,(make-info-literal #f 'object d 0))])
#f)]
[,pr (values (Symref (primref-name pr)) #f)]
[(unboxed-fp ,[e can-unbox-fp? -> e unboxed-fp?])
(safe-assert can-unbox-fp?)
(values e #t)]
[(unboxed-fp ,[e #t -> e unboxed-fp?])
(if can-unbox-fp?
(values e #t)
(values (unboxed-fp->boxed e) #f))]
[(call ,info0 ,mdcl0
(call ,info1 ,mdcl1 ,pr (quote ,d))
,[e* #f -> e* unboxed-fp?*] ...)
@ -3167,7 +3179,7 @@
;; Note: single-valued also implies that the primitive doesn't
;; tail-call an arbitary function (which might inspect attachments):
(all-set? (prim-mask single-valued) (primref-flags pr)))
(handle-prim (info-call-src info) (info-call-sexpr info) can-unbox-fp? (primref-level pr) (primref-name pr) e*))
(handle-prim (info-call-src info) (info-call-sexpr info) (primref-level pr) (primref-name pr) e*))
=> (lambda (e)
(let-values ([(e unboxed-fp?) (Expr e can-unbox-fp?)])
(values
@ -3190,7 +3202,8 @@
(info-call-shift-consumer-attachment?* info))
info)])
(values `(call ,info ,mdcl ,(Symref (primref-name pr)) ,e* ...)
#f)))])]
;; an error can be treated as unboxed if the context wants that:
(and can-unbox-fp? (info-call-error? info)))))])]
[(call ,info ,mdcl ,x ,e* ...)
(guard (uvar-loop? x))
(let ([e* (map (lambda (x1 e)
@ -3269,11 +3282,15 @@
(values `(mvlet ,(Expr1 e) ((,x** ...) ,interface* ,(map Expr1 body*)) ...) #f)])
(Lvalue : Lvalue (ir [unboxed-fp? #f]) -> Lvalue (#f)
[(mref ,e1 ,e2 ,imm ,type)
(safe-assert (or unboxed-fp? (not (eq? type 'fp))))
(values `(mref ,(Expr1 e1) ,(Expr1 e2) ,imm ,type) (eq? type 'fp))]
(let ([e `(mref ,(Expr1 e1) ,(Expr1 e2) ,imm ,type)])
(if (and (eq? type 'fp) (not unboxed-fp?))
(values (unboxed-fp->boxed e) #f)
(values e (eq? type 'fp))))]
[,x
(safe-assert (or unboxed-fp? (not (and (uvar? x) (eq? (uvar-type x) 'fp)))))
(values x (and (uvar? x) (eq? (uvar-type x) 'fp)))]))
(let ([fp? (and (uvar? x) (eq? (uvar-type x) 'fp))])
(if (and fp? (not unboxed-fp?))
(values (unboxed-fp->boxed x) #f)
(values x fp?)))]))
(define-who unhandled-arity
(lambda (name args)
(sorry! who "unhandled argument count ~s for ~s" (length args) 'name)))
@ -3315,10 +3332,10 @@
(unless (= (bitmaskify arity) (bitmaskify (map compute-interface #'(clause ...))))
(syntax-error x (format "arity mismatch for ~s" name))))))
(check-and-record level #'id)
(with-implicit (k src sexpr moi can-unbox-fp?)
(with-implicit (k src sexpr moi)
#`(symbol-hashtable-set! #,(if (eqv? level 2) #'ht2 #'ht3) 'id
(rec moi
(lambda (src sexpr can-unbox-fp? args)
(lambda (src sexpr args)
(apply (case-lambda clause ... [rest #f]) args))))))]))))
(define no-need-to-bind?
(lambda (multiple-ref? e)
@ -3336,11 +3353,9 @@
(if (no-need-to-bind? multiple-ref? e)
(values e values)
(let ([t (make-tmp 't type)])
(values t
(lambda (body)
(nanopass-case (L7 Expr) body
[(unboxed-fp ,body) `(unboxed-fp (let ([,t ,e]) ,body))]
[else `(let ([,t ,e]) ,body)])))))))
(values t (lift-fp-unboxed
(lambda (body)
`(let ([,t ,e]) ,body))))))))
(define list-binder
(lambda (multiple-ref? type e*)
(if (null? e*)
@ -3380,6 +3395,23 @@
($bind list-binder multiple-ref? type (b ...) e)]
[(_ multiple-ref? (b ...) e)
($bind list-binder multiple-ref? ptr (b ...) e)]))
(define lift-fp-unboxed
(lambda (k)
(lambda (e)
;; Propagate unboxing information:
(nanopass-case (L7 Expr) e
[(unboxed-fp ,e) `(unboxed-fp ,(k e))]
[else
(let ([new-e (k e)])
(nanopass-case (L7 Expr) e
[(mref ,e0 ,e1 ,imm ,type)
(if (eq? type 'fp)
`(unboxed-fp ,new-e)
new-e)]
[,x (if (and (uvar? x) (eq? (uvar-type x) 'fp))
`(unboxed-fp ,new-e)
new-e)]
[else new-e]))]))))
(define-syntax build-libcall
(lambda (x)
(syntax-case x ()
@ -3961,10 +3993,8 @@
(case-lambda
[(swapped? type base offset-expr)
(let-values ([(index offset) (offset-expr->index+offset offset-expr)])
(build-object-ref swapped? type base index offset #f))]
(build-object-ref swapped? type base index offset))]
[(swapped? type base index offset)
(build-object-ref swapped? type base index offset #f)]
[(swapped? type base index offset can-unbox-fp?)
(case type
[(scheme-object) `(inline ,(make-info-load ptr-type swapped?) ,%load ,base ,index (immediate ,offset))]
[(double-float)
@ -3990,15 +4020,7 @@
(immediate ,offset)))
,t)))])
(bind #f (base index)
(cond
[can-unbox-fp?
`(unboxed-fp ,(%mref ,base ,index ,offset fp))]
[else
(bind #t ([t (%constant-alloc type-flonum (constant size-flonum))])
(%seq
(set! ,(%mref ,t ,%zero ,(constant flonum-data-disp) fp)
(unboxed-fp ,(%mref ,base ,index ,offset fp)))
,t))])))]
(%mref ,base ,index ,offset fp)))]
[(single-float)
(if swapped?
(bind #f (base index)
@ -4012,7 +4034,7 @@
,%load-single->double
;; slight abuse to call this "unboxed", but `load-single->double`
;; wants an FP-flavored address
(unboxed-fp ,(%mref ,t ,%zero ,(constant flonum-data-disp) fp)))))
,(%mref ,t ,%zero ,(constant flonum-data-disp) fp))))
,t)))
(bind #f (base index)
(bind #t ([t (%constant-alloc type-flonum (constant size-flonum))])
@ -4022,7 +4044,7 @@
,%load-single->double
;; slight abuse to call this "unboxed", but `load-single->double`
;; wants an FP-flavored address
(unboxed-fp ,(%mref ,base ,index ,offset fp)))))
,(%mref ,base ,index ,offset fp))))
,t))))]
[(integer-8 integer-16 integer-24 integer-32 integer-40 integer-48 integer-56 integer-64)
(build-int-load swapped? type base index offset
@ -4107,8 +4129,8 @@
`(inline ,(make-info-unboxed-args '(#t #t)) ,%store-double->single
;; slight abuse to call this "unboxed", but `store-double->single`
;; wants an FP-flavored address
(unboxed-fp ,(%mref ,base ,index ,offset fp))
(unboxed-fp ,(%mref ,value ,%zero ,(constant flonum-data-disp) fp))))]
,(%mref ,base ,index ,offset fp)
,(%mref ,value ,%zero ,(constant flonum-data-disp) fp)))]
; 40-bit+ only on 64-bit machines
[(integer-8 integer-16 integer-24 integer-32 integer-40 integer-48 integer-56 integer-64
unsigned-8 unsigned-16 unsigned-24 unsigned-32 unsigned-40 unsigned-48 unsigned-56 unsigned-64)
@ -4283,8 +4305,8 @@
(list-bind #f (e*)
(let compare ([src src] [e2 e2] [e* e*])
(if (null? e*)
(moi src sexpr #f (list e1 e2))
`(if ,(moi src sexpr #f (list e1 e2))
(moi src sexpr (list e1 e2))
`(if ,(moi src sexpr (list e1 e2))
,(compare #f (car e*) (cdr e*))
(quote #f))))))))))
(define reduce-inequality
@ -4296,8 +4318,8 @@
(let compare ([src src] [e* (cons e1 (reverse (cons e2 re*)))])
(let ([more-args (cddr e*)])
(if (null? more-args)
(moi src sexpr #f e*)
`(if ,(moi src sexpr #f (list (car e*) (cadr e*)))
(moi src sexpr e*)
`(if ,(moi src sexpr (list (car e*) (cadr e*)))
,(compare #f (cdr e*))
(quote #f))))))
(bind #t ([e2 e2]) (f (car e*) (cdr e*) (cons e2 re*))))))))
@ -4309,7 +4331,7 @@
(let reduce ([src src] [e e] [e* e*])
(if (null? e*)
e
(reduce #f (moi src sexpr #f (list e (car e*))) (cdr e*)))))))))
(reduce #f (moi src sexpr (list e (car e*))) (cdr e*)))))))))
(define reduce-fp-compare ; suitable for arguments known or assumed to produce flonums
(lambda (reduce)
(lambda (src sexpr moi e1 e2 e*)
@ -7233,13 +7255,13 @@
(define-relop-inline >= r6rs:>= RELOP>= >=)
(define-relop-inline > r6rs:> RELOP> >))
(define-inline 3 positive? ; 3 so opt-level 2 errors come from positive?
[(e) (handle-prim src sexpr #f 3 '> (list e `(quote 0)))])
[(e) (handle-prim src sexpr 3 '> (list e `(quote 0)))])
(define-inline 3 nonnegative? ; 3 so opt-level 2 errors come from nonnegative?
[(e) (handle-prim src sexpr #f 3 '>= (list e `(quote 0)))])
[(e) (handle-prim src sexpr 3 '>= (list e `(quote 0)))])
(define-inline 3 negative? ; 3 so opt-level 2 errors come from negative?
[(e) (handle-prim src sexpr #f 3 '< (list e `(quote 0)))])
[(e) (handle-prim src sexpr 3 '< (list e `(quote 0)))])
(define-inline 3 nonpositive? ; 3 so opt-level 2 errors come from nonpositive?
[(e) (handle-prim src sexpr #f 3 '<= (list e `(quote 0)))])
[(e) (handle-prim src sexpr 3 '<= (list e `(quote 0)))])
(define-inline 2 zero?
[(e)
(or (relop-length RELOP= e)
@ -7446,84 +7468,62 @@
,(build-not (build-fl= e2 e2))))])
(let ()
(define build-fp-boxed
(lambda (can-unbox-fp? e)
(if can-unbox-fp?
`(unboxed-fp ,e)
(bind #t ([t (%constant-alloc type-flonum (constant size-flonum))])
`(seq
(set! ,(%mref ,t ,%zero ,(constant flonum-data-disp) fp) (unboxed-fp ,e))
,t)))))
(define (unboxed-explicit->implicit e)
(nanopass-case (L7 Expr) e
[(unboxed-fp ,e) e]
[else (%mref ,e ,%zero ,(constant flonum-data-disp) fp)]))
(define build-fp-op-1
(lambda (can-unbox-fp? op e)
(lambda (op e)
(bind #f fp (e)
(build-fp-boxed can-unbox-fp? (if (procedure? op) (op e) `(inline ,(make-info-unboxed-args '(#t)) ,op ,e))))))
(if (procedure? op) (op e) `(unboxed-fp (inline ,(make-info-unboxed-args '(#t)) ,op ,e))))))
(define build-fp-op-2
(lambda (can-unbox-fp? op e1 e2)
(lambda (op e1 e2)
(bind #f fp (e1 e2)
(build-fp-boxed can-unbox-fp? `(inline ,(make-info-unboxed-args '(#t #t)) ,op ,e1 ,e2)))))
`(unboxed-fp (inline ,(make-info-unboxed-args '(#t #t)) ,op ,e1 ,e2)))))
(define build-fl-adjust-sign
(lambda (e can-unbox-fp? combine base)
(build-fp-boxed
can-unbox-fp?
(constant-case ptr-bits
[(64)
(let ([t (make-tmp 'flsgn)])
`(let ([,t (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto ,e)])
(inline ,null-info ,%fpcastfrom (inline ,null-info ,combine ,t ,base))))]
[(32)
(let ([thi (make-tmp 'flsgnh)]
[tlo (make-tmp 'flsgnl)])
(bind #t fp (e)
`(let ([,thi (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto/hi ,e)]
[,tlo (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto/lo ,e)])
(inline ,null-info ,%fpcastfrom (inline ,null-info ,combine ,thi ,base) ,tlo))))]))))
(lambda (e combine base)
`(unboxed-fp
,(constant-case ptr-bits
[(64)
(let ([t (make-tmp 'flsgn)])
`(let ([,t (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto ,e)])
(inline ,null-info ,%fpcastfrom (inline ,null-info ,combine ,t ,base))))]
[(32)
(let ([thi (make-tmp 'flsgnh)]
[tlo (make-tmp 'flsgnl)])
(bind #t fp (e)
`(let ([,thi (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto/hi ,e)]
[,tlo (inline ,(make-info-unboxed-args '(#t)) ,%fpcastto/lo ,e)])
(inline ,null-info ,%fpcastfrom (inline ,null-info ,combine ,thi ,base) ,tlo))))]))))
(define build-flabs
(lambda (e can-unbox-fp?)
(build-fl-adjust-sign e can-unbox-fp? %logand (%inline srl (immediate -1) (immediate 1)))))
(lambda (e)
(build-fl-adjust-sign e %logand (%inline srl (immediate -1) (immediate 1)))))
(define build-flneg
(lambda (e can-unbox-fp?)
(build-fl-adjust-sign e can-unbox-fp? %logxor (%inline sll (immediate -1) (immediate ,(fx- (constant ptr-bits) 1))))))
(define maybe-build-fp-boxed
;; Used for an `e` that may be implicitly unboxed because it appears
;; as an argument to a primitive that accepts unboxed arguments
(lambda (can-unbox-fp? e)
(nanopass-case (L7 Expr) e
[,x (if (and (uvar? x) (eq? (uvar-type x) 'fp))
(build-fp-boxed can-unbox-fp? e)
e)]
[else e])))
(lambda (e)
(build-fl-adjust-sign e %logxor (%inline sll (immediate -1) (immediate ,(fx- (constant ptr-bits) 1))))))
(define-inline 3 fl+
[() `(quote 0.0)]
[(e) (maybe-build-fp-boxed can-unbox-fp? (ensure-single-valued e))]
[(e1 e2) (build-fp-op-2 can-unbox-fp? %fp+ e1 e2)]
[(e) (ensure-single-valued e)]
[(e1 e2) (build-fp-op-2 %fp+ e1 e2)]
[(e1 . e*) (reduce-fp src sexpr 3 'fl+ e1 e*)])
(define-inline 3 fl*
[() `(quote 1.0)]
[(e) (maybe-build-fp-boxed can-unbox-fp? (ensure-single-valued e))]
[(e1 e2) (build-fp-op-2 can-unbox-fp? %fp* e1 e2)]
[(e) (ensure-single-valued e)]
[(e1 e2) (build-fp-op-2 %fp* e1 e2)]
[(e1 . e*) (reduce-fp src sexpr 3 'fl* e1 e*)])
(define-inline 3 fl-
[(e) (build-flneg e can-unbox-fp?)]
[(e1 e2) (build-fp-op-2 can-unbox-fp? %fp- e1 e2)]
[(e) (build-flneg e)]
[(e1 e2) (build-fp-op-2 %fp- e1 e2)]
[(e1 . e*) (reduce-fp src sexpr 3 'fl- e1 e*)])
(define-inline 3 fl/
[(e) (build-fp-op-2 can-unbox-fp? %fp/ `(quote 1.0) e)]
[(e1 e2) (build-fp-op-2 can-unbox-fp? %fp/ e1 e2)]
[(e) (build-fp-op-2 %fp/ `(quote 1.0) e)]
[(e1 e2) (build-fp-op-2 %fp/ e1 e2)]
[(e1 . e*) (reduce-fp src sexpr 3 'fl/ e1 e*)])
(define-inline 3 flsqrt
[(e)
(constant-case architecture
[(x86 x86_64 arm32) (build-fp-op-1 can-unbox-fp? %fpsqrt e)]
[(x86 x86_64 arm32) (build-fp-op-1 %fpsqrt e)]
[(ppc32) #f])])
(define-inline 3 flround
@ -7531,7 +7531,7 @@
[(e) (build-libcall #f src sexpr flround e)])
(define-inline 3 flabs
[(e) (build-flabs e can-unbox-fp?)])
[(e) (build-flabs e)])
(let ()
(define build-fl-make-rectangular
@ -7542,9 +7542,9 @@
(set! ,(%mref ,t ,(constant inexactnum-type-disp))
,(%constant type-inexactnum))
(set! ,(%mref ,t ,%zero ,(constant inexactnum-real-disp) fp)
(unboxed-fp ,(%mref ,e1 ,%zero ,(constant flonum-data-disp) fp)))
,(%mref ,e1 ,%zero ,(constant flonum-data-disp) fp))
(set! ,(%mref ,t ,%zero ,(constant inexactnum-imag-disp) fp)
(unboxed-fp ,(%mref ,e2 ,%zero ,(constant flonum-data-disp) fp)))
,(%mref ,e2 ,%zero ,(constant flonum-data-disp) fp))
,t)))))
(define-inline 3 fl-make-rectangular
@ -7553,10 +7553,10 @@
(define-inline 3 cfl-
[(e) (bind #t (e)
`(if ,(%type-check mask-flonum type-flonum ,e)
,(build-flneg e #f)
,(build-flneg e)
,(build-fl-make-rectangular
(build-flneg (build-$inexactnum-real-part e) #f)
(build-flneg (build-$inexactnum-imag-part e) #f))))]
(build-flneg (build-$inexactnum-real-part e))
(build-flneg (build-$inexactnum-imag-part e)))))]
[(e1 e2) (build-libcall #f src sexpr cfl- e1 e2)]
; TODO: add 3 argument version of cfl- library function
#;[(e1 e2 e3) (build-libcall #f src sexpr cfl- e1 e2 e3)]
@ -7591,7 +7591,7 @@
,e
,(build-fl-make-rectangular
(build-$inexactnum-real-part e)
(build-flneg (build-$inexactnum-imag-part e) #f))))]))
(build-flneg (build-$inexactnum-imag-part e)))))]))
(define-inline 3 $make-exactnum
[(e1 e2) (bind #f (e1 e2)
@ -7753,31 +7753,27 @@
(let ()
(define build-checked-fp-op
(case-lambda
[(e can-unbox-fp? k)
(maybe-build-fp-boxed
can-unbox-fp?
(if (known-flonum-result? e)
e
(bind #t (e)
`(if ,(build-flonums? (list e))
,e
,(k e)))))]
[(e1 op can-unbox-fp? k) ; `op` can be a procedure that produces an implicitly unboxed value
[(e k)
(if (known-flonum-result? e)
e
(bind #t (e)
`(if ,(build-flonums? (list e))
,e
,(k e))))]
[(e1 op k) ; `op` can be a procedure that produces an implicitly unboxed value
(if (known-flonum-result? e1)
(build-fp-op-1 can-unbox-fp? op e1)
(build-fp-op-1 op e1)
(bind #t (e1)
(let ([e (build-fp-op-1 can-unbox-fp? op e1)]
(let ([e (build-fp-op-1 op e1)]
[k (lambda (e)
`(if ,(build-flonums? (list e1))
,e
,(k e1)))])
(nanopass-case (L7 Expr) e
[(unboxed-fp ,e) `(unboxed-fp ,(k e))]
[else (k e)]))))]
[(e1 e2 op can-unbox-fp? k)
((lift-fp-unboxed k) e))))]
[(e1 e2 op k)
;; uses result of `e1` or `e2` twice for error if other is always a flonum
(let ([build (lambda (e1 e2)
(build-fp-op-2 can-unbox-fp? op e1 e2))])
(build-fp-op-2 op e1 e2))])
(if (known-flonum-result? e1)
(if (known-flonum-result? e2)
(build e1 e2)
@ -7797,50 +7793,48 @@
`(if ,(build-flonums? (list e1 e2))
,e
,(k e1 e2)))])
(nanopass-case (L7 Expr) e
[(unboxed-fp ,e) `(unboxed-fp ,(k e))]
[else (k e)]))))))]))
((lift-fp-unboxed k) e))))))]))
(define-inline 2 fl+
[() `(quote 0.0)]
[(e) (build-checked-fp-op e can-unbox-fp?
[(e) (build-checked-fp-op e
(lambda (e)
(build-libcall #t src sexpr fl+ e `(quote 0.0))))]
[(e1 e2) (build-checked-fp-op e1 e2 %fp+ can-unbox-fp?
[(e1 e2) (build-checked-fp-op e1 e2 %fp+
(lambda (e1 e2)
(build-libcall #t src sexpr fl+ e1 e2)))]
[(e1 . e*) (reduce-fp src sexpr 2 'fl+ e1 e*)])
(define-inline 2 fl*
[() `(quote 1.0)]
[(e) (build-checked-fp-op e can-unbox-fp?
[(e) (build-checked-fp-op e
(lambda (e)
(build-libcall #t src sexpr fl* e `(quote 1.0))))]
[(e1 e2) (build-checked-fp-op e1 e2 %fp* can-unbox-fp?
[(e1 e2) (build-checked-fp-op e1 e2 %fp*
(lambda (e1 e2)
(build-libcall #t src sexpr fl* e1 e2)))]
[(e1 . e*) (reduce-fp src sexpr 2 'fl* e1 e*)])
(define-inline 2 fl-
[(e) (build-checked-fp-op e (lambda (e) (unboxed-explicit->implicit (build-flneg e #t))) can-unbox-fp?
[(e) (build-checked-fp-op e build-flneg
(lambda (e)
(build-libcall #t src sexpr flnegate e)))]
[(e1 e2) (build-checked-fp-op e1 e2 %fp- can-unbox-fp?
[(e1 e2) (build-checked-fp-op e1 e2 %fp-
(lambda (e1 e2)
(build-libcall #t src sexpr fl- e1 e2)))]
[(e1 . e*) (reduce-fp src sexpr 2 'fl- e1 e*)])
(define-inline 2 fl/
[(e) (build-checked-fp-op `(quote 1.0) e %fp/ can-unbox-fp?
[(e) (build-checked-fp-op `(quote 1.0) e %fp/
(lambda (e1 e2)
(build-libcall #t src sexpr fl/ e1 e2)))]
[(e1 e2) (build-checked-fp-op e1 e2 %fp/ can-unbox-fp?
[(e1 e2) (build-checked-fp-op e1 e2 %fp/
(lambda (e1 e2)
(build-libcall #t src sexpr fl/ e1 e2)))]
[(e1 . e*) (reduce-fp src sexpr 2 'fl/ e1 e*)])
(define-inline 2 flabs
[(e) (build-checked-fp-op e (lambda (e) (unboxed-explicit->implicit (build-flabs e #t))) can-unbox-fp?
[(e) (build-checked-fp-op e build-flabs
(lambda (e)
(build-libcall #t src sexpr flabs e)))])))
@ -7852,30 +7846,25 @@
(let ()
(define build-fixnum->flonum
; NB: x must already be bound in order to ensure it is done before the flonum is allocated
(lambda (e-x can-unbox-fp? k)
(let ([e (%inline fpt ,(build-unfix e-x))])
(if can-unbox-fp?
`(unboxed-fp ,(k e))
(k (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))])
(%seq
(set! ,(%mref ,t ,%zero ,(constant flonum-data-disp) fp) (unboxed-fp ,e))
,t)))))))
(lambda (e-x k)
(k `(unboxed-fp ,(%inline fpt ,(build-unfix e-x))))))
(define-inline 3 fixnum->flonum
[(e-x) (bind #f (e-x) (build-fixnum->flonum e-x can-unbox-fp? values))])
[(e-x) (bind #f (e-x) (build-fixnum->flonum e-x values))])
(define-inline 2 fixnum->flonum
[(e-x) (bind #t (e-x)
(build-fixnum->flonum e-x can-unbox-fp?
(lambda (e)
`(if ,(%type-check mask-fixnum type-fixnum ,e-x)
,e
,(build-libcall #t src sexpr fixnum->flonum e-x)))))])
(build-fixnum->flonum e-x
(lift-fp-unboxed
(lambda (e)
`(if ,(%type-check mask-fixnum type-fixnum ,e-x)
,e
,(build-libcall #t src sexpr fixnum->flonum e-x))))))])
(define-inline 2 real->flonum
[(e-x)
(if (known-flonum-result? e-x)
e-x
(bind #t (e-x)
`(if ,(%type-check mask-fixnum type-fixnum ,e-x)
,(build-fixnum->flonum e-x #f values)
,(build-fixnum->flonum e-x values)
(if ,(%type-check mask-flonum type-flonum ,e-x)
,e-x
,(build-libcall #t src sexpr real->flonum e-x `(quote real->flonum))))))]))
@ -9314,7 +9303,7 @@
(define-inline 2 name
[(e-bv e-offset)
(bind #t (e-bv e-offset)
`(if ,(handle-prim #f #f #f 3 '$bytevector-ref-check? (list `(quote 8) e-bv e-offset))
`(if ,(handle-prim #f #f 3 '$bytevector-ref-check? (list `(quote 8) e-bv e-offset))
,(let-values ([(e-index imm-offset) (bv-index-offset e-offset)])
(build-object-ref #f 'type e-bv e-index imm-offset))
,(build-libcall #t src sexpr name e-bv e-offset)))])]))
@ -9330,7 +9319,7 @@
#'(define-inline 3 name
[(e-bv e-offset)
(let-values ([(e-index imm-offset) (bv-index-offset e-offset)])
(build-object-ref #f 'type e-bv e-index imm-offset can-unbox-fp?))])])))
(build-object-ref #f 'type e-bv e-index imm-offset))])])))
(define-bv-native-ref-inline bytevector-s8-ref integer-8)
(define-bv-native-ref-inline bytevector-u8-ref unsigned-8)
@ -9458,7 +9447,7 @@
(bv-offset-okay? e-offset mask))
(constant? (lambda (x) (eq? x (constant native-endianness))) e-eness)
(let-values ([(e-index imm-offset) (bv-index-offset e-offset)])
(build-object-ref #f 'type e-bv e-index imm-offset can-unbox-fp?)))])])))
(build-object-ref #f 'type e-bv e-index imm-offset)))])])))
(define-bv-ieee-ref-inline bytevector-ieee-single-ref single-float 3)
(define-bv-ieee-ref-inline bytevector-ieee-double-ref double-float 7))
@ -10383,12 +10372,12 @@
[(e-bop e-x)
(bind #t (e-x)
(build-libcall #f src sexpr name e-bop e-x `(immediate 0)
(handle-prim #f #f #f 3 'x-length (list e-x))))]
(handle-prim #f #f 3 'x-length (list e-x))))]
[(e-bop e-x e-start)
(bind #t (e-x e-start)
(build-libcall #f src sexpr name e-bop e-x e-start
(%inline -
,(handle-prim #f #f #f 3 'x-length (list e-x))
,(handle-prim #f #f 3 'x-length (list e-x))
,e-start)))]
[(e-bop e-x e-start e-count)
(build-libcall #f src sexpr name e-bop e-x e-start e-count)])]))