Don't optimize mixed-mode arithmetic if it would change results.

original commit: 93939f45d01206121b5c129ac2c7ba5ed89f7564
This commit is contained in:
Vincent St-Amour 2012-12-04 15:05:33 -05:00
parent 17c30d1648
commit 21e2041a79

View File

@ -106,17 +106,41 @@
(begin (log-optimization "unary float" float-opt-msg this-syntax)
#'(op.unsafe f.opt)))
(pattern (#%plain-app (~var op (float-op binary-float-ops))
;; for now, accept anything that can be coerced to float
;; finer-grained checking is done below
f1:float-arg-expr
f2:float-arg-expr
fs:float-arg-expr ...)
;; if the result is a float, we can coerce integers to floats and optimize
#:when (let* ([safe-to-opt? (subtypeof? this-syntax -Flonum)]
;; if we don't have a return type of float, we missed an optimization
;; opportunity, report it
#:when (let* ([safe-to-opt?
;; For it to be safe, we need:
;; - the result to be a float, in which case coercing args to floats
;; won't change the result type
;; - if we're multiplying or dividing, all the args need to be actual
;; floats, can't coerce anything (o/w can turn division by 0 into a
;; non-error)
;; - for other operations, only one argument can be coerced. If more
;; than one needs coercion, we could end up turning exact (or
;; single-float) operations into float operations by accident.
;; (Note: could allow for more args, if not next to each other, but
;; probably not worth the trouble (most ops have 2 args anyway))
(and (subtypeof? this-syntax -Flonum)
(cond [(or (free-identifier=? #'op #'*)
(free-identifier=? #'op #'/))
(for/and ([a (in-list (syntax->list #'(f1 f2 fs ...)))])
(subtypeof? a -Flonum))]
[else
(>= 1
(for/sum ([a (in-list (syntax->list #'(f1 f2 fs ...)))]
#:when (not (subtypeof? a -Flonum)))
1))]))]
;; if we don't have a return type of float, or if the return type is
;; float, but we can't optimizer for some other reason, we missed an
;; optimization opportunity, report it
;; ignore operations that stay within integers or rationals, since
;; these have nothing to do with float optimizations
[missed-optimization? (and (not safe-to-opt?)
(in-real-layer? this-syntax))])
(or (in-real-layer? this-syntax)
(in-float-layer? this-syntax)))])
(when missed-optimization?
(log-float-real-missed-opt
this-syntax