@@ -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