Skip to content

Commit ee229f5

Browse files
committed
Compiler: propagate arity across unit boundary (WIP)
1 parent 659945d commit ee229f5

24 files changed

+2228
-2826
lines changed

compiler/lib/code.ml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ type expr =
339339
; args : Var.t list
340340
; exact : bool
341341
}
342-
| Block of int * Var.t array * array_or_not
342+
| Block of int * Var.t array * array_or_not * bool
343343
| Field of Var.t * int
344344
| Closure of Var.t list * cont
345345
| Constant of constant
@@ -479,8 +479,18 @@ module Print = struct
479479
if exact
480480
then Format.fprintf f "%a!(%a)" Var.print g var_list args
481481
else Format.fprintf f "%a(%a)" Var.print g var_list args
482-
| Block (t, a, _) ->
483-
Format.fprintf f "{tag=%d" t;
482+
| Block (t, a, k, imm) ->
483+
Format.fprintf
484+
f
485+
"{%s%s:tag=%d"
486+
(match imm with
487+
| true -> "Imm"
488+
| false -> "")
489+
(match k with
490+
| Array -> "A"
491+
| NotArray -> "NA"
492+
| Unknown -> "U")
493+
t;
484494
for i = 0 to Array.length a - 1 do
485495
Format.fprintf f "; %d = %a" i Var.print a.(i)
486496
done;
@@ -732,7 +742,7 @@ let invariant { blocks; start; _ } =
732742
in
733743
let check_expr = function
734744
| Apply _ -> ()
735-
| Block (_, _, _) -> ()
745+
| Block (_, _, _, _) -> ()
736746
| Field (_, _) -> ()
737747
| Closure (l, cont) ->
738748
List.iter l ~f:define;

compiler/lib/code.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ type expr =
186186
; args : Var.t list
187187
; exact : bool (* if true, then # of arguments = # of parameters *)
188188
}
189-
| Block of int * Var.t array * array_or_not
189+
| Block of int * Var.t array * array_or_not * bool
190190
| Field of Var.t * int
191191
| Closure of Var.t list * cont
192192
| Constant of constant

compiler/lib/deadcode.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ and mark_expr st e =
7070
| Apply { f; args; _ } ->
7171
mark_var st f;
7272
List.iter args ~f:(fun x -> mark_var st x)
73-
| Block (_, a, _) -> Array.iter a ~f:(fun x -> mark_var st x)
73+
| Block (_, a, _, _) -> Array.iter a ~f:(fun x -> mark_var st x)
7474
| Field (x, _) -> mark_var st x
7575
| Closure (_, (pc, _)) -> mark_reachable st pc
7676
| Special _ -> ()

compiler/lib/driver.ml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,29 @@ if (typeof module === 'object' && module.exports) {
625625
if times () then Format.eprintf " optimizing: %a@." Timer.print t;
626626
js
627627

628+
let collects_shapes p =
629+
let _, info = Flow.f p in
630+
let l = ref StringMap.empty in
631+
Code.Addr.Map.iter
632+
(fun _ block ->
633+
List.iter block.Code.body ~f:(fun (i, _) ->
634+
match i with
635+
| Code.Let
636+
( _
637+
, Prim
638+
( Extern "caml_register_global"
639+
, [ _code; Pv block; Pc (NativeString name) ] ) ) ->
640+
let shape = Flow.the_shape_of info block in
641+
let name =
642+
match name with
643+
| Byte s -> s
644+
| Utf (Utf8 s) -> s
645+
in
646+
l := StringMap.add name shape !l
647+
| _ -> ()))
648+
p.blocks;
649+
!l
650+
628651
let configure formatter =
629652
let pretty = Config.Flag.pretty () in
630653
Pretty_print.set_compact formatter (not pretty);
@@ -663,7 +686,15 @@ let full ~standalone ~wrap_with_fun ~profile ~linkall ~source_map formatter d p
663686
in
664687
if times () then Format.eprintf "Start Optimizing...@.";
665688
let t = Timer.make () in
666-
let r = opt p in
689+
let (((prog, _), _) as r) = opt p in
690+
let shapes = collects_shapes prog in
691+
StringMap.iter
692+
(fun name shape ->
693+
Shape.set_shape ~name shape;
694+
Pretty_print.string
695+
formatter
696+
(Printf.sprintf "//# shape: %s:%s\n" name (Shape.to_string shape)))
697+
shapes;
667698
let () = if times () then Format.eprintf " optimizations : %a@." Timer.print t in
668699
emit r
669700

compiler/lib/duplicate.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let expr s e =
2626
| Constant _ -> e
2727
| Apply { f; args; exact } ->
2828
Apply { f = s f; args = List.map args ~f:(fun x -> s x); exact }
29-
| Block (n, a, k) -> Block (n, Array.map a ~f:(fun x -> s x), k)
29+
| Block (n, a, k, imm) -> Block (n, Array.map a ~f:(fun x -> s x), k, imm)
3030
| Field (x, n) -> Field (s x, n)
3131
| Closure _ -> failwith "Inlining/Duplicating closure is currenly not supported"
3232
| Special x -> Special x

compiler/lib/eval.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ let is_int info x =
177177
(fun x ->
178178
match Flow.Info.def info x with
179179
| Some (Constant (Int _)) -> Y
180-
| Some (Block (_, _, _) | Constant _) -> N
180+
| Some (Block (_, _, _, _) | Constant _) -> N
181181
| None | Some _ -> Unknown)
182182
Unknown
183183
(fun u v ->
@@ -196,7 +196,7 @@ let the_tag_of info x get =
196196
info
197197
(fun x ->
198198
match Flow.Info.def info x with
199-
| Some (Block (j, _, _)) ->
199+
| Some (Block (j, _, _, _)) ->
200200
if Flow.Info.possibly_mutable info x then None else get j
201201
| Some (Constant (Tuple (j, _, _))) -> get j
202202
| None | Some _ -> None)
@@ -278,7 +278,7 @@ let eval_instr info ((x, loc) as i) =
278278
| Let (x, Prim (Extern "caml_sys_const_backend_type", [ _ ])) ->
279279
let jsoo = Code.Var.fresh () in
280280
[ Let (jsoo, Constant (String "js_of_ocaml")), noloc
281-
; Let (x, Block (0, [| jsoo |], NotArray)), loc
281+
; Let (x, Block (0, [| jsoo |], NotArray, true)), loc
282282
]
283283
| Let (_, Prim (Extern ("%resume" | "%perform" | "%reperform"), _)) ->
284284
[ i ] (* We need that the arguments to this primitives remain variables *)
@@ -338,7 +338,7 @@ let the_cond_of info x =
338338
| NativeString _
339339
| Float_array _
340340
| Int64 _ )) -> Non_zero
341-
| Some (Block (_, _, _)) -> Non_zero
341+
| Some (Block (_, _, _, _)) -> Non_zero
342342
| Some (Field _ | Closure _ | Prim _ | Apply _ | Special _) -> Unknown
343343
| None -> Unknown)
344344
Unknown
@@ -381,7 +381,7 @@ let rec do_not_raise pc visited blocks =
381381
| Array_set (_, _, _) | Offset_ref (_, _) | Set_field (_, _, _) | Assign _ -> ()
382382
| Let (_, e) -> (
383383
match e with
384-
| Block (_, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
384+
| Block (_, _, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
385385
| Apply _ -> raise May_raise
386386
| Special _ -> ()
387387
| Prim (Extern name, _) when Primitive.is_pure name -> ()

compiler/lib/flow.ml

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ let expr_deps blocks vars deps defs x e =
103103
| Closure (l, cont) ->
104104
List.iter l ~f:(fun x -> add_param_def vars defs x);
105105
cont_deps blocks vars deps defs cont
106-
| Block (_, a, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
106+
| Block (_, a, _, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
107107
| Field (y, _) -> add_dep deps x y
108108

109109
let program_deps { blocks; _ } =
@@ -152,7 +152,7 @@ let propagate1 deps defs st x =
152152
var_set_lift
153153
(fun z ->
154154
match defs.(Var.idx z) with
155-
| Expr (Block (_, a, _)) when n < Array.length a ->
155+
| Expr (Block (_, a, _, _)) when n < Array.length a ->
156156
let t = a.(n) in
157157
add_dep deps x t;
158158
Var.Tbl.get st t
@@ -186,15 +186,17 @@ type mutability_state =
186186
; possibly_mutable : Code.Var.ISet.t
187187
}
188188

189-
let rec block_escape st x =
189+
let rec block_escape st ?(immutable = false) x =
190190
Var.Set.iter
191191
(fun y ->
192192
if not (Code.Var.ISet.mem st.may_escape y)
193193
then (
194194
Code.Var.ISet.add st.may_escape y;
195-
Code.Var.ISet.add st.possibly_mutable y;
195+
if not immutable then Code.Var.ISet.add st.possibly_mutable y;
196+
196197
match st.defs.(Var.idx y) with
197-
| Expr (Block (_, l, _)) -> Array.iter l ~f:(fun z -> block_escape st z)
198+
| Expr (Block (_, l, _, immutable)) ->
199+
Array.iter l ~f:(fun z -> block_escape st ~immutable z)
198200
| _ -> ()))
199201
(Var.Tbl.get st.known_origins x)
200202

@@ -226,15 +228,18 @@ let expr_escape st _x e =
226228
| Pv v, `Shallow_const -> (
227229
match st.defs.(Var.idx v) with
228230
| Expr (Constant (Tuple _)) -> ()
229-
| Expr (Block (_, a, _)) -> Array.iter a ~f:(fun x -> block_escape st x)
231+
| Expr (Block (_, a, _, true)) ->
232+
Array.iter a ~f:(fun x -> block_escape st ~immutable:true x)
233+
| Expr (Block (_, a, _, false)) ->
234+
Array.iter a ~f:(fun x -> block_escape st x)
230235
| _ -> block_escape st v)
231236
| Pv v, `Object_literal -> (
232237
match st.defs.(Var.idx v) with
233238
| Expr (Constant (Tuple _)) -> ()
234-
| Expr (Block (_, a, _)) ->
239+
| Expr (Block (_, a, _, _)) ->
235240
Array.iter a ~f:(fun x ->
236241
match st.defs.(Var.idx x) with
237-
| Expr (Block (_, [| _k; v |], _)) -> block_escape st v
242+
| Expr (Block (_, [| _k; v |], _, _)) -> block_escape st v
238243
| Expr (Constant _) -> ()
239244
| _ -> block_escape st x)
240245
| _ -> block_escape st v)
@@ -282,7 +287,7 @@ let propagate2 ?(skip_param = false) defs known_origins possibly_mutable st x =
282287
|| Var.Set.exists
283288
(fun z ->
284289
match defs.(Var.idx z) with
285-
| Expr (Block (_, a, _)) ->
290+
| Expr (Block (_, a, _, _)) ->
286291
n >= Array.length a
287292
|| Var.ISet.mem possibly_mutable z
288293
|| Var.Tbl.get st a.(n)
@@ -382,7 +387,7 @@ let direct_approx (info : Info.t) x =
382387
then None
383388
else
384389
match info.info_defs.(Var.idx z) with
385-
| Expr (Block (_, a, _)) when n < Array.length a -> Some a.(n)
390+
| Expr (Block (_, a, _, _)) when n < Array.length a -> Some a.(n)
386391
| _ -> None)
387392
None
388393
(fun u v ->
@@ -392,6 +397,29 @@ let direct_approx (info : Info.t) x =
392397
y
393398
| _ -> None
394399

400+
let rec the_shape_of info x =
401+
get_approx
402+
info
403+
(fun x ->
404+
if Var.ISet.mem info.info_possibly_mutable x
405+
then Shape.Bot "possibly_mutable"
406+
else
407+
match info.info_defs.(Var.idx x) with
408+
| Expr (Block (_, a, _, true)) ->
409+
Shape.Block (List.map ~f:(the_shape_of info) (Array.to_list a))
410+
| Expr (Closure (l, _)) ->
411+
Shape.Function { arity = List.length l; pure = false; res = Bot "unk" }
412+
| Expr (Special (Alias_prim name)) -> (
413+
try
414+
let arity = Primitive.arity name in
415+
let pure = Primitive.is_pure name in
416+
Shape.Function { arity; pure; res = Bot "unk" }
417+
with _ -> Bot "other")
418+
| _ -> Shape.Bot "other")
419+
(Bot "init")
420+
(fun _u _v -> Shape.Bot "merge")
421+
x
422+
395423
let build_subst (info : Info.t) vars =
396424
let nv = Var.count () in
397425
let subst = Array.init nv ~f:(fun i -> Var.of_idx i) in

compiler/lib/flow.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ val the_native_string_of : Info.t -> Code.prim_arg -> Code.Native_string.t optio
6060

6161
val the_int : Info.t -> Code.prim_arg -> int32 option
6262

63+
val the_shape_of : Info.t -> Code.Var.t -> Shape.t
64+
6365
val f : ?skip_param:bool -> Code.program -> Code.program * Info.t

compiler/lib/freevars.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ let iter_expr_free_vars f e =
3333
| Apply { f = x; args; _ } ->
3434
f x;
3535
List.iter ~f args
36-
| Block (_, a, _) -> Array.iter ~f a
36+
| Block (_, a, _, _) -> Array.iter ~f a
3737
| Field (x, _) -> f x
3838
| Closure _ -> ()
3939
| Special _ -> ()

compiler/lib/generate.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list =
10421042
let prop = or_p prop prop' in
10431043
let e = apply_fun ctx f args exact cps loc in
10441044
(e, prop, queue), []
1045-
| Block (tag, a, array_or_not) ->
1045+
| Block (tag, a, array_or_not, _imm) ->
10461046
let contents, prop, queue =
10471047
List.fold_right
10481048
~f:(fun x (args, prop, queue) ->

0 commit comments

Comments
 (0)