Skip to content

Commit 74f2fa8

Browse files
committed
WIP: experiment with a faster analysis
1 parent 22cfc46 commit 74f2fa8

File tree

3 files changed

+73
-47
lines changed

3 files changed

+73
-47
lines changed

compiler/lib/global_flow.ml

Lines changed: 60 additions & 44 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
@@ -207,7 +215,7 @@ let expr_deps blocks st x e =
207215
match st.defs.(Var.idx f) with
208216
| Expr (Closure (params, _)) when List.length args = List.length params ->
209217
Hashtbl.add st.applied_functions (x, f) ();
210-
List.iter2 ~f:(fun p a -> add_assign_def st p a) params args;
218+
if not st.fast then List.iter2 ~f:(fun p a -> add_assign_def st p a) params args;
211219
Var.Set.iter (fun y -> add_dep st x y) (Var.Map.find f st.return_values)
212220
| _ -> ())
213221
| Closure (l, cont) ->
@@ -243,17 +251,19 @@ let program_deps st { blocks; _ } =
243251
~f:(fun i (pc, _) ->
244252
Hashtbl.replace h pc (i :: (try Hashtbl.find h pc with Not_found -> [])))
245253
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
254+
if not st.fast
255+
then
256+
Hashtbl.iter
257+
(fun pc tags ->
258+
let block = Addr.Map.find pc blocks in
259+
List.iter
260+
~f:(fun i ->
261+
match i with
262+
| Let (y, Field (x', _)) when Var.equal x x' ->
263+
Hashtbl.add st.known_cases y tags
264+
| _ -> ())
265+
block.body)
266+
h
257267
| Pushtrap (cont, x, cont_h, _) ->
258268
add_var st x;
259269
st.defs.(Var.idx x) <- Phi { known = Var.Set.empty; others = true };
@@ -406,31 +416,34 @@ let propagate st ~update approx x =
406416
| Top -> Top)
407417
| Prim (Extern "caml_check_bound", [ Pv y; _ ]) -> Var.Tbl.get approx y
408418
| 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)
419+
if st.fast
420+
then Domain.others
421+
else
422+
match Var.Tbl.get approx y with
423+
| Values { known; others } ->
424+
Domain.join_set
425+
~update
426+
~st
427+
~approx
428+
~others
429+
(fun z ->
430+
match st.defs.(Var.idx z) with
431+
| Expr (Block (_, lst, _)) ->
432+
Array.iter ~f:(fun t -> add_dep st x t) lst;
433+
let a =
434+
Array.fold_left
435+
~f:(fun acc t ->
436+
Domain.join ~update ~st ~approx (Var.Tbl.get approx t) acc)
437+
~init:Domain.bot
438+
lst
439+
in
440+
if st.possibly_mutable.(Var.idx z)
441+
then Domain.join ~update ~st ~approx Domain.others a
442+
else a
443+
| Expr (Closure _) -> Domain.bot
444+
| Phi _ | Expr _ -> assert false)
445+
known
446+
| Top -> Top)
434447
| Prim (Array_get, _) -> assert false
435448
| Prim ((Vectlength | Not | IsInt | Eq | Neq | Lt | Le | Ult), _) ->
436449
(* The result of these primitive is neither a function nor a
@@ -457,12 +470,14 @@ let propagate st ~update approx x =
457470
if not (Hashtbl.mem st.applied_functions (x, g))
458471
then (
459472
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;
473+
if not st.fast
474+
then
475+
List.iter2
476+
~f:(fun p a ->
477+
add_assign_def st p a;
478+
update ~children:false p)
479+
params
480+
args;
466481
Var.Set.iter
467482
(fun y -> add_dep st x y)
468483
(Var.Map.find g st.return_values));
@@ -550,6 +565,7 @@ let f p =
550565
; possibly_mutable
551566
; known_cases = Hashtbl.create 16
552567
; applied_functions = Hashtbl.create 16
568+
; fast = not (Config.Flag.effects ())
553569
}
554570
in
555571
program_deps st p;

compiler/lib/specialize.ml

Lines changed: 11 additions & 1 deletion
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,12 @@ 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

104-
let f = specialize_instrs
110+
let f ~function_arity p =
111+
let t = Timer.make () in
112+
let p = specialize_instrs ~function_arity p in
113+
if Debug.find "times" () then Format.eprintf " specialize: %a@." Timer.print t;
114+
p

compiler/tests-compiler/direct_calls.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ 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.;
6464
f(function(x){return x * 2.},_e_);
6565
return 0}
6666
//end
6767
function test2(param)
68-
{function f(g,x){return g(x)}
68+
{function f(g,x){return caml_call1(g,x)}
6969
var _c_=7;
7070
f(function(x){return x + 1 | 0},_c_);
7171
f(function(x){return caml_call2(Stdlib[28],x,cst_a$0)},cst_a);

0 commit comments

Comments
 (0)