Skip to content

Commit dfae974

Browse files
vouillonhhugo
authored andcommitted
WIP: experiment with a faster analysis
1 parent 56d1c7d commit dfae974

File tree

3 files changed

+76
-51
lines changed

3 files changed

+76
-51
lines changed

compiler/lib/global_flow.ml

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ type state =
100100
; applied_functions : (Var.t * Var.t, unit) Hashtbl.t
101101
(* Functions that have been already considered at a call site.
102102
This is to avoid repeated computations *)
103+
; fast : bool
103104
}
104105

105106
let add_var st x = Var.ISet.add st.vars x
@@ -126,7 +127,8 @@ let add_assign_def st x y =
126127
let add_param_def st x =
127128
add_var st x;
128129
let idx = Var.idx x in
129-
assert (is_undefined st.defs.(idx))
130+
assert (is_undefined st.defs.(idx));
131+
if st.fast then st.defs.(idx) <- Phi { known = Var.Set.empty; others = true }
130132

131133
let rec arg_deps st ?ignore params args =
132134
match params, args with
@@ -155,6 +157,12 @@ let expr_deps blocks st x e =
155157
(* The analysis knowns about these primitives, and will compute
156158
an approximation of the value they return based on an
157159
approximation of their arguments *)
160+
(if st.fast
161+
then
162+
match l with
163+
| Pv x :: _ -> do_escape st Escape x
164+
| Pc _ :: _ -> ()
165+
| [] -> assert false);
158166
List.iter
159167
~f:(fun a ->
160168
match a with
@@ -204,12 +212,15 @@ let expr_deps blocks st x e =
204212
(* If [f] is obviously a function, we can add appropriate
205213
dependencies right now. This speeds up the analysis
206214
significantly. *)
207-
match st.defs.(Var.idx f) with
208-
| Expr (Closure (params, _)) when List.length args = List.length params ->
209-
Hashtbl.add st.applied_functions (x, f) ();
210-
List.iter2 ~f:(fun p a -> add_assign_def st p a) params args;
211-
Var.Set.iter (fun y -> add_dep st x y) (Var.Map.find f st.return_values)
212-
| _ -> ())
215+
if false
216+
then
217+
match st.defs.(Var.idx f) with
218+
| Expr (Closure (params, _)) when List.length args = List.length params ->
219+
Hashtbl.add st.applied_functions (x, f) ();
220+
if not st.fast
221+
then List.iter2 ~f:(fun p a -> add_assign_def st p a) params args;
222+
Var.Set.iter (fun y -> add_dep st x y) (Var.Map.find f st.return_values)
223+
| _ -> ())
213224
| Closure (l, cont) ->
214225
List.iter l ~f:(fun x -> add_param_def st x);
215226
cont_deps blocks st cont
@@ -243,17 +254,19 @@ let program_deps st { blocks; _ } =
243254
~f:(fun i (pc, _) ->
244255
Hashtbl.replace h pc (i :: (try Hashtbl.find h pc with Not_found -> [])))
245256
a2;
246-
Hashtbl.iter
247-
(fun pc tags ->
248-
let block = Addr.Map.find pc blocks in
249-
List.iter
250-
~f:(fun i ->
251-
match i with
252-
| Let (y, Field (x', _)) when Var.equal x x' ->
253-
Hashtbl.add st.known_cases y tags
254-
| _ -> ())
255-
block.body)
256-
h
257+
if not st.fast
258+
then
259+
Hashtbl.iter
260+
(fun pc tags ->
261+
let block = Addr.Map.find pc blocks in
262+
List.iter
263+
~f:(fun i ->
264+
match i with
265+
| Let (y, Field (x', _)) when Var.equal x x' ->
266+
Hashtbl.add st.known_cases y tags
267+
| _ -> ())
268+
block.body)
269+
h
257270
| Pushtrap (cont, x, cont_h, _) ->
258271
add_var st x;
259272
st.defs.(Var.idx x) <- Phi { known = Var.Set.empty; others = true };
@@ -406,31 +419,34 @@ let propagate st ~update approx x =
406419
| Top -> Top)
407420
| Prim (Extern "caml_check_bound", [ Pv y; _ ]) -> Var.Tbl.get approx y
408421
| Prim ((Array_get | Extern "caml_array_unsafe_get"), [ Pv y; _ ]) -> (
409-
match Var.Tbl.get approx y with
410-
| Values { known; others } ->
411-
Domain.join_set
412-
~update
413-
~st
414-
~approx
415-
~others
416-
(fun z ->
417-
match st.defs.(Var.idx z) with
418-
| Expr (Block (_, lst, _)) ->
419-
Array.iter ~f:(fun t -> add_dep st x t) lst;
420-
let a =
421-
Array.fold_left
422-
~f:(fun acc t ->
423-
Domain.join ~update ~st ~approx (Var.Tbl.get approx t) acc)
424-
~init:Domain.bot
425-
lst
426-
in
427-
if st.possibly_mutable.(Var.idx z)
428-
then Domain.join ~update ~st ~approx Domain.others a
429-
else a
430-
| Expr (Closure _) -> Domain.bot
431-
| Phi _ | Expr _ -> assert false)
432-
known
433-
| Top -> Top)
422+
if st.fast
423+
then Domain.others
424+
else
425+
match Var.Tbl.get approx y with
426+
| Values { known; others } ->
427+
Domain.join_set
428+
~update
429+
~st
430+
~approx
431+
~others
432+
(fun z ->
433+
match st.defs.(Var.idx z) with
434+
| Expr (Block (_, lst, _)) ->
435+
Array.iter ~f:(fun t -> add_dep st x t) lst;
436+
let a =
437+
Array.fold_left
438+
~f:(fun acc t ->
439+
Domain.join ~update ~st ~approx (Var.Tbl.get approx t) acc)
440+
~init:Domain.bot
441+
lst
442+
in
443+
if st.possibly_mutable.(Var.idx z)
444+
then Domain.join ~update ~st ~approx Domain.others a
445+
else a
446+
| Expr (Closure _) -> Domain.bot
447+
| Phi _ | Expr _ -> assert false)
448+
known
449+
| Top -> Top)
434450
| Prim (Array_get, _) -> Domain.others
435451
| Prim ((Vectlength | Not | IsInt | Eq | Neq | Lt | Le | Ult), _) ->
436452
(* The result of these primitive is neither a function nor a
@@ -457,12 +473,14 @@ let propagate st ~update approx x =
457473
if not (Hashtbl.mem st.applied_functions (x, g))
458474
then (
459475
Hashtbl.add st.applied_functions (x, g) ();
460-
List.iter2
461-
~f:(fun p a ->
462-
add_assign_def st p a;
463-
update ~children:false p)
464-
params
465-
args;
476+
if not st.fast
477+
then
478+
List.iter2
479+
~f:(fun p a ->
480+
add_assign_def st p a;
481+
update ~children:false p)
482+
params
483+
args;
466484
Var.Set.iter
467485
(fun y -> add_dep st x y)
468486
(Var.Map.find g st.return_values));
@@ -550,6 +568,7 @@ let f p =
550568
; possibly_mutable
551569
; known_cases = Hashtbl.create 16
552570
; applied_functions = Hashtbl.create 16
571+
; fast = not (Config.Flag.effects ())
553572
}
554573
in
555574
program_deps st p;

compiler/lib/specialize.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,16 @@ let function_arity info x =
4949
in
5050
arity info x []
5151

52+
let count = ref 0
53+
5254
let specialize_instr function_arity (acc, free_pc, extra) i =
5355
match i with
5456
| Let (x, Apply { f; args; exact }) when (not exact) && Config.Flag.optcall () -> (
5557
let n' = List.length args in
5658
match function_arity f with
5759
| None -> i :: acc, free_pc, extra
5860
| Some n when n = n' ->
61+
incr count;
5962
Let (x, Apply { f; args; exact = true }) :: acc, free_pc, extra
6063
| Some n when n < n' ->
6164
let v = Code.Var.fresh () in
@@ -84,6 +87,7 @@ let specialize_instr function_arity (acc, free_pc, extra) i =
8487
| _ -> i :: acc, free_pc, extra
8588

8689
let specialize_instrs ~function_arity p =
90+
count := 0;
8791
let blocks, free_pc =
8892
Addr.Map.fold
8993
(fun pc block (blocks, free_pc) ->
@@ -99,6 +103,8 @@ let specialize_instrs ~function_arity p =
99103
p.blocks
100104
(Addr.Map.empty, p.free_pc)
101105
in
106+
(*
107+
Format.eprintf "EXACT: %d@." !count;*)
102108
{ p with blocks; free_pc }
103109

104110
let f = specialize_instrs

compiler/tests-compiler/direct_calls.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ let%expect_test "direct calls without --enable effects" =
5757
[%expect
5858
{|
5959
function test1(param){
60-
function f(g, x){return g(x);}
60+
function f(g, x){return caml_call1(g, x);}
6161
var _d_ = 7;
6262
f(function(x){return x + 1 | 0;}, _d_);
6363
var _e_ = 4.;
@@ -66,7 +66,7 @@ let%expect_test "direct calls without --enable effects" =
6666
}
6767
//end
6868
function test2(param){
69-
function f(g, x){return g(x);}
69+
function f(g, x){return caml_call1(g, x);}
7070
var _c_ = 7;
7171
f(function(x){return x + 1 | 0;}, _c_);
7272
f(function(x){return caml_call2(Stdlib[28], x, cst_a$0);}, cst_a);

0 commit comments

Comments
 (0)