Note [Floating in CorePrep]
ANFisation risks producing a lot of nested lets that obscures values:
let v = (:) (f 14) [] in e
==> { ANF in CorePrep }
let v = let sat = f 14 in (:) sat [] in e
Here, `v` is not a value anymore, and we'd allocate a thunk closure for `v` that
allocates a thunk for `sat` and then allocates the cons cell.
Hence we carry around a bunch of floated bindings with us so that we again
expose the values:
let v = let sat = f 14 in (:) sat [] in e
==> { Float sat }
let sat = f 14 in
let v = (:) sat [] in e
(We will not do this transformation if `v` does not become a value afterwards;
see Note [wantFloatLocal].)
If `v` is bound at the top-level, we might even float `sat` to top-level;
see Note [Floating out of top level bindings].
For nested let bindings, we have to keep in mind Note [Core letrec invariant]
and may exploit strict contexts; see Note [wantFloatLocal].
There are 3 main categories of floats, encoded in the `FloatingBind` type:
* `Float`: A floated binding, as `sat` above.
These come in different flavours as described by their `FloatInfo` and
`BindInfo`, which captures how far the binding can be floated and whether or
not we want to case-bind. See Note [BindInfo and FloatInfo].
* `UnsafeEqualityCase`: Used for floating around unsafeEqualityProof bindings;
see (U3) of Note [Implementing unsafeCoerce].
It's exactly a `Float` that is `CaseBound` and `LazyContextFloatable`
(see `mkNonRecFloat`), but one that has a non-DEFAULT Case alternative to
bind the unsafe coercion field of the Refl constructor.
* `FloatTick`: A floated `Tick`. See Note [Floating Ticks in CorePrep].
It is quite essential that CorePrep *does not* rearrange the order in which
evaluations happen, in contrast to, e.g., FloatOut, because CorePrep lowers
the seq# primop into a Case (see Note [seq# magic]). Fortunately, CorePrep does
not attempt to reorder the telescope of Floats or float out out of non-floated
binding sites (such as Case alts) in the first place; for that it would have to
do some kind of data dependency analysis. References 7
- Core letrec invariant GHC.Core
- BindInfo and FloatInfo GHC.CoreToStg.Prep
- Floating out of top level bindings GHC.CoreToStg.Prep
- Floating Ticks in CorePrep GHC.CoreToStg.Prep
- wantFloatLocal GHC.CoreToStg.Prep
- Implementing unsafeCoerce GHC.Internal.Unsafe.Coerce
- seq# magic GHC.Types.Id.Make
Referenced by 3
- GHC.CoreToStg.Prep call site ×2
- CorePrep Overview GHC.CoreToStg.Prep