Skip to content

Commit 6dcc384

Browse files
vouillonhhugo
authored andcommitted
Avoid additional block splitting during CPS transformation
We ignore any event at the end of a block. This happens when the block ends with a return or a branch. In case of a return, it's a tail call, so we don't have an event anyway. For a branch, the target block will start with an event which is would take precedence anyway.
1 parent 1cb65d9 commit 6dcc384

File tree

3 files changed

+78
-66
lines changed

3 files changed

+78
-66
lines changed

compiler/lib/effects.ml

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ let dominance_frontier g idom =
139139
g.preds;
140140
frontiers
141141

142+
(* Last instruction of a block, ignoring events *)
143+
let rec last_instr l =
144+
match l with
145+
| [] -> None
146+
| [ i ] | [ i; (Event _, _) ] -> Some i
147+
| _ :: rem -> last_instr rem
148+
149+
(* Split a block, separating the last instruction from the preceeding
150+
ones, ignoring events *)
151+
let block_split_last xs =
152+
let rec aux acc = function
153+
| [] -> None
154+
| [ x ] | [ x; (Event _, _) ] -> Some (List.rev acc, x)
155+
| x :: xs -> aux (x :: acc) xs
156+
in
157+
aux [] xs
158+
159+
let empty_body b =
160+
match b with
161+
| [] | [ (Event _, _) ] -> true
162+
| _ -> false
163+
142164
(****)
143165

144166
(*
@@ -176,7 +198,7 @@ let compute_needed_transformations ~cfg ~idom ~cps_needed ~blocks ~start =
176198
let block = Addr.Map.find pc blocks in
177199
(match fst block.branch with
178200
| Branch (dst, _) -> (
179-
match List.last block.body with
201+
match last_instr block.body with
180202
| Some
181203
( Let
182204
(x, (Apply _ | Prim (Extern ("%resume" | "%perform" | "%reperform"), _)))
@@ -572,7 +594,7 @@ let cps_block ~st ~k pc block =
572594
in
573595

574596
let rewritten_block =
575-
match List.split_last block.body, block.branch with
597+
match block_split_last block.body, block.branch with
576598
| Some (body_prefix, (Let (x, e), loc)), (Return ret, _loc_ret) ->
577599
Option.map (rewrite_instr x e loc) ~f:(fun f ->
578600
assert (List.is_empty alloc_jump_closures);
@@ -847,7 +869,7 @@ let split_blocks ~cps_needed (p : Code.program) =
847869
let is_split_point i r branch =
848870
match i with
849871
| Let (x, (Apply _ | Prim (Extern ("%resume" | "%perform" | "%reperform"), _))) ->
850-
((not (List.is_empty r))
872+
((not (empty_body r))
851873
||
852874
match fst branch with
853875
| Branch _ -> false
@@ -901,14 +923,6 @@ let remove_empty_blocks ~live_vars (p : Code.program) : Code.program =
901923
| None -> cont
902924
in
903925
let resolve cont = resolve_rec Addr.Set.empty cont in
904-
let empty_body b =
905-
List.for_all
906-
~f:(fun (i, _) ->
907-
match i with
908-
| Event _ -> true
909-
| _ -> false)
910-
b
911-
in
912926
Addr.Map.iter
913927
(fun pc block ->
914928
match block with

compiler/lib/partial_cps_analysis.ml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,18 @@ let add_tail_dep deps x y =
3939
(fun s -> Some (Var.Set.add x (Option.value ~default:Var.Set.empty s)))
4040
!deps
4141

42+
let rec block_iter_last ~f l =
43+
match l with
44+
| [] -> ()
45+
| [ i ] -> f true i
46+
| [ i; (Event _, _) ] -> f true i
47+
| i :: l ->
48+
f false i;
49+
block_iter_last ~f l
50+
4251
let block_deps ~info ~vars ~tail_deps ~deps ~blocks ~fun_name pc =
4352
let block = Addr.Map.find pc blocks in
44-
List.iter_last block.body ~f:(fun is_last (i, _) ->
53+
block_iter_last block.body ~f:(fun is_last (i, _) ->
4554
match i with
4655
| Let (x, Apply { f; _ }) -> (
4756
add_var vars x;

compiler/tests-compiler/effects_continuations.ml

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -103,86 +103,79 @@ let%expect_test "test-compiler/lib-effects/test1.ml" =
103103
{|
104104

105105
function exceptions(s, cont){
106-
try{var _w_ = runtime.caml_int_of_string(s), n = _w_;}
107-
catch(_A_){
108-
var _s_ = caml_wrap_exception(_A_);
109-
if(_s_[1] !== Stdlib[7]){
106+
try{var _t_ = runtime.caml_int_of_string(s), n = _t_;}
107+
catch(_x_){
108+
var _p_ = caml_wrap_exception(_x_);
109+
if(_p_[1] !== Stdlib[7]){
110110
var raise$1 = caml_pop_trap();
111-
return raise$1(caml_maybe_attach_backtrace(_s_, 0));
111+
return raise$1(caml_maybe_attach_backtrace(_p_, 0));
112112
}
113113
var n = 0;
114114
}
115115
try{
116116
if(caml_string_equal(s, cst$0))
117117
throw caml_maybe_attach_backtrace(Stdlib[8], 1);
118-
var _v_ = 7, m = _v_;
118+
var _s_ = 7, m = _s_;
119119
}
120-
catch(_z_){
121-
var _t_ = caml_wrap_exception(_z_);
122-
if(_t_ !== Stdlib[8]){
120+
catch(_w_){
121+
var _q_ = caml_wrap_exception(_w_);
122+
if(_q_ !== Stdlib[8]){
123123
var raise$0 = caml_pop_trap();
124-
return raise$0(caml_maybe_attach_backtrace(_t_, 0));
124+
return raise$0(caml_maybe_attach_backtrace(_q_, 0));
125125
}
126126
var m = 0;
127127
}
128128
runtime.caml_push_trap
129-
(function(_y_){
130-
if(_y_ === Stdlib[8]) return cont(0);
129+
(function(_v_){
130+
if(_v_ === Stdlib[8]) return cont(0);
131131
var raise = caml_pop_trap();
132-
return raise(caml_maybe_attach_backtrace(_y_, 0));
132+
return raise(caml_maybe_attach_backtrace(_v_, 0));
133133
});
134134
if(! caml_string_equal(s, cst))
135135
return caml_cps_call2
136136
(Stdlib[79],
137137
cst_toto,
138-
function(_x_){caml_pop_trap(); return cont([0, [0, _x_, n, m]]);});
139-
var _u_ = Stdlib[8], raise = caml_pop_trap();
140-
return raise(caml_maybe_attach_backtrace(_u_, 1));
138+
function(_u_){caml_pop_trap(); return cont([0, [0, _u_, n, m]]);});
139+
var _r_ = Stdlib[8], raise = caml_pop_trap();
140+
return raise(caml_maybe_attach_backtrace(_r_, 1));
141141
}
142142
//end
143143
function cond1(b, cont){
144-
function _p_(ic){return cont([0, ic, 7]);}
144+
function _o_(ic){return cont([0, ic, 7]);}
145145
return b
146-
? caml_cps_call2
147-
(Stdlib[79], cst_toto$0, function(_q_){return _p_(_q_);})
148-
: caml_cps_call2
149-
(Stdlib[79], cst_titi, function(_r_){return _p_(_r_);});
146+
? caml_cps_call2(Stdlib[79], cst_toto$0, _o_)
147+
: caml_cps_call2(Stdlib[79], cst_titi, _o_);
150148
}
151149
//end
152150
function cond2(b, cont){
153-
function _m_(){return cont(7);}
151+
function _m_(_n_){return cont(7);}
154152
return b
155-
? caml_cps_call2(Stdlib_Printf[3], _a_, function(_n_){return _m_();})
156-
: caml_cps_call2(Stdlib_Printf[3], _b_, function(_o_){return _m_();});
153+
? caml_cps_call2(Stdlib_Printf[3], _a_, _m_)
154+
: caml_cps_call2(Stdlib_Printf[3], _b_, _m_);
157155
}
158156
//end
159157
function cond3(b, cont){
160158
var x = [0, 0];
161-
function _k_(){return cont(x[1]);}
162-
return b
163-
? (x[1] = 1, _k_())
164-
: caml_cps_call2(Stdlib_Printf[3], _c_, function(_l_){return _k_();});
159+
function _k_(_l_){return cont(x[1]);}
160+
return b ? (x[1] = 1, _k_(0)) : caml_cps_call2(Stdlib_Printf[3], _c_, _k_);
165161
}
166162
//end
167163
function loop1(b, cont){
168164
return caml_cps_call2
169165
(Stdlib[79],
170166
cst_static_examples_ml,
171167
function(ic){
172-
function _i_(){
168+
function _i_(_j_){
173169
return caml_cps_call2
174170
(Stdlib[83],
175171
ic,
176172
function(line){
177173
return b
178-
? caml_cps_call2
179-
(Stdlib[53],
180-
line,
181-
function(_j_){return caml_cps_exact_call0(_i_);})
182-
: caml_cps_exact_call0(_i_);
174+
? caml_cps_call2(Stdlib[53], line, _i_)
175+
: caml_cps_exact_call1(_i_, 0);
183176
});
184177
}
185-
return _i_();
178+
return _i_(0);
186179
});
187180
}
188181
//end
@@ -191,23 +184,15 @@ let%expect_test "test-compiler/lib-effects/test1.ml" =
191184
(Stdlib[79],
192185
cst_static_examples_ml$0,
193186
function(ic){
194-
return caml_cps_call2
195-
(Stdlib_Printf[3],
196-
_d_,
197-
function(_f_){
198-
function _g_(){
199-
return caml_cps_call2
200-
(Stdlib[83],
201-
ic,
202-
function(line){
203-
return caml_cps_call2
204-
(Stdlib[53],
205-
line,
206-
function(_h_){return caml_cps_exact_call0(_g_);});
207-
});
208-
}
209-
return _g_();
210-
});
187+
function _g_(_h_){
188+
return caml_cps_call2
189+
(Stdlib[83],
190+
ic,
191+
function(line){
192+
return caml_cps_call2(Stdlib[53], line, _g_);
193+
});
194+
}
195+
return caml_cps_call2(Stdlib_Printf[3], _d_, _g_);
211196
});
212197
}
213198
//end
@@ -216,8 +201,12 @@ let%expect_test "test-compiler/lib-effects/test1.ml" =
216201
(list_rev,
217202
_e_,
218203
function(l){
219-
var x = l;
220-
for(;;){if(! x) return cont(l); var r = x[2]; x = r;}
204+
function _f_(x){
205+
if(! x) return cont(l);
206+
var r = x[2];
207+
return caml_cps_exact_call1(_f_, r);
208+
}
209+
return _f_(l);
221210
});
222211
}
223212
//end |}]

0 commit comments

Comments
 (0)