Skip to content

Commit b21cef3

Browse files
authored
perf: sort before elim dead branches (#11366)
This PR sorts the declarations fed into ElimDeadBranches in increasing size. This can improve performance when we are dealing with a lot of iterations. The motivation for this change is as follows. Currently the algorithm for doing one step of abstract interpretation is: ``` for decl in scc do interpDecl if summaryChanged decl then return true return false ``` whenever we return true we run another step. Now suppose we are in a situation where we have an SCC with one big decl in the front and then `n` small ones afterwards. For each time that the small ones change their summary, we will re-run analysis of the big one in the front. Currently the ordering is basically at "random" based on how other compilers inject things into the SCC. This change ensures the behavior is consistent and at least somewhat intelligent. By putting the small declarations first, whenever we trigger a rerun of the loop we bias analyzing the small declarations first, thus decreasing run time. Note that this change does not have much effect on the current pipeline because: We usually construct the SCCs in a way such that small ones happen to be in front anyways. However, with upcomping changes on specialization this is about to change.
1 parent 9a5a9c2 commit b21cef3

File tree

6 files changed

+126
-116
lines changed

6 files changed

+126
-116
lines changed

src/Lean/Compiler/LCNF/ElimDeadBranches.lean

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,9 @@ def inferStep : InterpM Bool := do
581581
withReader (fun ctx => { ctx with currFnIdx := idx }) do
582582
decl.params.forM fun p => updateVarAssignment p.fvarId .top
583583
match decl.value with
584-
| .code code .. => interpCode code
584+
| .code code .. =>
585+
withTraceNode `Compiler.elimDeadBranches (fun _ => return m!"Analyzing {decl.name}") do
586+
interpCode code
585587
| .extern .. => updateCurrFnSummary .top
586588
let newVal ← getFunVal idx
587589
if currentVal != newVal then
@@ -591,13 +593,14 @@ def inferStep : InterpM Bool := do
591593
/--
592594
Run `inferStep` until it reaches a fix point.
593595
-/
594-
partial def inferMain : InterpM Unit := do
596+
partial def inferMain (n : Nat := 0) : InterpM Unit := do
595597
let ctx ← read
596598
modify fun s => { s with assignments := ctx.decls.map fun _ => {} }
597599
let modified ← inferStep
598600
if modified then
599-
inferMain
601+
inferMain (n + 1)
600602
else
603+
trace[Compiler.elimDeadBranches] m!"Termination after {n} steps"
601604
return ()
602605

603606
/--
@@ -647,6 +650,11 @@ end UnreachableBranches
647650

648651
open UnreachableBranches in
649652
def Decl.elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do
653+
/-
654+
We sort declarations by size here to ensure that when we restart in inferStep it will mostly be
655+
small declarations that get re-analyzed.
656+
-/
657+
let decls := decls.qsort (fun l r => (l.size, l.name.toString).lexLt (r.size, r.name.toString))
650658
let mut assignments := decls.map fun _ => {}
651659
let initialVal i :=
652660
/-
@@ -659,7 +667,9 @@ def Decl.elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do
659667
let mut funVals := decls.size.fold (init := .empty) fun i _ p => p.push (initialVal i)
660668
let ctx := { decls }
661669
let mut state := { assignments, funVals }
662-
(_, state) ← inferMain |>.run ctx |>.run state
670+
(_, state) ←
671+
withTraceNode `Compiler.elimDeadBranches (fun _ => return m!"Analyzing block: {decls.map (·.name)}")
672+
inferMain |>.run ctx |>.run state
663673
funVals := state.funVals
664674
assignments := state.assignments
665675
modifyEnv fun e =>

tests/lean/4089.lean.expected.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
let x_4 : obj := reuse x_5 in ctor_0[Prod.mk] x_3 x_2;
99
ret x_4
1010
[Compiler.IR] [reset_reuse]
11+
def Sigma.toProd (x_1 : ◾) (x_2 : ◾) (x_3 : obj) : obj :=
12+
let x_4 : obj := Sigma.toProd._redArg x_3;
13+
ret x_4
1114
def Sigma.toProd._redArg (x_1 : obj) : obj :=
1215
case x_1 : obj of
1316
Sigma.mk →
@@ -16,9 +19,6 @@
1619
let x_5 : tobj := reset[2] x_1;
1720
let x_4 : obj := reuse x_5 in ctor_0[Prod.mk] x_2 x_3;
1821
ret x_4
19-
def Sigma.toProd (x_1 : ◾) (x_2 : ◾) (x_3 : obj) : obj :=
20-
let x_4 : obj := Sigma.toProd._redArg x_3;
21-
ret x_4
2222
[Compiler.IR] [reset_reuse]
2323
def foo (x_1 : tobj) : tobj :=
2424
case x_1 : tobj of

tests/lean/4240.lean.expected.out

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
[Compiler.IR] [result]
2+
def isSomeWithInstanceNat (x_1 : @& obj) : u8 :=
3+
let x_2 : usize := 0;
4+
let x_3 : tobj := Array.uget ◾ x_1 x_2 ◾;
5+
let x_4 : u8 := MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0 x_3;
6+
dec x_3;
7+
ret x_4
28
def MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0 (x_1 : @& tobj) : u8 :=
39
case x_1 : tobj of
410
MyOption.none →
@@ -7,19 +13,13 @@
713
MyOption.some →
814
let x_3 : u8 := 1;
915
ret x_3
10-
def isSomeWithInstanceNat (x_1 : @& obj) : u8 :=
11-
let x_2 : usize := 0;
12-
let x_3 : tobj := Array.uget ◾ x_1 x_2 ◾;
13-
let x_4 : u8 := MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0 x_3;
14-
dec x_3;
15-
ret x_4
16-
def MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0._boxed (x_1 : tobj) : tagged :=
17-
let x_2 : u8 := MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0 x_1;
16+
def isSomeWithInstanceNat._boxed (x_1 : obj) : tagged :=
17+
let x_2 : u8 := isSomeWithInstanceNat x_1;
1818
dec x_1;
1919
let x_3 : tobj := box x_2;
2020
ret x_3
21-
def isSomeWithInstanceNat._boxed (x_1 : obj) : tagged :=
22-
let x_2 : u8 := isSomeWithInstanceNat x_1;
21+
def MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0._boxed (x_1 : tobj) : tagged :=
22+
let x_2 : u8 := MyOption.isSomeWithInstance._at_.isSomeWithInstanceNat.spec_0 x_1;
2323
dec x_1;
2424
let x_3 : tobj := box x_2;
2525
ret x_3

tests/lean/computedFieldsCode.lean.expected.out

Lines changed: 84 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
dec x_1;
2828
ret x_2
2929
[Compiler.IR] [result]
30+
def Exp.ctorElim (x_1 : ◾) (x_2 : @& tobj) (x_3 : tobj) (x_4 : ◾) (x_5 : tobj) : tobj :=
31+
let x_6 : tobj := Exp.ctorElim._redArg x_3 x_5;
32+
ret x_6
3033
def Exp.ctorElim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
3134
case x_1 : tobj of
3235
Exp.var →
@@ -46,106 +49,60 @@
4649
default →
4750
dec x_1;
4851
ret x_2
49-
def Exp.ctorElim (x_1 : ◾) (x_2 : @& tobj) (x_3 : tobj) (x_4 : ◾) (x_5 : tobj) : tobj :=
50-
let x_6 : tobj := Exp.ctorElim._redArg x_3 x_5;
51-
ret x_6
5252
def Exp.ctorElim._boxed (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : tobj) (x_5 : tobj) : tobj :=
5353
let x_6 : tobj := Exp.ctorElim x_1 x_2 x_3 x_4 x_5;
5454
dec x_2;
5555
ret x_6
5656
[Compiler.IR] [result]
57-
def Exp.var.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
58-
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
59-
ret x_3
6057
def Exp.var.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
6158
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
6259
ret x_5
63-
[Compiler.IR] [result]
64-
def Exp.app.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
60+
def Exp.var.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
6561
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
6662
ret x_3
63+
[Compiler.IR] [result]
6764
def Exp.app.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
6865
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
6966
ret x_5
70-
[Compiler.IR] [result]
71-
def Exp.a1.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
67+
def Exp.app.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
7268
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
7369
ret x_3
70+
[Compiler.IR] [result]
7471
def Exp.a1.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
7572
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
7673
ret x_5
77-
[Compiler.IR] [result]
78-
def Exp.a2.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
74+
def Exp.a1.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
7975
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
8076
ret x_3
77+
[Compiler.IR] [result]
8178
def Exp.a2.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
8279
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
8380
ret x_5
84-
[Compiler.IR] [result]
85-
def Exp.a3.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
81+
def Exp.a2.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
8682
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
8783
ret x_3
84+
[Compiler.IR] [result]
8885
def Exp.a3.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
8986
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
9087
ret x_5
91-
[Compiler.IR] [result]
92-
def Exp.a4.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
88+
def Exp.a3.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
9389
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
9490
ret x_3
91+
[Compiler.IR] [result]
9592
def Exp.a4.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
9693
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
9794
ret x_5
98-
[Compiler.IR] [result]
99-
def Exp.a5.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
95+
def Exp.a4.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
10096
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
10197
ret x_3
98+
[Compiler.IR] [result]
10299
def Exp.a5.elim (x_1 : ◾) (x_2 : tobj) (x_3 : ◾) (x_4 : tobj) : tobj :=
103100
let x_5 : tobj := Exp.ctorElim._redArg x_2 x_4;
104101
ret x_5
102+
def Exp.a5.elim._redArg (x_1 : tobj) (x_2 : tobj) : tobj :=
103+
let x_3 : tobj := Exp.ctorElim._redArg x_1 x_2;
104+
ret x_3
105105
[Compiler.IR] [result]
106-
def Exp.casesOn._override._redArg (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : @& tobj) (x_5 : @& tobj) (x_6 : @& tobj) (x_7 : @& tobj) (x_8 : @& tobj) : tobj :=
107-
case x_1 : tobj of
108-
Exp.var._impl →
109-
dec x_3;
110-
let x_9 : u32 := sproj[0, 8] x_1;
111-
dec x_1;
112-
let x_10 : tobj := box x_9;
113-
let x_11 : tobj := app x_2 x_10;
114-
ret x_11
115-
Exp.app._impl →
116-
dec x_2;
117-
let x_12 : tobj := proj[0] x_1;
118-
inc x_12;
119-
let x_13 : tobj := proj[1] x_1;
120-
inc x_13;
121-
dec x_1;
122-
let x_14 : tobj := app x_3 x_12 x_13;
123-
ret x_14
124-
Exp.a1._impl →
125-
dec x_3;
126-
dec x_2;
127-
inc x_4;
128-
ret x_4
129-
Exp.a2._impl →
130-
dec x_3;
131-
dec x_2;
132-
inc x_5;
133-
ret x_5
134-
Exp.a3._impl →
135-
dec x_3;
136-
dec x_2;
137-
inc x_6;
138-
ret x_6
139-
Exp.a4._impl →
140-
dec x_3;
141-
dec x_2;
142-
inc x_7;
143-
ret x_7
144-
Exp.a5._impl →
145-
dec x_3;
146-
dec x_2;
147-
inc x_8;
148-
ret x_8
149106
def Exp.casesOn._override (x_1 : ◾) (x_2 : tobj) (x_3 : tobj) (x_4 : tobj) (x_5 : @& tobj) (x_6 : @& tobj) (x_7 : @& tobj) (x_8 : @& tobj) (x_9 : @& tobj) : tobj :=
150107
case x_2 : tobj of
151108
Exp.var._impl →
@@ -189,14 +146,49 @@
189146
dec x_3;
190147
inc x_9;
191148
ret x_9
192-
def Exp.casesOn._override._redArg._boxed (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : tobj) (x_5 : tobj) (x_6 : tobj) (x_7 : tobj) (x_8 : tobj) : tobj :=
193-
let x_9 : tobj := Exp.casesOn._override._redArg x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8;
194-
dec x_8;
195-
dec x_7;
196-
dec x_6;
197-
dec x_5;
198-
dec x_4;
199-
ret x_9
149+
def Exp.casesOn._override._redArg (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : @& tobj) (x_5 : @& tobj) (x_6 : @& tobj) (x_7 : @& tobj) (x_8 : @& tobj) : tobj :=
150+
case x_1 : tobj of
151+
Exp.var._impl →
152+
dec x_3;
153+
let x_9 : u32 := sproj[0, 8] x_1;
154+
dec x_1;
155+
let x_10 : tobj := box x_9;
156+
let x_11 : tobj := app x_2 x_10;
157+
ret x_11
158+
Exp.app._impl →
159+
dec x_2;
160+
let x_12 : tobj := proj[0] x_1;
161+
inc x_12;
162+
let x_13 : tobj := proj[1] x_1;
163+
inc x_13;
164+
dec x_1;
165+
let x_14 : tobj := app x_3 x_12 x_13;
166+
ret x_14
167+
Exp.a1._impl →
168+
dec x_3;
169+
dec x_2;
170+
inc x_4;
171+
ret x_4
172+
Exp.a2._impl →
173+
dec x_3;
174+
dec x_2;
175+
inc x_5;
176+
ret x_5
177+
Exp.a3._impl →
178+
dec x_3;
179+
dec x_2;
180+
inc x_6;
181+
ret x_6
182+
Exp.a4._impl →
183+
dec x_3;
184+
dec x_2;
185+
inc x_7;
186+
ret x_7
187+
Exp.a5._impl →
188+
dec x_3;
189+
dec x_2;
190+
inc x_8;
191+
ret x_8
200192
def Exp.casesOn._override._boxed (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : tobj) (x_5 : tobj) (x_6 : tobj) (x_7 : tobj) (x_8 : tobj) (x_9 : tobj) : tobj :=
201193
let x_10 : tobj := Exp.casesOn._override x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9;
202194
dec x_9;
@@ -205,22 +197,15 @@
205197
dec x_6;
206198
dec x_5;
207199
ret x_10
200+
def Exp.casesOn._override._redArg._boxed (x_1 : tobj) (x_2 : tobj) (x_3 : tobj) (x_4 : tobj) (x_5 : tobj) (x_6 : tobj) (x_7 : tobj) (x_8 : tobj) : tobj :=
201+
let x_9 : tobj := Exp.casesOn._override._redArg x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8;
202+
dec x_8;
203+
dec x_7;
204+
dec x_6;
205+
dec x_5;
206+
dec x_4;
207+
ret x_9
208208
[Compiler.IR] [result]
209-
def Exp.var._override (x_1 : u32) : tobj :=
210-
let x_2 : u64 := UInt32.toUInt64 x_1;
211-
let x_3 : u64 := 1000;
212-
let x_4 : u64 := UInt64.add x_2 x_3;
213-
let x_5 : obj := ctor_0.0.12[Exp.var._impl];
214-
sset x_5[0, 0] : u64 := x_4;
215-
sset x_5[0, 8] : u32 := x_1;
216-
ret x_5
217-
def Exp.app._override (x_1 : tobj) (x_2 : tobj) : tobj :=
218-
let x_3 : u64 := Exp.hash._override x_1;
219-
let x_4 : u64 := Exp.hash._override x_2;
220-
let x_5 : u64 := mixHash x_3 x_4;
221-
let x_6 : obj := ctor_1.0.8[Exp.app._impl] x_1 x_2;
222-
sset x_6[2, 0] : u64 := x_5;
223-
ret x_6
224209
def Exp.a1._override : tobj :=
225210
let x_1 : tagged := ctor_2[Exp.a1._impl];
226211
ret x_1
@@ -236,6 +221,21 @@
236221
def Exp.a5._override : tobj :=
237222
let x_1 : tagged := ctor_6[Exp.a5._impl];
238223
ret x_1
224+
def Exp.app._override (x_1 : tobj) (x_2 : tobj) : tobj :=
225+
let x_3 : u64 := Exp.hash._override x_1;
226+
let x_4 : u64 := Exp.hash._override x_2;
227+
let x_5 : u64 := mixHash x_3 x_4;
228+
let x_6 : obj := ctor_1.0.8[Exp.app._impl] x_1 x_2;
229+
sset x_6[2, 0] : u64 := x_5;
230+
ret x_6
231+
def Exp.var._override (x_1 : u32) : tobj :=
232+
let x_2 : u64 := UInt32.toUInt64 x_1;
233+
let x_3 : u64 := 1000;
234+
let x_4 : u64 := UInt64.add x_2 x_3;
235+
let x_5 : obj := ctor_0.0.12[Exp.var._impl];
236+
sset x_5[0, 0] : u64 := x_4;
237+
sset x_5[0, 8] : u32 := x_1;
238+
ret x_5
239239
def Exp.hash._override (x_1 : @& tobj) : u64 :=
240240
case x_1 : tobj of
241241
Exp.var._impl →

tests/lean/doubleReset.lean.expected.out

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
[Compiler.IR] [reset_reuse]
2+
def _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0 (x_1 : ◾) (x_2 : ◾) (x_3 : ◾) (x_4 : tobj) (x_5 : usize) (x_6 : usize) (x_7 : obj) : obj :=
3+
let x_8 : obj := _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg x_4 x_5 x_6 x_7;
4+
ret x_8
5+
def applyProjectionRules (x_1 : ◾) (x_2 : ◾) (x_3 : ◾) (x_4 : obj) (x_5 : tobj) : obj :=
6+
let x_6 : obj := applyProjectionRules._redArg x_4 x_5;
7+
ret x_6
8+
def applyProjectionRules._redArg (x_1 : obj) (x_2 : tobj) : obj :=
9+
let x_3 : usize := Array.usize ◾ x_1;
10+
let x_4 : usize := 0;
11+
let x_5 : obj := _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg x_2 x_3 x_4 x_1;
12+
ret x_5
213
def _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg (x_1 : tobj) (x_2 : usize) (x_3 : usize) (x_4 : obj) : obj :=
314
let x_5 : u8 := USize.decLt x_3 x_2;
415
case x_5 : u8 of
@@ -24,14 +35,3 @@
2435
let x_16 : obj := Array.uset ◾ x_11 x_3 x_13 ◾;
2536
let x_17 : obj := _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg x_1 x_2 x_15 x_16;
2637
ret x_17
27-
def _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0 (x_1 : ◾) (x_2 : ◾) (x_3 : ◾) (x_4 : tobj) (x_5 : usize) (x_6 : usize) (x_7 : obj) : obj :=
28-
let x_8 : obj := _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg x_4 x_5 x_6 x_7;
29-
ret x_8
30-
def applyProjectionRules._redArg (x_1 : obj) (x_2 : tobj) : obj :=
31-
let x_3 : usize := Array.usize ◾ x_1;
32-
let x_4 : usize := 0;
33-
let x_5 : obj := _private.Init.Data.Array.Basic.0.Array.mapMUnsafe.map._at_.applyProjectionRules.spec_0._redArg x_2 x_3 x_4 x_1;
34-
ret x_5
35-
def applyProjectionRules (x_1 : ◾) (x_2 : ◾) (x_3 : ◾) (x_4 : obj) (x_5 : tobj) : obj :=
36-
let x_6 : obj := applyProjectionRules._redArg x_4 x_5;
37-
ret x_6

tests/lean/reduceArity.lean.expected.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[Compiler.result] size: 1
2+
def g (α : ◾) (n : Nat) (a : lcAny) (b : lcAny) (f : lcAny → lcAny) : lcAny :=
3+
let _x.1 := g._redArg n a f;
4+
return _x.1
15
[Compiler.result] size: 9
26
def g._redArg (n : Nat) (a : lcAny) (f : lcAny → lcAny) : lcAny :=
37
let zero := 0;
@@ -11,10 +15,6 @@
1115
let _x.2 := g._redArg n.1 a f;
1216
let _x.3 := f _x.2;
1317
return _x.3
14-
[Compiler.result] size: 1
15-
def g (α : ◾) (n : Nat) (a : lcAny) (b : lcAny) (f : lcAny → lcAny) : lcAny :=
16-
let _x.1 := g._redArg n a f;
17-
return _x.1
1818
[Compiler.result] size: 1
1919
def h._closed_0 : Nat → Nat :=
2020
let _x.1 := double;

0 commit comments

Comments
 (0)