Skip to content

Commit 5953744

Browse files
committed
Inline: remove dead closures to respect the invariant
1 parent 8788502 commit 5953744

File tree

1 file changed

+54
-7
lines changed

1 file changed

+54
-7
lines changed

compiler/lib/inline.ml

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ let inline inline_count live_vars closures pc (outer, p) =
197197
make this code unoptimized. (wrt to Jit compilers) *)
198198
&& f_size < Config.Param.inlining_limit ()
199199
then (
200+
live_vars.(Var.idx f) <- 0;
200201
let blocks, cont_pc, free_pc =
201202
match rem, branch with
202203
| [], Return y when Var.compare x y = 0 ->
@@ -298,6 +299,48 @@ let stats = Debug.find "stats"
298299

299300
let debug_stats = Debug.find "stats-debug"
300301

302+
(* Inlining a function used only once will leave an unused closure
303+
with an initial continuation pointing to a block belonging to
304+
another function. This removes these closures. *)
305+
306+
let remove_dead_closures_from_block ~live_vars p pc block =
307+
let is_dead_closure i =
308+
match i with
309+
| Let (f, Closure _) ->
310+
let f = Var.idx f in
311+
f < Array.length live_vars && live_vars.(f) = 0
312+
| _ -> false
313+
in
314+
if List.exists ~f:is_dead_closure block.body
315+
then
316+
{ p with
317+
blocks =
318+
Addr.Map.add
319+
pc
320+
{ block with
321+
body =
322+
List.fold_left block.body ~init:[] ~f:(fun acc i ->
323+
match i, acc with
324+
| Event _, Event _ :: prev ->
325+
(* Avoid consecutive events (keep just the last one) *)
326+
i :: prev
327+
| _ -> if is_dead_closure i then acc else i :: acc)
328+
|> List.rev
329+
}
330+
p.blocks
331+
}
332+
else p
333+
334+
let remove_dead_closures ~live_vars p pc =
335+
Code.traverse
336+
{ fold = fold_children }
337+
(fun pc p ->
338+
let block = Addr.Map.find pc p.blocks in
339+
remove_dead_closures_from_block ~live_vars p pc block)
340+
pc
341+
p.blocks
342+
p
343+
301344
let f p live_vars =
302345
let previous_p = p in
303346
let inline_count = ref 0 in
@@ -309,12 +352,16 @@ let f p live_vars =
309352
p
310353
(fun name cl_params (pc, _) _ (closures, p) ->
311354
let traverse outer =
312-
Code.traverse
313-
{ fold = Code.fold_children }
314-
(inline inline_count live_vars closures)
315-
pc
316-
p.blocks
317-
(outer, p)
355+
let outer, p =
356+
Code.traverse
357+
{ fold = Code.fold_children }
358+
(inline inline_count live_vars closures)
359+
pc
360+
p.blocks
361+
(outer, p)
362+
in
363+
let p = remove_dead_closures ~live_vars p pc in
364+
outer, p
318365
in
319366
match name with
320367
| None ->
@@ -333,8 +380,8 @@ let f p live_vars =
333380
(* Inlining a raising function can result in empty blocks *)
334381
if times () then Format.eprintf " inlining: %a@." Timer.print t;
335382
if stats () then Format.eprintf "Stats - inline: %d optimizations@." !inline_count;
383+
let p = Deadcode.remove_unused_blocks p in
336384
if debug_stats ()
337385
then Code.check_updates ~name:"inline" previous_p p ~updates:!inline_count;
338-
let p = Deadcode.remove_unused_blocks p in
339386
Code.invariant p;
340387
p

0 commit comments

Comments
 (0)