lean4-htt/tests/lean/run/simpCacheTest.lean
Joachim Breitner 2441bf1f76
perf: check simp cache in simpLoop (#8880)
This PR makes `simp` consult its own cache more often, to avoid
replicating work.

Before, the simp cache was checked upon entry of `simpImpl` only, which
then calls `simpLoop`, which recursively iterates the `pre`-lemmas,
without checking the cache again.

Now, `simpLoop` itself checks the cache. This seems more principled,
given that `simpLoop` is actually putting entries into the cache for
each of its calls, so it’s more uniform if it checks the cache itself.

This avoids repeated rewrites. For example given
```
theorem ab : a = b := testSorry
theorem bc : b = c := testSorry
example (h : P c) : P b ∧ P a := by simp [ab, bc, h]
```
simp would rewrite `b ==> c` twice (once as part of `b ==> c` and then
again as part of `a ==> b ==> c`). And it’d be order dependent: With
```
example (h : P c) : P a ∧ P b := by simp [ab, bc, h]
```
the `a ==> b ==> c` chain would insert `b ==> c` into the cache, and
picked up by `simpImpl` when rewriting `P b`.

With this change, `b ==> c` is performed only once in both examples.

Instruction counts on stdlib and mathlib both show a mild improvement
across the board (0.5%), with individual modules improving by up to 4%
in stdlib and even more in mathlib.


(This does not check the cache before applying `post`, which explains
where there are still some repeated rewrites in the trace logs. But I’m
less sure about inserting a cache check here and so I am treading
carefully here. It’s also going to be at most one `post` application
that’s duplicated, because if `post` returns `.visit`, we go back to
`pre` and thus a cache check.)
2025-06-21 17:58:05 +00:00

72 lines
1.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-!
Checks that the simp cache is consulted within `simpLoop`, not just in `simpMain`
-/
axiom testSorry : α
opaque a : Nat
opaque b : Nat
opaque c : Nat
opaque f : Nat → Nat
opaque P : Nat → Prop
theorem ab : a = b := testSorry
theorem bc : b = c := testSorry
theorem ba : b = a := testSorry
theorem fafb : f a = f b := testSorry
set_option trace.Meta.Tactic.simp.rewrite true
-- This trace should only mention one `bc` rewrite, not two.
/--
trace: [Meta.Tactic.simp.rewrite] bc:1000:
b
==>
c
[Meta.Tactic.simp.rewrite] h:1000:
P c
==>
True
[Meta.Tactic.simp.rewrite] ab:1000:
a
==>
b
[Meta.Tactic.simp.rewrite] h:1000:
P c
==>
True
[Meta.Tactic.simp.rewrite] and_self:1000:
True ∧ True
==>
True
-/
#guard_msgs in
example (h : P c) : P b ∧ P a := by simp [ab, bc, h]
-- Almost the same goal, but ordered differently.
/--
trace: [Meta.Tactic.simp.rewrite] ab:1000:
a
==>
b
[Meta.Tactic.simp.rewrite] bc:1000:
b
==>
c
[Meta.Tactic.simp.rewrite] h:1000:
P c
==>
True
[Meta.Tactic.simp.rewrite] h:1000:
P c
==>
True
[Meta.Tactic.simp.rewrite] and_self:1000:
True ∧ True
==>
True
-/
#guard_msgs in
example (h : P c) : P a ∧ P b := by simp [ab, bc, h]