Don't optimize mixed-mode arithmetic if it would change results.
original commit: 93939f45d01206121b5c129ac2c7ba5ed89f7564
This commit is contained in:
parent
17c30d1648
commit
21e2041a79
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user