Note [BindInfo and FloatInfo]

GHC/CoreToStg/Prep.hs:1945 compiler

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

Referenced by 7