feat: LCNF.simp .let case

This commit is contained in:
Leonardo de Moura 2022-08-29 09:50:42 -07:00
parent 7b161d33d1
commit ca80bc52dc
3 changed files with 33 additions and 8 deletions

View file

@ -16,7 +16,6 @@ structure State where
map : Std.PHashMap Expr FVarId := {}
subst : FVarSubst := {}
abbrev M := StateRefT State CompilerM
instance : MonadFVarSubst M where
@ -29,16 +28,13 @@ instance : MonadFVarSubst M where
@[inline] def addEntry (value : Expr) (fvarId : FVarId) : M Unit :=
modify fun s => { s with map := s.map.insert value fvarId }
@[inline] def addSubst (fvarId fvarId' : FVarId) : M Unit :=
modify fun s => { s with subst := s.subst.insert fvarId (.fvar fvarId') }
@[inline] def withNewScope (x : M α) : M α := do
let map := (← get).map
try x finally modify fun s => { s with map }
def replaceFVar (fvarId fvarId' : FVarId) : M Unit := do
eraseFVar fvarId
addSubst fvarId fvarId'
addFVarSubst fvarId fvarId'
end CSE

View file

@ -46,7 +46,7 @@ partial def elimDead (code : Code) : M Code := do
match code with
| .let decl k =>
let k ← elimDead k
if (← get).contains decl.fvarId then
if !decl.pure || (← get).contains decl.fvarId then
/- Remark: we don't need to collect `decl.type` because LCNF local declarations do not occur in types. -/
collectExprM decl.value
return code.updateCont! k

View file

@ -199,18 +199,47 @@ def incVisited : SimpM Unit :=
def markUsedFVar (fvarId : FVarId) : SimpM Unit :=
modify fun s => { s with used := s.used.insert fvarId }
def markUsedExpr (e : Expr) : SimpM Unit :=
modify fun s => { s with used := collectLocalDecls s.used e }
def markUsedLetDecl (letDecl : LetDecl) : SimpM Unit :=
markUsedExpr letDecl.value
def isUsed (fvarId : FVarId) : SimpM Bool :=
return (← get).used.contains fvarId
def eraseLetDecl (decl : LetDecl) : SimpM Unit := do
eraseFVar decl.fvarId
markSimplified
mutual
partial def simp (code : Code) : SimpM Code := do
-- TODO
incVisited
match code with
| .let decl k =>
let decl ← normLetDecl decl
if decl.value.isFVar then
/- Eliminate `let _x_i := _x_j;` -/
addSubst decl.fvarId decl.value
eraseLetDecl decl
simp k
else
/- TODO: simple value simplifications & inlining -/
let k ← simp k
if !decl.pure || (← isUsed decl.fvarId) then
markUsedLetDecl decl
return code.updateLet! decl k
else
/- Dead variable elimination -/
eraseLetDecl decl
return k
| .return fvarId =>
let fvarId ← normFVar fvarId
markUsedFVar fvarId
return code.updateReturn! fvarId
| .unreach .. => return code
| _ => return code
| _ => return code -- TODO: implement other cases
end