@@ -39,7 +39,7 @@ We try to find a good order to traverse the code:
3939 first
4040*)
4141
42- let collect_closures p =
42+ let collect_closures closures_position p =
4343 let closures = Var.Hashtbl. create 128 in
4444 let rec traverse p enclosing pc =
4545 Code. traverse
@@ -51,6 +51,7 @@ let collect_closures p =
5151 match i with
5252 | Let (f , Closure (params , ((pc' , _ ) as cont ), _ )) ->
5353 Var.Hashtbl. add closures f (params, cont, enclosing);
54+ Var.Hashtbl. add closures_position f pc;
5455 traverse p (Some f) pc'
5556 | _ -> () )
5657 block.body)
@@ -91,25 +92,20 @@ let collect_deps p closures =
9192
9293module Var_SCC = Strongly_connected_components. Make (Var )
9394
94- let visit_closures p ~live_vars f ~ cleanup acc =
95- let closures = collect_closures p in
95+ let visit_closures p closures_position ~live_vars f acc =
96+ let closures = collect_closures closures_position p in
9697 let deps = collect_deps p closures in
9798 let scc = Var_SCC. connected_components_sorted_from_roots_to_leaf deps in
9899 let f' recursive acc g =
99100 let params, cont, enclosing_function = Var.Hashtbl. find closures g in
100101 f ~recursive ~enclosing_function ~current_function: (Some g) ~params ~cont acc
101102 in
102- let cleanup' l acc =
103- List. fold_left l ~init: acc ~f: (fun acc x ->
104- let _, (pc, _), _ = Var.Hashtbl. find closures x in
105- cleanup pc acc)
106- in
107103 let acc =
108104 Array. fold_left
109105 scc
110106 ~f: (fun acc group ->
111107 match group with
112- | Var_SCC. No_loop g -> f' false acc g |> cleanup' [ g ]
108+ | Var_SCC. No_loop g -> f' false acc g
113109 | Has_loop l ->
114110 let set = Var.Set. of_list l in
115111 let deps' =
@@ -129,14 +125,9 @@ let visit_closures p ~live_vars f ~cleanup acc =
129125 scc
130126 ~f: (fun acc group ->
131127 match group with
132- | Var_SCC. No_loop g -> f' true acc g |> cleanup' [ g ]
133- | Has_loop l ->
134- List. fold_left
135- ~f: (fun acc g -> f' true acc g |> cleanup' [ g ])
136- ~init: acc
137- l)
138- ~init: acc
139- |> cleanup' l)
128+ | Var_SCC. No_loop g -> f' true acc g
129+ | Has_loop l -> List. fold_left ~f: (fun acc g -> f' true acc g) ~init: acc l)
130+ ~init: acc)
140131 ~init: acc
141132 in
142133 f
@@ -146,7 +137,6 @@ let visit_closures p ~live_vars f ~cleanup acc =
146137 ~params: []
147138 ~cont: (p.start, [] )
148139 acc
149- |> cleanup p.start
150140
151141(* ***)
152142
@@ -196,6 +186,7 @@ type info =
196186
197187type context =
198188 { profile : Profile .t (* * Aggressive inlining? *)
189+ ; closures_position : Addr .t Var.Hashtbl .t
199190 ; p : program
200191 ; live_vars : int array (* * Occurence count of all variables *)
201192 ; inline_count : int ref (* * Inlining statistics *)
@@ -481,32 +472,17 @@ let remove_dead_closures_from_block ~live_vars block =
481472 f < Array. length live_vars && live_vars.(f) = 0
482473 | _ -> false
483474 in
484- if List. exists ~f: is_dead_closure block.body
485- then
486- { block with
487- body =
488- List. fold_left block.body ~init: [] ~f: (fun acc i ->
489- match i, acc with
490- | Event _ , Event _ :: prev ->
491- (* Avoid consecutive events (keep just the last one) *)
492- i :: prev
493- | _ -> if is_dead_closure i then acc else i :: acc)
494- |> List. rev
495- }
496- else block
497-
498- let remove_dead_closures ~live_vars p pc =
499- Code. traverse
500- { fold = fold_children }
501- (fun pc p ->
502- let block = Addr.Map. find pc p.blocks in
503- let block' = remove_dead_closures_from_block ~live_vars block in
504- if phys_equal block block'
505- then p
506- else { p with blocks = Addr.Map. add pc block' p.blocks })
507- pc
508- p.blocks
509- p
475+ assert (List. exists ~f: is_dead_closure block.body);
476+ { block with
477+ body =
478+ List. fold_left block.body ~init: [] ~f: (fun acc i ->
479+ match i, acc with
480+ | Event _ , Event _ :: prev ->
481+ (* Avoid consecutive events (keep just the last one) *)
482+ i :: prev
483+ | _ -> if is_dead_closure i then acc else i :: acc)
484+ |> List. rev
485+ }
510486
511487(* ***)
512488
@@ -527,7 +503,7 @@ let rewrite_closure blocks cont_pc clos_pc =
527503 blocks
528504 blocks
529505
530- let inline_function p rem branch x params cont args =
506+ let inline_function closures_position p rem branch x params cont args =
531507 let blocks, cont_pc, free_pc =
532508 match rem, branch with
533509 | [] , Return y when Var. equal x y ->
@@ -536,6 +512,9 @@ let inline_function p rem branch x params cont args =
536512 | _ ->
537513 let fresh_addr = p.free_pc in
538514 let free_pc = fresh_addr + 1 in
515+ List. iter rem ~f: (function
516+ | Let (x , Closure _ ) -> Var.Hashtbl. replace closures_position x fresh_addr
517+ | _ -> () );
539518 ( Addr.Map. add fresh_addr { params = [ x ]; body = rem; branch } p.blocks
540519 , Some fresh_addr
541520 , free_pc )
@@ -552,7 +531,7 @@ let inline_function p rem branch x params cont args =
552531 in
553532 [] , (Branch (fresh_addr, args), { p with blocks; free_pc })
554533
555- let inline_in_block ~context pc block p =
534+ let inline_in_block ~context pc block p inlined =
556535 let body, (branch, p) =
557536 List. fold_right
558537 ~f: (fun i (rem , state ) ->
@@ -565,13 +544,15 @@ let inline_in_block ~context pc block p =
565544 then (
566545 let branch, p = state in
567546 incr context.inline_count;
547+ inlined := Var.Set. add f ! inlined;
568548 if closure_count ~context info > 0 then context.has_closures := true ;
569549 context.live_vars.(Var. idx f) < - context.live_vars.(Var. idx f) - 1 ;
570550 if context.live_vars.(Var. idx f) > 0
571551 then
572552 let p, _, params, cont = Duplicate. closure p ~f ~params ~cont in
573- inline_function p rem branch x params cont args
574- else inline_function p rem branch x params cont args)
553+ inline_function context.closures_position p rem branch x params cont args
554+ else
555+ inline_function context.closures_position p rem branch x params cont args)
575556 else i :: rem, state
576557 | _ -> i :: rem, state)
577558 ~init: ([] , (block.branch, p))
@@ -580,9 +561,11 @@ let inline_in_block ~context pc block p =
580561 { p with blocks = Addr.Map. add pc { block with body; branch } p.blocks }
581562
582563let inline ~profile ~inline_count p ~live_vars =
564+ let closures_position = Var.Hashtbl. create 18 in
583565 if debug () then Format. eprintf " ====== inlining ======@." ;
584566 (visit_closures
585567 p
568+ closures_position
586569 ~live_vars
587570 (fun ~recursive
588571 ~enclosing_function
@@ -597,6 +580,7 @@ let inline ~profile ~inline_count p ~live_vars =
597580 let context =
598581 { context with has_closures; enclosing_function; current_function }
599582 in
583+ let inlined = ref Var.Set. empty in
600584 let p =
601585 Code. traverse
602586 { fold = Code. fold_children }
@@ -616,11 +600,34 @@ let inline ~profile ~inline_count p ~live_vars =
616600 ~context: { context with in_loop = Addr.Set. mem pc in_loop }
617601 pc
618602 block
619- p)
603+ p
604+ inlined)
620605 pc
621606 p.blocks
622607 p
623608 in
609+ let blocks_to_clean =
610+ Var.Set. fold
611+ (fun f acc ->
612+ let f_idx = Var. idx f in
613+ if f_idx < Array. length live_vars && live_vars.(f_idx) = 0
614+ then
615+ let pc = Var.Hashtbl. find closures_position f in
616+ Addr.Set. add pc acc
617+ else acc)
618+ ! inlined
619+ Addr.Set. empty
620+ in
621+ let blocks =
622+ Addr.Set. fold
623+ (fun pc blocks ->
624+ let block = Addr.Map. find pc blocks in
625+ let block = remove_dead_closures_from_block ~live_vars block in
626+ Addr.Map. add pc block blocks)
627+ blocks_to_clean
628+ p.blocks
629+ in
630+ let p = { p with blocks } in
624631 let env =
625632 match current_function with
626633 | Some f ->
@@ -643,10 +650,8 @@ let inline ~profile ~inline_count p ~live_vars =
643650 | None -> context.env
644651 in
645652 { context with p; env })
646- ~cleanup: (fun pc context ->
647- let p = remove_dead_closures ~live_vars context.p pc in
648- { context with p })
649653 { profile
654+ ; closures_position
650655 ; p
651656 ; live_vars
652657 ; inline_count
0 commit comments