You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Original bug ID: 7023 Reporter:@alainfrisch Assigned to:@alainfrisch Status: resolved (set by @alainfrisch on 2016-07-13T07:27:23Z) Resolution: fixed Priority: normal Severity: minor Target version: 4.03.1+dev Fixed in version: 4.04.0 +dev / +beta1 / +beta2 Category: back end (clambda to assembly) Monitored by:@diml@jmeber
Bug description
This is to document a bad behavior of the current unboxing strategy. While let-bound identifiers are unboxed when the bound expression would always returns an explicitly boxed value, function arguments, or identifiers bound to already boxed values, are never unboxed, thus potentially preventing the unboxing of other let-bound identifiers.
Examples:
let f1 b x =
let y =
if b then x else x +. 1.
in
y *. 2.
let f2 b g =
let x = g () in
let y =
if b then x (* or g() *) else x +. 1.
in
y *. 2.
In both cases, the x identifier is not unboxed, which then prevents y to be unboxed itself (because the "then" branch returns something which is not considered to be a boxed thing). This means than "x +. 1" requires boxing when b is false.
One possible approach would be to relax Cmmgen.is_unboxed_number so that branching constructions (including if-then-else) are considered to return "immediately unboxable" number if at least one branch does so, while currently all branches must do so. But one needs to be careful, because:
This could actually create more boxing (as in "let y = if b then g () else 1. in h y" when b is true).
This might be unsafe if branches return different types (possible with GADTs).
1 is probably not too bad in practice. A possible way to address 2 is to keep more type information for bound identifiers at the Clambda level, or to keep track of "GADT opening" explicitly in this representation (as a special kind of branch). To illustrate the dangerous case, consider:
type _ is_float =
| Yes: float is_float
| No: 'a is_float
let f (type t) (b : t is_float) (g : unit -> t) : t =
let x = g () in
let y : t =
match b with
| Yes -> x +. 1.
| No -> x
in
match b with
| Yes -> y *. 1.
| No -> y
(on top of unbox_earlier) to experiment with keeping some type info about let-bound identifiers. In cmmgen, when translating a "let x = ... in ..." and "x" has been marked (by Translcore) to be a "boxed number", then the criterion for unboxing the bound identifier is relaxed; in case of a branch construct, only one branch needs to box its result to trigger the unboxing scheme (and not all branches).
eliminates boxing for the examples in this ticket. It remembers which let-bound identifiers are floats by marking them using a flag directly attached to the Ident.t (this seems to be the lighter way to pass the info down to cmm). This could be generalized to other types as well (and actually a single flag for all of them is enough; we just need to know that the identifier was not bound to an "unknown" type, i.e. a GADT existential).
Original bug ID: 7023
Reporter: @alainfrisch
Assigned to: @alainfrisch
Status: resolved (set by @alainfrisch on 2016-07-13T07:27:23Z)
Resolution: fixed
Priority: normal
Severity: minor
Target version: 4.03.1+dev
Fixed in version: 4.04.0 +dev / +beta1 / +beta2
Category: back end (clambda to assembly)
Monitored by: @diml @jmeber
Bug description
This is to document a bad behavior of the current unboxing strategy. While let-bound identifiers are unboxed when the bound expression would always returns an explicitly boxed value, function arguments, or identifiers bound to already boxed values, are never unboxed, thus potentially preventing the unboxing of other let-bound identifiers.
Examples:
In both cases, the x identifier is not unboxed, which then prevents y to be unboxed itself (because the "then" branch returns something which is not considered to be a boxed thing). This means than "x +. 1" requires boxing when b is false.
One possible approach would be to relax Cmmgen.is_unboxed_number so that branching constructions (including if-then-else) are considered to return "immediately unboxable" number if at least one branch does so, while currently all branches must do so. But one needs to be careful, because:
This could actually create more boxing (as in "let y = if b then g () else 1. in h y" when b is true).
This might be unsafe if branches return different types (possible with GADTs).
1 is probably not too bad in practice. A possible way to address 2 is to keep more type information for bound identifiers at the Clambda level, or to keep track of "GADT opening" explicitly in this representation (as a special kind of branch). To illustrate the dangerous case, consider:
which results in:
and in this case, it would be incorrect to unbox y.
The text was updated successfully, but these errors were encountered: