lean4-htt/tests/elab/floatLetIn.lean
Garmelon 08eb78a5b2
chore: switch to new test/bench suite (#12590)
This PR sets up the new integrated test/bench suite. It then migrates
all benchmarks and some related tests to the new suite. There's also
some documentation and some linting.

For now, a lot of the old tests are left alone so this PR doesn't become
even larger than it already is. Eventually, all tests should be migrated
to the new suite though so there isn't a confusing mix of two systems.
2026-02-25 13:51:53 +00:00

148 lines
3.2 KiB
Text

/-!
# Tests for the `floatLetIn` compiler pass
-/
structure State where
abc : Nat
xyz : Array Nat
bool : Bool
deriving Inhabited
def State.size (t : State) : Nat := t.xyz.size
@[extern]
opaque State.restore (abc : Nat) (size : Nat) (s : State) : State
def StateFn := State → State
set_option trace.Compiler.saveMono true
/-!
The `floatLetIn` pass moves values (here `st.size`) into one branch if they are only used in that
branch.
-/
/--
trace: [Compiler.saveMono] size: 7
def test1 st : State :=
cases st : State
| State.mk abc xyz bool =>
cases bool : State
| Bool.false =>
return st
| Bool.true =>
let b := State.size st;
let _x.1 := State.restore abc b st;
return _x.1
-/
#guard_msgs in
def test1 : StateFn := fun st =>
let a := st.abc
let b := st.size
if st.bool then
st.restore a b
else
st
/-!
This doesn't occur if it would destroy linearity.
-/
/--
trace: [Compiler.saveMono] size: 10
def test2 fn st : State :=
cases st : State
| State.mk abc xyz bool =>
let b := State.size st;
let st := fn st;
cases st : State
| State.mk abc xyz bool =>
cases bool : State
| Bool.false =>
return st
| Bool.true =>
let _x.1 := State.restore abc b st;
return _x.1
-/
#guard_msgs in
def test2 (fn : StateFn) : StateFn := fun st =>
let a := st.abc
let b := st.size
let st := fn st
if st.bool then
st.restore a b
else
st
/-!
Passing a value to a function as a borrowed parameter doesn't count as a linear pass and thus values
can be happily passed through it.
-/
/--
trace: [Compiler.saveMono] size: 0
def State.remake @&s : State :=
extern
-/
#guard_msgs in
@[extern]
opaque State.remake (s : @& State) : State
/--
trace: [Compiler.saveMono] size: 10
def test3 st : State :=
let st := State.remake st;
cases st : State
| State.mk abc xyz bool =>
cases bool : State
| Bool.false =>
return st
| Bool.true =>
cases st : State
| State.mk abc xyz bool =>
let b := State.size st;
let _x.1 := State.restore abc b st;
return _x.1
-/
#guard_msgs in
def test3 : StateFn := fun st =>
let a := st.abc
let b := st.size
let st := State.remake st
if st.bool then
st.restore a b
else
st
/-!
This also doesn't occur if there are indirect uses of a variable in both branches.
-/
/--
trace: [Compiler.saveMono] size: 13
def test4 st : State :=
cases st : State
| State.mk abc xyz bool =>
let b := State.size st;
let _x.1 := 1;
let c := Nat.add b _x.1;
cases bool : State
| Bool.false =>
let _x.2 := Nat.add abc _x.1;
let _x.3 := 2;
let _x.4 := Nat.add c _x.3;
let _x.5 := State.restore _x.2 _x.4 st;
return _x.5
| Bool.true =>
let _x.6 := State.restore abc c st;
return _x.6
-/
#guard_msgs in
def test4 : StateFn := fun st =>
let a := st.abc
let b := st.size
let c := b + 1
if st.bool then
st.restore a c
else
st.restore (a + 1) (c + 2)