Skip to content

Commit 17a8ae0

Browse files
committed
Compiler: remove empty blocks
1 parent 46f55cf commit 17a8ae0

File tree

16 files changed

+2893
-3079
lines changed

16 files changed

+2893
-3079
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* Runtime/wasm: support unmarshaling compressed data (#1898)
2020
* Runtime/wasm: make resuming a continuation more efficient in Wasm (#1892)
2121
* Compiler: improve performance of Javascript linking
22+
* Compiler: remove empty blocks (#1934)
2223
* Ppx: explicitly disallow polymorphic method (#1897)
2324
* Ppx: allow "function" in object literals (#1897)
2425
* Lib: make the Wasm version of Json.output work with native ints and JavaScript objects (#1872)

compiler/lib-wasm/generate.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ let start () = make_context ~value_type:Gc_target.Value.value
12381238

12391239
let f ~context ~unit_name p ~live_vars ~in_cps ~deadcode_sentinal ~debug =
12401240
let t = Timer.make () in
1241-
let p = if effects_cps () then fix_switch_branches p else p in
1241+
let p = fix_switch_branches p in
12421242
let module G = Generate (Gc_target) in
12431243
let res = G.f ~context ~unit_name ~live_vars ~in_cps ~deadcode_sentinal ~debug p in
12441244
if times () then Format.eprintf " code gen.: %a@." Timer.print t;

compiler/lib/deadcode.ml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,62 @@ let add_cont_dep blocks defs (pc, args) =
186186
| Some block -> add_arg_dep defs block.params args
187187
| None -> () (* Dead continuation *)
188188

189+
let empty_body b =
190+
match b with
191+
| [] | [ Event _ ] -> true
192+
| _ -> false
193+
194+
let remove_empty_blocks ~live_vars (p : Code.program) : Code.program =
195+
let shortcuts = Hashtbl.create 16 in
196+
let rec resolve_rec visited ((pc, args) as cont) =
197+
if Addr.Set.mem pc visited
198+
then cont
199+
else
200+
match Hashtbl.find_opt shortcuts pc with
201+
| Some (params, cont) ->
202+
let pc', args' = resolve_rec (Addr.Set.add pc visited) cont in
203+
let s = Subst.from_map (Subst.build_mapping params args) in
204+
pc', List.map ~f:s args'
205+
| None -> cont
206+
in
207+
let resolve cont = resolve_rec Addr.Set.empty cont in
208+
Addr.Map.iter
209+
(fun pc block ->
210+
match block with
211+
| { params; body; branch = Branch cont; _ } when empty_body body ->
212+
let args =
213+
List.fold_left
214+
~f:(fun args x -> Var.Set.add x args)
215+
~init:Var.Set.empty
216+
(snd cont)
217+
in
218+
(* We can skip an empty block if its parameters are only
219+
used as argument to the continuation *)
220+
if
221+
List.for_all
222+
~f:(fun x -> live_vars.(Var.idx x) = 1 && Var.Set.mem x args)
223+
params
224+
then Hashtbl.add shortcuts pc (params, cont)
225+
| _ -> ())
226+
p.blocks;
227+
let blocks =
228+
Addr.Map.map
229+
(fun block ->
230+
{ block with
231+
branch =
232+
(let branch = block.branch in
233+
match branch with
234+
| Branch cont -> Branch (resolve cont)
235+
| Cond (x, cont1, cont2) -> Cond (x, resolve cont1, resolve cont2)
236+
| Switch (x, a1) -> Switch (x, Array.map ~f:resolve a1)
237+
| Pushtrap (cont1, x, cont2) -> Pushtrap (resolve cont1, x, resolve cont2)
238+
| Poptrap cont -> Poptrap (resolve cont)
239+
| Return _ | Raise _ | Stop -> branch)
240+
})
241+
p.blocks
242+
in
243+
{ p with blocks }
244+
189245
let f ({ blocks; _ } as p : Code.program) =
190246
let t = Timer.make () in
191247
let nv = Var.count () in

compiler/lib/deadcode.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ type variable_uses =
2222
int array (* For each variable, indicates how many times it is used. *)
2323

2424
val f : Code.program -> Code.program * variable_uses
25+
26+
val remove_empty_blocks : live_vars:variable_uses -> Code.program -> Code.program

compiler/lib/driver.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ let deadcode' p =
4949
Deadcode.f p
5050

5151
let deadcode p =
52-
let r, _ = deadcode' p in
53-
r
52+
let r, live_vars = deadcode' p in
53+
Deadcode.remove_empty_blocks ~live_vars r
5454

5555
let inline p =
5656
if Config.Flag.inline () && Config.Flag.deadcode ()
@@ -102,7 +102,7 @@ let effects ~deadcode_sentinal p =
102102
| `Cps | `Double_translation ->
103103
if debug () then Format.eprintf "Effects...@.";
104104
let p, live_vars = Deadcode.f p in
105-
let p = Effects.remove_empty_blocks ~live_vars p in
105+
let p = Deadcode.remove_empty_blocks ~live_vars p in
106106
let p, live_vars = Deadcode.f p in
107107
let info = Global_flow.f ~fast:false p in
108108
let p, live_vars =

compiler/lib/effects.ml

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,57 +1106,6 @@ let split_blocks ~cps_needed (p : Code.program) =
11061106

11071107
(****)
11081108

1109-
let remove_empty_blocks ~live_vars (p : Code.program) : Code.program =
1110-
let shortcuts = Hashtbl.create 16 in
1111-
let rec resolve_rec visited ((pc, args) as cont) =
1112-
if Addr.Set.mem pc visited
1113-
then cont
1114-
else
1115-
match Hashtbl.find_opt shortcuts pc with
1116-
| Some (params, cont) ->
1117-
let pc', args' = resolve_rec (Addr.Set.add pc visited) cont in
1118-
let s = Subst.from_map (Subst.build_mapping params args) in
1119-
pc', List.map ~f:s args'
1120-
| None -> cont
1121-
in
1122-
let resolve cont = resolve_rec Addr.Set.empty cont in
1123-
Addr.Map.iter
1124-
(fun pc block ->
1125-
match block with
1126-
| { params; body; branch = Branch cont; _ } when empty_body body ->
1127-
let args =
1128-
List.fold_left
1129-
~f:(fun args x -> Var.Set.add x args)
1130-
~init:Var.Set.empty
1131-
(snd cont)
1132-
in
1133-
(* We can skip an empty block if its parameters are only
1134-
used as argument to the continuation *)
1135-
if
1136-
List.for_all
1137-
~f:(fun x -> live_vars.(Var.idx x) = 1 && Var.Set.mem x args)
1138-
params
1139-
then Hashtbl.add shortcuts pc (params, cont)
1140-
| _ -> ())
1141-
p.blocks;
1142-
let blocks =
1143-
Addr.Map.map
1144-
(fun block ->
1145-
{ block with
1146-
branch =
1147-
(let branch = block.branch in
1148-
match branch with
1149-
| Branch cont -> Branch (resolve cont)
1150-
| Cond (x, cont1, cont2) -> Cond (x, resolve cont1, resolve cont2)
1151-
| Switch (x, a1) -> Switch (x, Array.map ~f:resolve a1)
1152-
| Pushtrap (cont1, x, cont2) -> Pushtrap (resolve cont1, x, resolve cont2)
1153-
| Poptrap cont -> Poptrap (resolve cont)
1154-
| Return _ | Raise _ | Stop -> branch)
1155-
})
1156-
p.blocks
1157-
in
1158-
{ p with blocks }
1159-
11601109
(****)
11611110

11621111
let f ~flow_info ~live_vars p =

compiler/lib/effects.mli

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
type trampolined_calls = Code.Var.Set.t
2020

21-
val remove_empty_blocks : live_vars:Deadcode.variable_uses -> Code.program -> Code.program
22-
2321
type in_cps = Code.Var.Set.t
2422

2523
val f :

compiler/tests-compiler/cond.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ let%expect_test "conditional" =
4545
function f(a, b, c, d, e, f){
4646
a:
4747
{
48-
b:
4948
if(a){
5049
if(! b && ! c && ! d && ! e && ! f){var x = 1; break a;}
5150
}
5251
else if(b){
53-
if(! c && ! d){if(e) break b; if(f) break b; var x = 2; break a;}
52+
if(! c && ! d && ! e && ! f){var x = 2; break a;}
5453
}
5554
else if(c){
5655
if(! d && ! e && ! f){var x = 3; break a;}
@@ -66,4 +65,5 @@ let%expect_test "conditional" =
6665
}
6766
return x + 2 | 0;
6867
}
69-
//end |}]
68+
//end
69+
|}]

compiler/tests-compiler/exceptions.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ let prevent_inline = some_name
3535
function some_name(param){
3636
try{
3737
try{throw caml_maybe_attach_backtrace(Stdlib[8], 1);}
38-
catch(x$0){var x = caml_wrap_exception(x$0), i$0 = x;}
38+
catch(x$0){var x = caml_wrap_exception(x$0), i = x;}
3939
}
40-
catch(i$1){var i = caml_wrap_exception(i$1), i$0 = i;}
41-
throw caml_maybe_attach_backtrace(i$0, 1);
40+
catch(_a_){var i = caml_wrap_exception(_a_);}
41+
throw caml_maybe_attach_backtrace(i, 1);
4242
}
43-
//end |}];
43+
//end
44+
|}];
4445
print_fun_decl (program ~debug:false) None;
4546
[%expect
4647
{|

compiler/tests-compiler/gh1007.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,11 @@ let () = M.myfun M.x
332332
len = len$0;
333333
param = l$0;
334334
}
335-
if(2 <= len) sort(len, l);
336-
x$0 = next;
335+
if(2 <= len){sort(len, l); x$0 = next;} else x$0 = next;
337336
}
338337
}
339-
//end |}]
338+
//end
339+
|}]
340340

341341
let%expect_test _ =
342342
let prog =

0 commit comments

Comments
 (0)