@@ -77,12 +77,12 @@ type info =
77
77
; params : Var .t list
78
78
; cont : Code .cont
79
79
; enclosing_function : Var .t option
80
+ ; recursive : bool
80
81
; loops : bool cache
81
82
; body_size : int cache
82
83
; full_size : int cache
83
84
; closure_count : int cache
84
85
; init_code : int cache
85
- ; recursive : bool cache
86
86
; return_block : bool cache
87
87
; interesting_params : (Var .t * int ) list cache
88
88
; mutable dead : bool
@@ -176,34 +176,6 @@ let count_init_code info =
176
176
~init: 0
177
177
body)
178
178
179
- let is_recursive info ~env =
180
- let f = info.f in
181
- cache info.cont info.recursive (fun { blocks; _ } pc ->
182
- let rec traverse blocks f pc =
183
- Code. traverse
184
- { fold = fold_children }
185
- (fun pc _ ->
186
- let block = Addr.Map. find pc blocks in
187
- Freevars. iter_block_free_vars
188
- (fun f' -> if Var. equal f f' then raise Exit )
189
- block;
190
- List. iter
191
- ~f: (fun i ->
192
- match i with
193
- | Let (f' , Closure (_ , (pc' , _ ))) ->
194
- if not (Var.Map. mem f' env && (Var.Map. find f' env).dead)
195
- then traverse blocks f pc'
196
- | _ -> () )
197
- block.body)
198
- pc
199
- blocks
200
- ()
201
- in
202
- try
203
- traverse blocks f pc;
204
- false
205
- with Exit -> true )
206
-
207
179
let return_block info =
208
180
cache info.cont info.return_block (fun { blocks; _ } pc ->
209
181
Code. traverse
@@ -246,10 +218,10 @@ let interesting_parameters info ~live_vars =
246
218
[] )
247
219
248
220
let functor_like ~env p info =
249
- (not (contains_loop info p))
221
+ (not info.recursive)
222
+ && (not (contains_loop info p))
250
223
&& return_block info p
251
224
&& count_init_code info p * 2 > body_size info ~env p
252
- && (not (is_recursive info ~env p))
253
225
&& full_size info ~env p - body_size info ~env p < = 20 * closure_count info ~env p
254
226
255
227
let rec small_function
@@ -262,9 +234,9 @@ let rec small_function
262
234
~has_closures
263
235
info
264
236
args =
265
- body_size info ~env p < = 15
237
+ (not info.recursive)
238
+ && body_size info ~env p < = 15
266
239
&& closure_count info ~env p = 0
267
- && (not (is_recursive info ~env p))
268
240
&& (not (List. is_empty args))
269
241
&&
270
242
let relevant_params = interesting_parameters info ~live_vars p in
@@ -343,6 +315,79 @@ and should_inline
343
315
344
316
(* ***)
345
317
318
+ let collect_closures p =
319
+ let rec traverse p current pc closures =
320
+ Code. traverse
321
+ { fold = Code. fold_children }
322
+ (fun pc closures ->
323
+ let block = Addr.Map. find pc p.blocks in
324
+ List. fold_left
325
+ ~f: (fun closures i ->
326
+ match i with
327
+ | Let (f , Closure (params , ((pc' , _ ) as cont ))) ->
328
+ let closures = Var.Map. add f (params, cont, current) closures in
329
+ traverse p (Some f) pc' closures
330
+ | _ -> closures)
331
+ ~init: closures
332
+ block.body)
333
+ pc
334
+ p.blocks
335
+ closures
336
+ in
337
+ traverse p None p.start Var.Map. empty
338
+
339
+ let add_dep deps current f =
340
+ Option. iter
341
+ ~f: (fun g -> deps := Var.Map. add f (Var.Set. add g (Var.Map. find f ! deps)) ! deps)
342
+ current
343
+
344
+ let collect_deps p closures =
345
+ let deps = ref (Var.Map. map (fun _ -> Var.Set. empty) closures) in
346
+ let traverse p current pc =
347
+ Code. traverse
348
+ { fold = Code. fold_children }
349
+ (fun pc () ->
350
+ let block = Addr.Map. find pc p.blocks in
351
+ Freevars. iter_block_free_vars
352
+ (fun f -> if Var.Map. mem f closures then add_dep deps current f)
353
+ block;
354
+ List. iter
355
+ ~f: (fun i ->
356
+ match i with
357
+ | Let (f , Closure _ ) -> add_dep deps current f
358
+ | _ -> () )
359
+ block.body)
360
+ pc
361
+ p.blocks
362
+ ()
363
+ in
364
+ traverse p None p.start;
365
+ Var.Map. iter (fun f (_ , (pc , _ ), _ ) -> traverse p (Some f) pc) closures;
366
+ ! deps
367
+
368
+ module Var_SCC = Strongly_connected_components. Make (Var )
369
+
370
+ let visit_closures p f acc =
371
+ let closures = collect_closures p in
372
+ let deps = collect_deps p closures in
373
+ let scc = Var_SCC. connected_components_sorted_from_roots_to_leaf deps in
374
+ let f' recursive acc g =
375
+ let params, cont, parent = Var.Map. find g closures in
376
+ f recursive parent (Some g) params cont acc
377
+ in
378
+ let acc =
379
+ Array. fold_left
380
+ scc
381
+ ~f: (fun acc group ->
382
+ match group with
383
+ | Var_SCC. No_loop g -> f' false acc g
384
+ | Has_loop l -> List. fold_left ~f: (fun acc g -> f' true acc g) ~init: acc l)
385
+ ~init: acc
386
+ in
387
+ f false None None [] (p.start, [] ) acc
388
+
389
+ (* ***)
390
+
346
391
let rewrite_block pc' pc blocks =
347
392
let block = Addr.Map. find pc blocks in
348
393
let block =
@@ -468,7 +513,7 @@ let trace_inlining
468
513
sz
469
514
sz'
470
515
(contains_loop info p)
471
- (is_recursive info ~env p)
516
+ info.recursive
472
517
(closure_count info ~env p)
473
518
(count_init_code info p)
474
519
(return_block info p)
@@ -547,9 +592,9 @@ let inline_in_block
547
592
let inline ~inline_count p ~live_vars =
548
593
if debug () then Format. eprintf " ====== inlining ======@." ;
549
594
fst
550
- (Code. fold_closures_in_reverse_postorder
595
+ (visit_closures
551
596
p
552
- (fun enclosing_function name_opt params ((pc , _ ) as cont ) (p , env ) ->
597
+ (fun recursive enclosing_function name_opt params ((pc , _ ) as cont ) (p , env ) ->
553
598
let has_closures = ref (closure_count_uncached ~env p pc > 0 ) in
554
599
let in_loop = blocks_in_loop p pc in
555
600
let p =
@@ -591,12 +636,12 @@ let inline ~inline_count p ~live_vars =
591
636
; params
592
637
; cont
593
638
; enclosing_function
639
+ ; recursive
594
640
; loops = ref None
595
641
; body_size = ref None
596
642
; full_size = ref None
597
643
; closure_count = ref None
598
644
; init_code = ref None
599
- ; recursive = ref None
600
645
; return_block = ref None
601
646
; interesting_params = ref None
602
647
; dead = false
0 commit comments