File: .lake/packages/lean4/src/lean/Lean/Compiler/LCNF/FloatLetIn.lean

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision.dont
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision.unknown
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision.arm
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Type

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision.default
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.instBEqDecision
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: BEq Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.instReprDecision
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Repr Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.instInhabitedDecision
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Inhabited Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.instHashableDecision
code: /--
The decision of the float mechanism.
-/
inductive Decision where
|
  /--
  Push into the arm with name `name`.
  -/
  arm (name : Name)
| /--
  Push into the default arm.
  -/
  default
|
  /--
  Dont move this declaration it is needed where it is right now.
  -/
  dont
|
  /--
  No decision has been made yet.
  -/
  unknown
deriving Hashable, BEq, Inhabited, Repr
goal: Hashable Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.Decision.ofAlt
code: def Decision.ofAlt : Alt → Decision

goal: Lean.Compiler.LCNF.Alt → Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.BaseFloatContext.decls
code: /--
The context for `BaseFloatM`.
-/
structure BaseFloatContext where
  /--
  All the declarations that were collected in the current LCNF basic
  block up to the current statement (in reverse order for efficiency).
  -/
  decls : List CodeDecl := []
goal: List Lean.Compiler.LCNF.CodeDecl

full_name: Lean.Compiler.LCNF.FloatLetIn.BaseFloatContext
code: /--
The context for `BaseFloatM`.
-/
structure BaseFloatContext where
  /--
  All the declarations that were collected in the current LCNF basic
  block up to the current statement (in reverse order for efficiency).
  -/
  decls : List CodeDecl := []
goal: Type

full_name: Lean.Compiler.LCNF.FloatLetIn.FloatState.decision
code: /--
The state for `FloatM`
-/
structure FloatState where
  /--
  A map from identifiers of declarations to their current decision.
  -/
  decision : HashMap FVarId Decision
  /--
  A map from decisions (excluding `unknown`) to the declarations with
  these decisions (in correct order). Basically:
  - Which declarations do we not move
  - Which declarations do we move into a certain arm
  - Which declarations do we move into the default arm
  -/
  newArms : HashMap Decision (List CodeDecl)
goal: Lean.HashMap Lean.FVarId Lean.Compiler.LCNF.FloatLetIn.Decision

full_name: Lean.Compiler.LCNF.FloatLetIn.FloatState.newArms
code: /--
The state for `FloatM`
-/
structure FloatState where
  /--
  A map from identifiers of declarations to their current decision.
  -/
  decision : HashMap FVarId Decision
  /--
  A map from decisions (excluding `unknown`) to the declarations with
  these decisions (in correct order). Basically:
  - Which declarations do we not move
  - Which declarations do we move into a certain arm
  - Which declarations do we move into the default arm
  -/
  newArms : HashMap Decision (List CodeDecl)
goal: Lean.HashMap Lean.Compiler.LCNF.FloatLetIn.Decision (List Lean.Compiler.LCNF.CodeDecl)

full_name: Lean.Compiler.LCNF.FloatLetIn.FloatState
code: /--
The state for `FloatM`
-/
structure FloatState where
  /--
  A map from identifiers of declarations to their current decision.
  -/
  decision : HashMap FVarId Decision
  /--
  A map from decisions (excluding `unknown`) to the declarations with
  these decisions (in correct order). Basically:
  - Which declarations do we not move
  - Which declarations do we move into a certain arm
  - Which declarations do we move into the default arm
  -/
  newArms : HashMap Decision (List CodeDecl)
goal: Type

full_name: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM
code: /--
Use to collect relevant declarations for the floating mechanism.
-/
abbrev BaseFloatM 
goal: Type

full_name: Lean.Compiler.LCNF.FloatLetIn.FloatM
code: /--
Use to compute the actual floating.
-/
abbrev FloatM 
goal: Type

full_name: Lean.Compiler.LCNF.FloatLetIn.withNewCandidate
code: /--
Add `decl` to the list of declarations and run `x` with that updated context.
-/
def withNewCandidate (decl : CodeDecl) (x : BaseFloatM α) : BaseFloatM α 
goal: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM α

full_name: Lean.Compiler.LCNF.FloatLetIn.withNewScope
code: /--
Run `x` with an empty list of declarations.
-/
def withNewScope (x : BaseFloatM α) : BaseFloatM α 
goal: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM α

full_name: Lean.Compiler.LCNF.FloatLetIn.ignore?
code: /--
Whether to ignore `decl` for the floating mechanism. We want to do this if:
- `decl`' is storing a typeclass instance
- `decl` is a projection from a variable that is storing a typeclass instance
-/
def ignore? (decl : LetDecl) : BaseFloatM Bool 
goal: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM Bool

full_name: Lean.Compiler.LCNF.FloatLetIn.initialDecisions.goAlt
code: /--
Compute the initial decision for all declarations that `BaseFloatM` collected
up to this point, with respect to `cs`. The initial decisions are:
- `dont` if the declaration is detected by `ignore?`
- `dont` if the declaration is the discriminant of `cs` since we obviously need
  the discriminant to be computed before the match.
- `dont` if we see the declaration being used in more than one cases arm
- `arm` or `default` if we see the declaration only being used in exactly one cases arm
- `unknown` otherwise
-/
def initialDecisions (cs : Cases) : BaseFloatM (HashMap FVarId Decision) 
goal: StateRefT' IO.RealWorld (Lean.HashMap Lean.FVarId Lean.Compiler.LCNF.FloatLetIn.Decision)
  Lean.Compiler.LCNF.FloatLetIn.BaseFloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.initialDecisions.goCases
code: /--
Compute the initial decision for all declarations that `BaseFloatM` collected
up to this point, with respect to `cs`. The initial decisions are:
- `dont` if the declaration is detected by `ignore?`
- `dont` if the declaration is the discriminant of `cs` since we obviously need
  the discriminant to be computed before the match.
- `dont` if we see the declaration being used in more than one cases arm
- `arm` or `default` if we see the declaration only being used in exactly one cases arm
- `unknown` otherwise
-/
def initialDecisions (cs : Cases) : BaseFloatM (HashMap FVarId Decision) 
goal: StateRefT' IO.RealWorld (Lean.HashMap Lean.FVarId Lean.Compiler.LCNF.FloatLetIn.Decision)
  Lean.Compiler.LCNF.FloatLetIn.BaseFloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.initialDecisions.goFVar
code: /--
Compute the initial decision for all declarations that `BaseFloatM` collected
up to this point, with respect to `cs`. The initial decisions are:
- `dont` if the declaration is detected by `ignore?`
- `dont` if the declaration is the discriminant of `cs` since we obviously need
  the discriminant to be computed before the match.
- `dont` if we see the declaration being used in more than one cases arm
- `arm` or `default` if we see the declaration only being used in exactly one cases arm
- `unknown` otherwise
-/
def initialDecisions (cs : Cases) : BaseFloatM (HashMap FVarId Decision) 
goal: StateRefT' IO.RealWorld (Lean.HashMap Lean.FVarId Lean.Compiler.LCNF.FloatLetIn.Decision)
  Lean.Compiler.LCNF.FloatLetIn.BaseFloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.initialDecisions
code: /--
Compute the initial decision for all declarations that `BaseFloatM` collected
up to this point, with respect to `cs`. The initial decisions are:
- `dont` if the declaration is detected by `ignore?`
- `dont` if the declaration is the discriminant of `cs` since we obviously need
  the discriminant to be computed before the match.
- `dont` if we see the declaration being used in more than one cases arm
- `arm` or `default` if we see the declaration only being used in exactly one cases arm
- `unknown` otherwise
-/
def initialDecisions (cs : Cases) : BaseFloatM (HashMap FVarId Decision) 
goal: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM (Lean.HashMap Lean.FVarId Lean.Compiler.LCNF.FloatLetIn.Decision)

full_name: Lean.Compiler.LCNF.FloatLetIn.initialNewArms
code: /--
Compute the initial new arms. This will just set up a map from all arms of
`cs` to empty `Array`s, plus one additional entry for `dont`.
-/
def initialNewArms (cs : Cases) : HashMap Decision (List CodeDecl) 
goal: Lean.HashMap Lean.Compiler.LCNF.FloatLetIn.Decision (List Lean.Compiler.LCNF.CodeDecl)

full_name: Lean.Compiler.LCNF.FloatLetIn.dontFloat
code: /--
Will:
- put `decl` into the `dont` arm
- decide that any free variable that occurs in `decl` and is a declaration
  of interest as not getting moved either.
```
let x := ...
let y := ...
let z := x + y
cases z with
| n => z * x
| m => z * y
```
Here `x` and `y` are originally marked as getting floated into `n` and `m`
respectively but since `z` can't be moved we don't want that to move `x` and `y`.
-/
def dontFloat (decl : CodeDecl) : FloatM Unit 
goal: Lean.Compiler.LCNF.FloatLetIn.FloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.dontFloat.goFVar
code: /--
Will:
- put `decl` into the `dont` arm
- decide that any free variable that occurs in `decl` and is a declaration
  of interest as not getting moved either.
```
let x := ...
let y := ...
let z := x + y
cases z with
| n => z * x
| m => z * y
```
Here `x` and `y` are originally marked as getting floated into `n` and `m`
respectively but since `z` can't be moved we don't want that to move `x` and `y`.
-/
def dontFloat (decl : CodeDecl) : FloatM Unit 
goal: Lean.Compiler.LCNF.FloatLetIn.FloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.float
code: /--
Will:
- put `decl` into the arm it is marked to be moved into
- for any variables that might occur in `decl` and are of interest:
  - if they are already meant to be floated into the same arm or not at all leave them untouched:
    ```
    let x := ...
    let y := x + z
    cases z with
    | n => x * y
    | m => z
    ```
    If we are at `y` `x` is already marked to be floated into `n` as well.
  - if there hasn't be a decision yet, that is they are marked with `.unknown` we float
    them into the same arm as the current value:
    ```
    let x := ..
    let y := x + 2
    cases z with
    | n => y
    | m => z
    ```
    Here `x` is initially marked as `.unknown` since it occurs in no branch, however
    since we want to move `y` into the `n` branch we can also decide to move `x`
    into the `n` branch. Note that this decision might be revoked later on in the case of:
    ```
    let x := ..
    let a := x + 1
    let y := x + 2
    cases z with
    | n => y
    | m => a
    ```
    When we visit `a` `x` is now marked as getting moved into `n` but since it also occurs
    in `a` which wants to be moved somewhere else we will instead decide to not move `x`
    at all.
  - if they are meant to be floated somewhere else decide that they won't get floated:
    ```
    let x := ...
    let y := x + z
    cases z with
    | n => y
    | m => x
    ```
    If we are at `y` `x` is still marked to be moved but we don't want that.
-/
def float (decl : CodeDecl) : FloatM Unit 
goal: Lean.Compiler.LCNF.FloatLetIn.FloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.float.goFVar
code: /--
Will:
- put `decl` into the arm it is marked to be moved into
- for any variables that might occur in `decl` and are of interest:
  - if they are already meant to be floated into the same arm or not at all leave them untouched:
    ```
    let x := ...
    let y := x + z
    cases z with
    | n => x * y
    | m => z
    ```
    If we are at `y` `x` is already marked to be floated into `n` as well.
  - if there hasn't be a decision yet, that is they are marked with `.unknown` we float
    them into the same arm as the current value:
    ```
    let x := ..
    let y := x + 2
    cases z with
    | n => y
    | m => z
    ```
    Here `x` is initially marked as `.unknown` since it occurs in no branch, however
    since we want to move `y` into the `n` branch we can also decide to move `x`
    into the `n` branch. Note that this decision might be revoked later on in the case of:
    ```
    let x := ..
    let a := x + 1
    let y := x + 2
    cases z with
    | n => y
    | m => a
    ```
    When we visit `a` `x` is now marked as getting moved into `n` but since it also occurs
    in `a` which wants to be moved somewhere else we will instead decide to not move `x`
    at all.
  - if they are meant to be floated somewhere else decide that they won't get floated:
    ```
    let x := ...
    let y := x + z
    cases z with
    | n => y
    | m => x
    ```
    If we are at `y` `x` is still marked to be moved but we don't want that.
-/
def float (decl : CodeDecl) : FloatM Unit 
goal: Lean.Compiler.LCNF.FloatLetIn.FloatM Unit

full_name: Lean.Compiler.LCNF.FloatLetIn.floatLetIn
code: /--
Iterate through `decl`, pushing local declarations that are only used in one
control flow arm into said arm in order to avoid useless computations.
-/
partial def floatLetIn (decl : Decl) : CompilerM Decl 
goal: Lean.Compiler.LCNF.CompilerM Lean.Compiler.LCNF.Decl

full_name: Lean.Compiler.LCNF.FloatLetIn.floatLetIn.go
code: /--
Iterate through `decl`, pushing local declarations that are only used in one
control flow arm into said arm in order to avoid useless computations.
-/
partial def floatLetIn (decl : Decl) : CompilerM Decl 
goal: Lean.Compiler.LCNF.FloatLetIn.BaseFloatM Lean.Compiler.LCNF.Code

full_name: Lean.Compiler.LCNF.FloatLetIn.floatLetIn.goCases
code: /--
Iterate through `decl`, pushing local declarations that are only used in one
control flow arm into said arm in order to avoid useless computations.
-/
partial def floatLetIn (decl : Decl) : CompilerM Decl 
goal: Lean.Compiler.LCNF.FloatLetIn.FloatM Unit

full_name: Lean.Compiler.LCNF.Decl.floatLetIn
code: def Decl.floatLetIn (decl : Decl) : CompilerM Decl 
goal: Lean.Compiler.LCNF.CompilerM Lean.Compiler.LCNF.Decl

full_name: Lean.Compiler.LCNF.floatLetIn
code: def floatLetIn (phase := Phase.base) (occurrence := 0) : Pass 
goal: Lean.Compiler.LCNF.Pass

full_name: Lean.Compiler.LCNF.initFn._@..lake.packages.lean4.src.lean.Lean.Compiler.LCNF.FloatLetIn._hyg.2270
code: builtin_initialize
  registerTraceClass `Compiler.floatLetIn (inherited := true)
goal: IO Unit