Skip to content

Commit 7119cc4

Browse files
committed
Simplify nested conditionals
When a conditional is simplified, it might be possible to simply previous conditionals as well. Do this in one pass.
1 parent 4f91c6c commit 7119cc4

File tree

1 file changed

+61
-37
lines changed

1 file changed

+61
-37
lines changed

compiler/lib/deadcode.ml

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -349,28 +349,30 @@ let remove_empty_blocks st (p : Code.program) : Code.program =
349349
if not (Code.cont_equal cont cont') then st.block_shortcut <- st.block_shortcut + 1;
350350
cont'
351351
in
352-
Addr.Map.iter
353-
(fun pc block ->
354-
match block with
355-
| { params; body; branch = Branch cont; _ } when empty_body body ->
356-
let args =
357-
List.fold_left
358-
~f:(fun args x -> Var.Set.add x args)
359-
~init:Var.Set.empty
360-
(snd cont)
361-
in
362-
(* We can skip an empty block if its parameters are only
352+
let register_block_if_empty pc block =
353+
match block with
354+
| { params; body; branch = Branch cont; _ } when empty_body body ->
355+
let args =
356+
List.fold_left
357+
~f:(fun args x -> Var.Set.add x args)
358+
~init:Var.Set.empty
359+
(snd cont)
360+
in
361+
(* We can skip an empty block if its parameters are only
363362
used as argument to the continuation *)
364-
if
365-
List.for_all
366-
~f:(fun x -> st.live.(Var.idx x) = 1 && Var.Set.mem x args)
367-
params
368-
then Addr.Hashtbl.add shortcuts pc (params, cont)
369-
| _ -> ())
370-
p.blocks;
363+
if List.for_all ~f:(fun x -> st.live.(Var.idx x) = 1 && Var.Set.mem x args) params
364+
then Addr.Hashtbl.add shortcuts pc (params, cont)
365+
| _ -> ()
366+
in
367+
Addr.Map.iter register_block_if_empty p.blocks;
371368
let blocks =
372-
Addr.Map.fold
373-
(fun pc block blocks ->
369+
(* We are relying on the fact that forward branches target blocks
370+
with higher addresses in the code generated by the OCaml
371+
compiler. By processing the blocks in descending address order,
372+
simplifying a branch can make it possible to simplify earlier
373+
branches. *)
374+
Seq.fold_left
375+
(fun blocks (pc, block) ->
374376
if
375377
match block.branch with
376378
| Branch (pc, _) | Poptrap (pc, _) -> not (Addr.Hashtbl.mem shortcuts pc)
@@ -383,25 +385,47 @@ let remove_empty_blocks st (p : Code.program) : Code.program =
383385
else
384386
Addr.Map.add
385387
pc
386-
{ block with
387-
branch =
388-
(let branch = block.branch in
389-
match branch with
390-
| Branch cont -> Branch (resolve cont)
391-
| Cond (x, cont1, cont2) ->
392-
let cont1' = resolve cont1 in
393-
let cont2' = resolve cont2 in
394-
if Code.cont_equal cont1' cont2'
395-
then Branch cont1'
396-
else Cond (x, cont1', cont2')
397-
| Switch (x, a1) -> Switch (x, Array.map ~f:resolve a1)
398-
| Pushtrap (cont1, x, cont2) -> Pushtrap (resolve cont1, x, resolve cont2)
399-
| Poptrap cont -> Poptrap (resolve cont)
400-
| Return _ | Raise _ | Stop -> assert false)
401-
}
388+
(match block with
389+
| { body; branch = Cond (x, cont1, cont2); _ } ->
390+
let cont1' = resolve cont1 in
391+
let cont2' = resolve cont2 in
392+
if Code.cont_equal cont1' cont2'
393+
then (
394+
let decr_usage x = st.live.(Var.idx x) <- st.live.(Var.idx x) - 1 in
395+
decr_usage x;
396+
let body =
397+
List.fold_right
398+
~f:(fun i rem ->
399+
if live_instr st i
400+
then
401+
match i, rem with
402+
| Event _, Event _ :: _ -> rem
403+
| _ -> i :: rem
404+
else (
405+
Freevars.iter_instr_free_vars decr_usage i;
406+
rem))
407+
body
408+
~init:[]
409+
in
410+
let block = { block with body; branch = Branch cont1' } in
411+
register_block_if_empty pc block;
412+
block)
413+
else { block with branch = Cond (x, cont1', cont2') }
414+
| _ ->
415+
{ block with
416+
branch =
417+
(let branch = block.branch in
418+
match branch with
419+
| Branch cont -> Branch (resolve cont)
420+
| Switch (x, a1) -> Switch (x, Array.map ~f:resolve a1)
421+
| Pushtrap (cont1, x, cont2) ->
422+
Pushtrap (resolve cont1, x, resolve cont2)
423+
| Poptrap cont -> Poptrap (resolve cont)
424+
| Cond _ | Return _ | Raise _ | Stop -> assert false)
425+
})
402426
blocks)
403427
p.blocks
404-
p.blocks
428+
(Addr.Map.to_rev_seq p.blocks)
405429
in
406430
{ p with blocks }
407431

0 commit comments

Comments
 (0)