This PR removes code that has the false assumption that LCNF local vars can occur in types. There are other comments in `ElimDead.lean` asserting that this is not possible, so this must have been a change early in the development of the new compiler.
95 lines
2.8 KiB
Text
95 lines
2.8 KiB
Text
/-
|
|
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
prelude
|
|
import Lean.Compiler.LCNF.Simp.SimpM
|
|
|
|
namespace Lean.Compiler.LCNF
|
|
namespace Simp
|
|
|
|
/--
|
|
Mark `fvarId` as an used free variable.
|
|
This is information is used to eliminate dead local declarations.
|
|
-/
|
|
def markUsedFVar (fvarId : FVarId) : SimpM Unit :=
|
|
modify fun s => { s with used := s.used.insert fvarId }
|
|
|
|
/--
|
|
Mark all free variables occurring in `arg` as used.
|
|
-/
|
|
def markUsedArg (arg : Arg) : SimpM Unit :=
|
|
match arg with
|
|
| .fvar fvarId => markUsedFVar fvarId
|
|
-- Locally declared variables do not occur in types.
|
|
| .type _ | .erased => return ()
|
|
|
|
/--
|
|
Mark all free variables occurring in `e` as used.
|
|
-/
|
|
def markUsedLetValue (e : LetValue) : SimpM Unit := do
|
|
match e with
|
|
| .lit .. | .erased => return ()
|
|
| .proj _ _ fvarId => markUsedFVar fvarId
|
|
| .const _ _ args => args.forM markUsedArg
|
|
| .fvar fvarId args => markUsedFVar fvarId; args.forM markUsedArg
|
|
|
|
/--
|
|
Mark all free variables occurring on the right-hand side of the given let declaration as used.
|
|
This is information is used to eliminate dead local declarations.
|
|
-/
|
|
def markUsedLetDecl (letDecl : LetDecl) : SimpM Unit :=
|
|
markUsedLetValue letDecl.value
|
|
|
|
mutual
|
|
/--
|
|
Mark all free variables occurring in `code` as used.
|
|
-/
|
|
partial def markUsedCode (code : Code) : SimpM Unit := do
|
|
match code with
|
|
| .let decl k => markUsedLetDecl decl; markUsedCode k
|
|
| .jp decl k | .fun decl k => markUsedFunDecl decl; markUsedCode k
|
|
| .return fvarId => markUsedFVar fvarId
|
|
| .unreach .. => return ()
|
|
| .jmp fvarId args => markUsedFVar fvarId; args.forM markUsedArg
|
|
| .cases c => markUsedFVar c.discr; c.alts.forM fun alt => markUsedCode alt.getCode
|
|
|
|
/--
|
|
Mark all free variables occurring in `funDecl` as used.
|
|
-/
|
|
partial def markUsedFunDecl (funDecl : FunDecl) : SimpM Unit :=
|
|
markUsedCode funDecl.value
|
|
end
|
|
|
|
/--
|
|
Return `true` if `fvarId` is in the `used` set.
|
|
-/
|
|
def isUsed (fvarId : FVarId) : SimpM Bool :=
|
|
return (← get).used.contains fvarId
|
|
|
|
/--
|
|
Attach the given `decls` to `code`. For example, assume `decls` is `#[.let _x.1 := 10, .let _x.2 := true]`,
|
|
then the result is
|
|
```
|
|
let _x.1 := 10
|
|
let _x.2 := true
|
|
<code>
|
|
```
|
|
-/
|
|
def attachCodeDecls (decls : Array CodeDecl) (code : Code) : SimpM Code := do
|
|
go decls.size code
|
|
where
|
|
go (i : Nat) (code : Code) : SimpM Code := do
|
|
if i > 0 then
|
|
let decl := decls[i-1]!
|
|
if (← isUsed decl.fvarId) then
|
|
match decl with
|
|
| .let decl => markUsedLetDecl decl; go (i-1) (.let decl code)
|
|
| .fun decl => markUsedFunDecl decl; go (i-1) (.fun decl code)
|
|
| .jp decl => markUsedFunDecl decl; go (i-1) (.jp decl code)
|
|
else
|
|
eraseCodeDecl decl
|
|
go (i-1) code
|
|
else
|
|
return code
|