Skip to content

perf: make isRfl lazy #7719

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/Lean/Meta/Tactic/Simp/Rewrite.lean
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ where
return false

private def useImplicitDefEqProof (thm : SimpTheorem) : SimpM Bool := do
if thm.rfl then
return (← getConfig).implicitDefEqProofs
if (← getConfig).implicitDefEqProofs then
thm.getRfl
else
return false

Expand Down Expand Up @@ -218,7 +218,7 @@ where
else
let candidates := candidates.insertionSort fun e₁ e₂ => e₁.1.priority > e₂.1.priority
for (thm, numExtraArgs) in candidates do
unless inErasedSet thm || (rflOnly && !thm.rfl) do
unless inErasedSet thm || (rflOnly && !(← thm.getRfl)) do
if let some result ← tryTheoremWithExtraArgs? e thm numExtraArgs then
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
return some result
Expand All @@ -236,7 +236,7 @@ where
else
let candidates := candidates.insertionSort fun e₁ e₂ => e₁.priority > e₂.priority
for thm in candidates do
unless inErasedSet thm || (rflOnly && !thm.rfl) do
unless inErasedSet thm || (rflOnly && !(← thm.getRfl)) do
let result? ← withNewMCtxDepth do
let val ← thm.getValue
let type ← inferType val
Expand Down Expand Up @@ -352,7 +352,7 @@ def simpMatchDiscrs? (info : MatcherInfo) (e : Expr) : SimpM (Option Result) :=
def simpMatchCore (matcherName : Name) (e : Expr) : SimpM Step := do
for matchEq in (← Match.getEquationsFor matcherName).eqnNames do
-- Try lemma
match (← withReducible <| Simp.tryTheorem? e { origin := .decl matchEq, proof := mkConst matchEq, rfl := (← isRflTheorem matchEq) }) with
match (← withReducible <| Simp.tryTheorem? e { origin := .decl matchEq, proof := mkConst matchEq, rflTask := (← isRflTheorem matchEq) }) with
| none => pure ()
| some r => return .visit r
return .continue
Expand Down Expand Up @@ -433,7 +433,7 @@ def sevalGround : Simproc := fun e => do
-- `declName` has equation theorems associated with it.
for eqn in eqns do
-- TODO: cache SimpTheorem to avoid calls to `isRflTheorem`
if let some result ← Simp.tryTheorem? e { origin := .decl eqn, proof := mkConst eqn, rfl := (← isRflTheorem eqn) } then
if let some result ← Simp.tryTheorem? e { origin := .decl eqn, proof := mkConst eqn, rflTask := (← isRflTheorem eqn) } then
trace[Meta.Tactic.simp.ground] "unfolded, {e} => {result.expr}"
return .visit result
return .continue
Expand Down
49 changes: 30 additions & 19 deletions src/Lean/Meta/Tactic/Simp/SimpTheorems.lean
Original file line number Diff line number Diff line change
Expand Up @@ -122,45 +122,56 @@ structure SimpTheorem where
It is also viewed an `id` used to "erase" `simp` theorems from `SimpTheorems`.
-/
origin : Origin
/-- `rfl` is true if `proof` is by `Eq.refl` or `rfl`. -/
rfl : Bool
/-- True if `proof` is by `Eq.refl` or `rfl`. Lazy so `[simp]` doesn't block the main thread. -/
rflTask : Task Bool
deriving Inhabited

def SimpTheorem.getRfl (t : SimpTheorem) : CoreM Bool :=
traceBlock "SimpTheorem.getRfl" t.rflTask

mutual
partial def isRflProofCore (type : Expr) (proof : Expr) : CoreM Bool := do
partial def isRflProofCore (env : Environment) (type : Expr) (proof : Expr) : Task Bool :=
match type with
| .forallE _ _ type _ =>
if let .lam _ _ proof _ := proof then
isRflProofCore type proof
isRflProofCore env type proof
else
return false
.pure false
| _ =>
if type.isAppOfArity ``Eq 3 then
if proof.isAppOfArity ``Eq.refl 2 || proof.isAppOfArity ``rfl 2 then
return true
.pure true
else if proof.isAppOfArity ``Eq.symm 4 then
-- `Eq.symm` of rfl theorem is a rfl theorem
isRflProofCore type proof.appArg! -- small hack: we don't need to set the exact type
isRflProofCore env type proof.appArg! -- small hack: we don't need to set the exact type
else if proof.getAppFn.isConst then
-- The application of a `rfl` theorem is a `rfl` theorem
-- A constant which is a `rfl` theorem is a `rfl` theorem
isRflTheorem proof.getAppFn.constName!
isRflTheoremCore env proof.getAppFn.constName!
else
return false
.pure false
else
return false

partial def isRflTheorem (declName : Name) : CoreM Bool := do
let { kind := .thm, constInfo, .. } ← getAsyncConstInfo declName | return false
let .thmInfo info ← traceBlock "isRflTheorem theorem body" constInfo | return false
isRflProofCore info.type info.value
.pure false

partial def isRflTheoremCore (env : Environment) (declName : Name) : Task Bool := Id.run do
env.findTask declName |>.bind (sync := true) fun
| none => .pure false
| some aconst => aconst.constInfo.bind (sync := true) fun
| .thmInfo info => isRflProofCore env info.type info.value
| _ => .pure false
end

def isRflProof (proof : Expr) : MetaM Bool := do
def isRflProof (proof : Expr) : MetaM (Task Bool) := do
let env ← getEnv
if let .const declName .. := proof then
isRflTheorem declName
return isRflTheoremCore env declName
else
isRflProofCore (← inferType proof) proof
let type ← inferType proof
return isRflProofCore env type proof

def isRflTheorem (declName : Name) : MetaM (Task Bool) := do
let env ← getEnv
return isRflTheoremCore env declName

instance : ToFormat SimpTheorem where
format s :=
Expand Down Expand Up @@ -401,7 +412,7 @@ private def mkSimpTheoremCore (origin : Origin) (e : Expr) (levelParams : Array
match type.eq? with
| some (_, lhs, rhs) => pure (← DiscrTree.mkPath lhs noIndexAtArgs, ← isPerm lhs rhs)
| none => throwError "unexpected kind of 'simp' theorem{indentExpr type}"
return { origin, keys, perm, post, levelParams, proof, priority := prio, rfl := (← isRflProof proof) }
return { origin, keys, perm, post, levelParams, proof, priority := prio, rflTask := (← isRflProof proof) }

private def mkSimpTheoremsFromConst (declName : Name) (post : Bool) (inv : Bool) (prio : Nat) : MetaM (Array SimpTheorem) := do
let cinfo ← getConstVal declName
Expand Down
2 changes: 1 addition & 1 deletion src/Lean/Meta/Tactic/Split.lean
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ where
let simpTheorem := {
origin := .decl matchEqDeclName
proof := mkConst matchEqDeclName
rfl := (← isRflTheorem matchEqDeclName)
rflTask := (← isRflTheorem matchEqDeclName)
}
match (← withReducible <| Simp.tryTheorem? e simpTheorem) with
| none => return .continue
Expand Down
2 changes: 1 addition & 1 deletion src/Lean/Meta/Tactic/Unfold.lean
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def unfold (e : Expr) (declName : Name) : MetaM Simp.Result := do
return { expr := (← deltaExpand e (· == declName)) }
where
pre (unfoldThm : Name) (e : Expr) : SimpM Simp.Step := do
match (← withReducible <| Simp.tryTheorem? e { origin := .decl unfoldThm, proof := mkConst unfoldThm, rfl := (← isRflTheorem unfoldThm) }) with
match (← withReducible <| Simp.tryTheorem? e { origin := .decl unfoldThm, proof := mkConst unfoldThm, rflTask := (← isRflTheorem unfoldThm) }) with
| none => pure ()
| some r => match (← reduceMatcher? r.expr) with
| .reduced e' => return .done { r with expr := e' }
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,9 @@ static inline void lean_set_task_header(lean_object * o) {
o->m_rc = -1;
o->m_tag = LeanTask;
o->m_other = 0;
#ifndef LEAN_MIMALLOC
o->m_cs_sz = 0;
#endif
}

static lean_task_object * alloc_task(obj_arg c, unsigned prio, bool keep_alive) {
Expand Down
16 changes: 15 additions & 1 deletion stage0/src/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions stage0/src/config.h.in

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 34 additions & 3 deletions stage0/src/include/lean/lean.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions stage0/src/runtime/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions stage0/src/runtime/mpz.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading