-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathpure_inline_cexpScript.sml
More file actions
221 lines (204 loc) · 6.75 KB
/
pure_inline_cexpScript.sml
File metadata and controls
221 lines (204 loc) · 6.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
(*
Inlining optimization for cexp
*)
Theory pure_inline_cexp
Ancestors
list pair topological_sort pure_cexp pure_vars balanced_map
pure_freshen pure_letrec_spec_cexp pure_dead_let pure_comp_conf
mlstring
Libs
BasicProvers
(*******************)
(* heuristic for deciding when to inline *)
Type heuristic = “:'a cexp -> bool”
Theorem cexp_size_lemma[local]:
∀vbs.
list_size (cexp_size (K 0)) (MAP SND vbs) ≤
list_size (pair_size mlstring_size (cexp_size (K 0))) vbs
Proof
Induct \\ fs [] \\ rw [] \\ res_tac
\\ fs [list_size_def,basicSizeTheory.pair_size_def]
\\ PairCases_on `h`
\\ fs [list_size_def,basicSizeTheory.pair_size_def]
QED
Definition cheap_def:
cheap (Var _ e) = T ∧
cheap (Lam _ _ _) = T ∧
cheap (Prim _ _ xs) = NULL xs ∧
cheap _ = F
End
Definition heuristic_insert_def:
heuristic_insert m h v e =
if cheap e ∧ h e then
insert m v e
else
m
End
Definition heuristic_insert_Rec_def:
heuristic_insert_Rec m h fs =
case fs of
| [(v, e)] =>
if h e then (
case specialise v e of
| NONE => m
| SOME b => insert m v b
)
else
m
| _ => m
End
Theorem size_lemma[local]:
∀bs.
list_size (λx. cexp_size (K 0) (SND (SND x))) bs ≤
list_size (pair_size mlstring_size
(pair_size (list_size mlstring_size) (cexp_size (K 0)))) bs
Proof
Induct \\ fs [list_size_def,FORALL_PROD,basicSizeTheory.pair_size_def]
QED
(*
It can be the case that we create sth like:
```
(\x -> x + 1) y
```
by inlining in the App case. The problem now is that
```
(\x -> x + 1) y ≠ let x = y in x + 1
```
And so goint further won't do anything
*)
Definition App_Lam_to_Lets_def:
App_Lam_to_Lets (App a (Lam _ vs b) es) =
(if LENGTH es < LENGTH vs (* not fully applied *) then NONE else
let es1 = TAKE (LENGTH vs) es in
let es2 = DROP (LENGTH vs) es in
SOME $ SmartApp a (Lets a (ZIP (vs,es1)) b) es2) ∧
App_Lam_to_Lets e = NONE
End
Definition inline_def:
inline (m: ('a cexp) var_map) ns (cl: num) (h: 'a heuristic) (Var (a: 'a) v) =
(case lookup m v of
| NONE => (Var a v, ns)
| SOME e =>
if is_Lam e
then (Var a v, ns)
else if cl = 0 then (Var a v, ns)
else (
inline m ns (cl - 1) h e
)) ∧
inline m ns cl h (App a e es) = (
let (es1, ns1) = inline_list m ns cl h es
in (
case get_Var_name e of
(* Var applied to arguments *)
| SOME v => (
case lookup m v of
| SOME e_m =>
let (exp, ns2) = freshen_cexp (App a e_m es1) ns1
in (case App_Lam_to_Lets exp of
| NONE => (App a e es1, ns1)
| SOME exp1 =>
if cl = 0 then (App a e es1, ns1)
else inline m ns2 (cl - 1) h exp1
)
| _ =>
let (e1, ns2) = inline m ns1 cl h e
in (App a e1 es1, ns2)
)
(* Not a Var -- can't inline *)
| _ =>
let (e1, ns2) = inline m ns1 cl h e
in (App a e1 es1, ns2)
)
) ∧
inline m ns cl h (Let a v e1 e2) =
(let m1 = heuristic_insert m h v e1
in let (e3, ns3) = inline m ns cl h e1
in let (e4, ns4) = inline m1 ns3 cl h e2
in (Let a v e3 e4, ns4)) ∧
inline m ns cl h (Letrec a vbs e) =
(let m1 = heuristic_insert_Rec m h vbs
in let (vbs1, ns1) = inline_list m ns cl h (MAP SND vbs)
in let (e2, ns2) = inline m1 ns1 cl h e
in (Letrec a (MAP2 (λ(v,_) x. (v, x)) vbs vbs1) e2, ns2)) ∧
inline m ns cl h (Lam a vs e) =
(let (e1, ns1) = inline m ns cl h e
in (Lam a vs e1, ns1)) ∧
inline m ns cl h (Prim a op es) =
(let (es2, ns2) = inline_list m ns cl h es
in (Prim a op es2, ns2)) ∧
inline m ns cl h (Case a e v bs f) =
(let (e1, ns1) = inline m ns cl h e
in let (bs2, ns2) = inline_list m ns1 cl h (MAP (λ(v, vs, e). e) bs)
in let (f3, ns3) = case f of
| NONE => (NONE, ns2)
| SOME (vs, e) =>
let (e4, ns4) = inline m ns2 cl h e
in (SOME (vs, e4), ns4)
in (Case a e1 v (MAP2 (λ(v, vs, _) e. (v, vs, e)) bs bs2) f3, ns3)) ∧
inline m ns cl h (NestedCase a e v p e' bs) =
(NestedCase a e v p e' bs, ns) ∧
inline_list m ns cl h [] = ([], ns) ∧
inline_list m ns cl h (e::es) =
(let (e1, ns1) = inline m ns cl h e in
let (es2, ns2) = inline_list m ns1 cl h es
in (e1::es2, ns2))
Termination
WF_REL_TAC `inv_image ($< LEX $<) $ λx. case x of
| INL (m, ns, cl, h, e) => (cl, cexp_size (K 0) e)
| INR (m, ns, cl, h, es) => (cl, list_size (cexp_size (K 0)) es)`
\\ fs [] \\ rw [] \\ gvs []
\\ qspec_then `vbs` assume_tac cexp_size_lemma \\ fs []
\\ qspec_then ‘bs’ assume_tac size_lemma \\ fs []
End
Definition inline_all_def:
inline_all cl h e =
let (e1, s) = freshen_cexp e (boundvars_of e)
in let (inlined_e, _) = inline empty s cl h e1
in dead_let inlined_e
End
Theorem cexp_size_lemma2[local]:
∀xs e.
MEM e xs ⇒
cexp_size (K 0) e ≤ list_size (cexp_size (K 0)) xs
Proof
Induct \\ fs [] \\ rw [] \\ res_tac \\ fs [list_size_def]
QED
Definition tree_size_heuristic_rec_def:
tree_size_heuristic_rec (n: num) (Var a v) = (n - 1) ∧
tree_size_heuristic_rec n (Prim a op es) =
FOLDL (λa e. if a < 0 then a else tree_size_heuristic_rec a e) (n - 1) es ∧
tree_size_heuristic_rec n (App a e es) =
FOLDL (λa e. if a < 0 then a else tree_size_heuristic_rec a e) (n - 1) (e::es) ∧
tree_size_heuristic_rec n (Lam a vs e) =
tree_size_heuristic_rec (n - 1) e ∧
tree_size_heuristic_rec n (Let a v e1 e2) =
(let n1 = tree_size_heuristic_rec (n - 1) e1
in if n1 < 0 then n1 else tree_size_heuristic_rec n1 e2) ∧
tree_size_heuristic_rec n (Letrec a vbs e) =
(let n1 = FOLDL (λa (v, e). if a < 0 then a else tree_size_heuristic_rec a e) (n - 1) vbs
in if n1 < 0 then n1 else tree_size_heuristic_rec n1 e) ∧
tree_size_heuristic_rec n (Case a e v bs f) =
(let n1 = FOLDL (λa (v, vs, e). if a < 0 then a else tree_size_heuristic_rec a e) (n - 1) bs
in if n1 < 0 then n1 else
case f of
NONE => n1
| SOME (vs, e) => tree_size_heuristic_rec n1 e) ∧
tree_size_heuristic_rec n (NestedCase a e v p e' bs) =
(let n1 = FOLDL (λa (p, e). if a < 0 then a else tree_size_heuristic_rec a e) (n - 1) bs
in if n1 < 0 then n1 else tree_size_heuristic_rec n1 e')
Termination
WF_REL_TAC ‘measure (λx. case x of
| (n, e) => cexp_size (K 0) e)’
\\ fs [] \\ rw [] \\ gvs []
\\ imp_res_tac cexp_size_lemma2 \\ fs []
End
Definition tree_size_heuristic_def:
tree_size_heuristic n e =
(tree_size_heuristic_rec n e ≥ 0)
End
(*******************)
Definition inline_top_level_def:
inline_top_level c e =
inline_all c.inlining.depth (tree_size_heuristic c.inlining.heuristic) e
End
(*******************)