Note [BindInfo and FloatInfo]
The `BindInfo` of a `Float` describes whether it will be case-bound or
let-bound:
* `LetBound`: A let binding `let x = rhs in ...`, can be Rec or NonRec.
* `CaseBound`: A case binding `case rhs of x -> { __DEFAULT -> .. }`.
(So always NonRec.)
Some case-bound things (string literals, lifted bindings)
can float to top-level (but not all), hence it is similar
to, but not the same as `StrictContextFloatable :: FloatInfo`
described below.
This info is used in `wrapBinds` to pick the corresponding binding form.
We want to case-bind iff the binding is (non-recursive, and) either
* ok-for-spec-eval (and perhaps lifted, see Note [Speculative evaluation]), or
* unlifted, or
* strictly used
The `FloatInfo` of a `Float` describes how far it can float without
(a) violating Core invariants and (b) changing semantics.
* Any binding is at least `StrictContextFloatable`, meaning we may float it
out of a strict context such as `f <>` where `f` is strict.
We may never float out of a Case alternative `case e of p -> <>`, though,
even if we made sure that `p` does not capture any variables of the float,
because that risks sequencing guarantees of Note [seq# magic].
* A binding is `LazyContextFloatable` if we may float it out of a lazy context
such as `let x = <> in Just x`.
Counterexample: A strict or unlifted binding that isn't ok-for-spec-eval
such as `case divInt# x y of r -> { __DEFAULT -> I# r }`.
Here, we may not foat out the strict `r = divInt# x y`.
* A binding is `TopLvlFloatable` if it is `LazyContextFloatable` and also can
be bound at the top level.
Counterexample: A strict or unlifted binding (ok-for-spec-eval or not)
such as `case x +# y of r -> { __DEFAULT -> I# r }`.
This meaning of "at least" is encoded in `floatsAtLeastAsFarAs`.
Note that today, `LetBound` implies `TopLvlFloatable`, so we could make do with
the the following enum (check `mkNonRecFloat` for whether this is up to date):
LetBoundTopLvlFloatable (lifted or boxed values)
CaseBoundTopLvlFloatable (strings, ok-for-spec-eval and lifted)
CaseBoundLazyContextFloatable (ok-for-spec-eval and unlifted)
CaseBoundStrictContextFloatable (not ok-for-spec-eval and unlifted)
Although there is redundancy in the current encoding, SG thinks it is cleaner
conceptually.
See also Note [Floats and FloatDecision] for how we maintain whole groups of
floats and how far they go. References 3
- Floats and FloatDecision GHC.CoreToStg.Prep
- Speculative evaluation GHC.CoreToStg.Prep
- seq# magic GHC.Types.Id.Make
Referenced by 7
- GHC.CoreToStg.Prep call site ×4
- Floats and FloatDecision GHC.CoreToStg.Prep
- wantFloatLocal GHC.CoreToStg.Prep
- Floating in CorePrep GHC.CoreToStg.Prep