diff --git a/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/optimizer/float-complex.rkt b/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/optimizer/float-complex.rkt index fd82acab..a5a33644 100644 --- a/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/optimizer/float-complex.rkt +++ b/pkgs/typed-racket-pkgs/typed-racket-lib/typed-racket/optimizer/float-complex.rkt @@ -30,7 +30,6 @@ (define-merged-syntax-class projection^ (real-part^ imag-part^)) (define-merged-syntax-class float-complex-op (+^ -^ *^ conjugate^ exp^)) -(define-merged-syntax-class float-complex->float-op (magnitude^ projection^)) (define-syntax-class/specialize float-expr (subtyped-expr -Flonum)) (define-syntax-class/specialize float-complex-expr (subtyped-expr -FloatComplex)) @@ -270,16 +269,6 @@ #`(c.bindings ... ((imag-binding) (unsafe-fl* -1.0 c.imag-binding)))) - (pattern (#%plain-app op:magnitude^ c:unboxed-float-complex-opt-expr) - #:with real-binding (generate-temporary "unboxed-real-") - #:with imag-binding #'0.0 - #:do [(log-unboxing-opt "unboxed unary float complex")] - #:with (bindings ...) - #`(c.bindings ... - ((real-binding) - (unsafe-flsqrt - (unsafe-fl+ (unsafe-fl* c.real-binding c.real-binding) - (unsafe-fl* c.imag-binding c.imag-binding)))))) (pattern (#%plain-app op:exp^ c:unboxed-float-complex-opt-expr) #:when (or (subtypeof? this-syntax -FloatComplex) @@ -293,25 +282,6 @@ ((real-binding) (unsafe-fl* (unsafe-flcos c.imag-binding) scaling-factor)) ((imag-binding) (unsafe-fl* (unsafe-flsin c.imag-binding) scaling-factor)))) - (pattern (#%plain-app op:real-part^ c:unboxed-float-complex-opt-expr) - #:with real-binding #'c.real-binding - #:with imag-binding #'0.0 - #:do [(log-unboxing-opt "unboxed unary float complex")] - #:with (bindings ...) #'(c.bindings ...)) - (pattern (#%plain-app op:imag-part^ c:unboxed-float-complex-opt-expr) - #:with real-binding #'c.imag-binding - #:with imag-binding #'0.0 - #:do [(log-unboxing-opt "unboxed unary float complex")] - #:with (bindings ...) #'(c.bindings ...)) - - ;; special handling of reals inside complex operations - ;; must be after any cases that we are supposed to handle - (pattern e:float-arg-expr - #:with real-binding (generate-temporary 'unboxed-float-) - #:with imag-binding #'0.0 - #:do [(log-unboxing-opt "float-arg-expr in complex ops")] - #:with (bindings ...) #`(((real-binding) e.opt))) - ;; we can eliminate boxing that was introduced by the user (pattern (#%plain-app op:make-rectangular^ real:float-arg-expr imag:float-arg-expr) @@ -351,14 +321,6 @@ #:with (bindings ...) #`(((real-binding) '#,(real->double-flonum (real-part n))) ((imag-binding) '#,(real->double-flonum (imag-part n))))) - (pattern (quote n*:number) - #:do [(define n (syntax->datum #'n*))] - #:when (real? n) - #:with real-binding (generate-temporary "unboxed-real-") - #:with imag-binding #'0.0 - #:do [(log-unboxing-opt "unboxed literal")] - #:with (bindings ...) - #`(((real-binding) '#,(real->double-flonum n)))) (pattern e:float-complex-expr #:with e* (generate-temporary) @@ -368,6 +330,14 @@ #`(((e*) e.opt) ((real-binding) (unsafe-flreal-part e*)) ((imag-binding) (unsafe-flimag-part e*)))) + + ;; The following optimizations are incorrect and cause bugs because they turn exact numbers into inexact + (pattern e:float-arg-expr + #:with real-binding (generate-temporary 'unboxed-float-) + #:with imag-binding #'0.0 + #:do [(log-unboxing-opt "float-arg-expr in complex ops")] + #:with (bindings ...) #`(((real-binding) e.opt))) + (pattern e:opt-expr #:when (subtypeof? #'e -Number) ; complex, maybe exact, maybe not #:with e* (generate-temporary) @@ -420,17 +390,6 @@ ;; required, otherwise syntax/parse is not happy #:with opt #'#f) - ;; we can optimize taking the real of imag part of an unboxed complex - ;; hopefully, the compiler can eliminate unused bindings for the other part if it's not used - (pattern (#%plain-app op:projection^ c:float-complex-expr) - #:with c*:unboxed-float-complex-opt-expr #'c - #:do [(log-unboxing-opt "complex accessor elimination")] - #:with opt #`(let*-values (c*.bindings ...) - #,(if (or (free-identifier=? #'op #'real-part) - (free-identifier=? #'op #'flreal-part) - (free-identifier=? #'op #'unsafe-flreal-part)) - #'c*.real-binding - #'c*.imag-binding))) (pattern (#%plain-app op:make-polar^ r theta) #:when (subtypeof? this-syntax -FloatComplex) @@ -453,13 +412,32 @@ #:commit #:attributes (opt) - (pattern (#%plain-app op:float-complex->float-op e:expr ...) - #:when (subtypeof? this-syntax -Flonum) + ;; we can optimize taking the real of imag part of an unboxed complex + ;; hopefully, the compiler can eliminate unused bindings for the other part if it's not used + (pattern (#%plain-app _:projection^ _:float-complex-expr) #:attr opt (delay (syntax-parse this-syntax - (exp:unboxed-float-complex-opt-expr - #'(let*-values (exp.bindings ...) exp.real-binding))))) + [(#%plain-app op:projection^ c:unboxed-float-complex-opt-expr) + (log-unboxing-opt "complex accessor elimination") + #`(let*-values (c.bindings ...) + #,(if (or (free-identifier=? #'op #'real-part) + (free-identifier=? #'op #'flreal-part) + (free-identifier=? #'op #'unsafe-flreal-part)) + #'c.real-binding + #'c.imag-binding))]))) + + (pattern (#%plain-app _:magnitude^ _:float-complex-expr) + #:attr opt + (delay + (syntax-parse this-syntax + [(#%plain-app op:magnitude^ c:unboxed-float-complex-opt-expr) + (log-unboxing-opt "unboxed unary float complex") + #`(let*-values (c.bindings ...) + (unsafe-flsqrt + (unsafe-fl+ (unsafe-fl* c.real-binding c.real-binding) + (unsafe-fl* c.imag-binding c.imag-binding))))]))) + (pattern (#%plain-app op:float-complex-op e:expr ...) #:when (subtypeof? this-syntax -FloatComplex) diff --git a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/known-bugs.rkt b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/known-bugs.rkt index 257d5474..44055869 100644 --- a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/known-bugs.rkt +++ b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/known-bugs.rkt @@ -57,7 +57,7 @@ (test-suite "Known bugs" ;; Arguments are converted to inexact too early - (good-opt (* (make-rectangular -inf.0 1) (* 1 1))) + (bad-opt (* (make-rectangular -inf.0 1) (* 1 1))) (bad-opt (/ -inf.0-inf.0i 8)) (good-opt (- (* -1 1 +nan.0) 1.0+1.0i)) (good-opt (- (* (/ 6 11) (/ 1.2345678f0 123456.7f0)) (make-rectangular 0.0 0.3))) diff --git a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/tests/float-complex-parts3.rkt b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/tests/float-complex-parts3.rkt index 15b5a50c..74fe7593 100644 --- a/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/tests/float-complex-parts3.rkt +++ b/pkgs/typed-racket-pkgs/typed-racket-test/tests/typed-racket/optimizer/tests/float-complex-parts3.rkt @@ -1,29 +1,33 @@ #;#; #<