Skip to content

Commit 9b152a0

Browse files
committed
More exact calls
1 parent bc2adbe commit 9b152a0

File tree

7 files changed

+80
-41
lines changed

7 files changed

+80
-41
lines changed

compiler/lib/driver.ml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ let inline p =
4949

5050
let specialize_1 (p, info) =
5151
if debug () then Format.eprintf "Specialize...@.";
52-
Specialize.f info p
52+
Specialize.f ~function_arity:(fun f -> Specialize.function_arity info f) p
5353

5454
let specialize_js (p, info) =
5555
if debug () then Format.eprintf "Specialize js...@.";
@@ -91,6 +91,13 @@ let effects p =
9191
p |> Deadcode.f +> Effects.f +> map_fst Lambda_lifting.f)
9292
else p, (Code.Var.Set.empty : Effects.cps_calls)
9393

94+
let exact_calls p =
95+
if not (Config.Flag.effects ())
96+
then
97+
let info = Global_flow.f p in
98+
Specialize.f ~function_arity:(fun f -> Global_flow.function_arity info f) p
99+
else p
100+
94101
let print p =
95102
if debug () then Code.Print.program (fun _ _ -> "") p;
96103
p
@@ -565,7 +572,11 @@ let full
565572
p =
566573
let exported_runtime = not standalone in
567574
let opt =
568-
specialize_js_once +> profile +> effects +> map_fst (Generate_closure.f +> deadcode')
575+
specialize_js_once
576+
+> profile
577+
+> exact_calls
578+
+> effects
579+
+> map_fst (Generate_closure.f +> deadcode')
569580
in
570581
let emit =
571582
generate d ~exported_runtime ~wrap_with_fun ~warn_on_unhandled_effect:standalone

compiler/lib/global_flow.ml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,25 @@ let exact_call info f n =
621621
| Expr (Block _) -> true
622622
| Expr _ | Phi _ -> assert false)
623623
known
624+
625+
let function_arity info f =
626+
match Var.Tbl.get info.info_approximation f with
627+
| Top | Values { others = true; _ } -> None
628+
| Values { known; others = false } -> (
629+
match
630+
Var.Set.fold
631+
(fun g acc ->
632+
match info.info_defs.(Var.idx g) with
633+
| Expr (Closure (params, _)) -> (
634+
let n = List.length params in
635+
match acc with
636+
| None -> Some (Some n)
637+
| Some (Some n') when n <> n' -> Some None
638+
| Some _ -> acc)
639+
| Expr (Block _) -> acc
640+
| Expr _ | Phi _ -> assert false)
641+
known
642+
None
643+
with
644+
| Some v -> v
645+
| None -> None)

compiler/lib/global_flow.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ type info =
4040
val f : Code.program -> info
4141

4242
val exact_call : info -> Var.t -> int -> bool
43+
44+
val function_arity : info -> Var.t -> int option

compiler/lib/specialize.ml

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,39 @@ open! Stdlib
2121
open Code
2222
open Flow
2323

24-
let rec function_cardinality info x acc =
25-
get_approx
26-
info
27-
(fun x ->
28-
match info.info_defs.(Var.idx x) with
29-
| Expr (Closure (l, _)) -> Some (List.length l)
30-
| Expr (Prim (Extern "%closure", [ Pc (String prim) ])) -> (
31-
try Some (Primitive.arity prim) with Not_found -> None)
32-
| Expr (Apply { f; args; _ }) -> (
33-
if List.mem f ~set:acc
34-
then None
35-
else
36-
match function_cardinality info f (f :: acc) with
37-
| Some n ->
38-
let diff = n - List.length args in
39-
if diff > 0 then Some diff else None
40-
| None -> None)
41-
| _ -> None)
42-
None
43-
(fun u v ->
44-
match u, v with
45-
| Some n, Some m when n = m -> u
46-
| _ -> None)
47-
x
24+
let function_arity info x =
25+
let rec arity info x acc =
26+
get_approx
27+
info
28+
(fun x ->
29+
match info.info_defs.(Var.idx x) with
30+
| Expr (Closure (l, _)) -> Some (List.length l)
31+
| Expr (Prim (Extern "%closure", [ Pc (String prim) ])) -> (
32+
try Some (Primitive.arity prim) with Not_found -> None)
33+
| Expr (Apply { f; args; _ }) -> (
34+
if List.mem f ~set:acc
35+
then None
36+
else
37+
match arity info f (f :: acc) with
38+
| Some n ->
39+
let diff = n - List.length args in
40+
if diff > 0 then Some diff else None
41+
| None -> None)
42+
| _ -> None)
43+
None
44+
(fun u v ->
45+
match u, v with
46+
| Some n, Some m when n = m -> u
47+
| _ -> None)
48+
x
49+
in
50+
arity info x []
4851

49-
let specialize_instr info (acc, free_pc, extra) i =
52+
let specialize_instr function_arity (acc, free_pc, extra) i =
5053
match i with
51-
| Let (x, Apply { f; args; _ }) when Config.Flag.optcall () -> (
54+
| Let (x, Apply { f; args; exact }) when (not exact) && Config.Flag.optcall () -> (
5255
let n' = List.length args in
53-
match function_cardinality info f [] with
56+
match function_arity f with
5457
| None -> i :: acc, free_pc, extra
5558
| Some n when n = n' ->
5659
Let (x, Apply { f; args; exact = true }) :: acc, free_pc, extra
@@ -80,13 +83,13 @@ let specialize_instr info (acc, free_pc, extra) i =
8083
| _ -> i :: acc, free_pc, extra)
8184
| _ -> i :: acc, free_pc, extra
8285

83-
let specialize_instrs info p =
86+
let specialize_instrs ~function_arity p =
8487
let blocks, free_pc =
8588
Addr.Map.fold
8689
(fun pc block (blocks, free_pc) ->
8790
let body, free_pc, extra =
8891
List.fold_right block.body ~init:([], free_pc, []) ~f:(fun i acc ->
89-
specialize_instr info acc i)
92+
specialize_instr function_arity acc i)
9093
in
9194
let blocks =
9295
List.fold_left extra ~init:blocks ~f:(fun blocks (pc, b) ->
@@ -98,4 +101,4 @@ let specialize_instrs info p =
98101
in
99102
{ p with blocks; free_pc }
100103

101-
let f info p = specialize_instrs info p
104+
let f = specialize_instrs

compiler/lib/specialize.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1919
*)
2020

21-
val f : Flow.info -> Code.program -> Code.program
21+
val function_arity : Flow.info -> Code.Var.t -> int option
22+
23+
val f : function_arity:(Code.Var.t -> int option) -> Code.program -> Code.program

compiler/tests-compiler/direct_calls.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,31 @@ let%expect_test "direct calls without --enable effects" =
5757
[%expect
5858
{|
5959
function test1(param)
60-
{function f(g,x){return caml_call1(g,x)}
60+
{function f(g,x){return 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 caml_call1(g,x)}
68+
{function f(g,x){return 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);
7272
return 0}
7373
//end
7474
function test3(x)
7575
{function F(symbol){function f(x){return x + 1 | 0}return [0,f]}
76-
var M1=F([0]),M2=F([0]),_b_=caml_call1(M2[1],2);
77-
return [0,caml_call1(M1[1],1),_b_]}
76+
var M1=F([0]),M2=F([0]),_b_=M2[1].call(null,2);
77+
return [0,M1[1].call(null,1),_b_]}
7878
//end
7979
function test4(x)
8080
{function F(symbol)
8181
{function f(x){return caml_call2(Stdlib_Printf[2],_a_,x)}return [0,f]}
8282
var M1=F([0]),M2=F([0]);
83-
caml_call1(M1[1],1);
84-
return caml_call1(M2[1],2)}
83+
M1[1].call(null,1);
84+
return M2[1].call(null,2)}
8585
//end |}]
8686

8787
let%expect_test "direct calls with --enable effects" =

compiler/tests-compiler/gh1007.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,7 @@ let () = M.run ()
545545
even=closures$0[1],
546546
param$0=even(i);
547547
for(;;)
548-
{if(759635106 > param$0[1])
549-
{var f=param$0[2],param$0=caml_call1(f,0);continue}
548+
{if(759635106 > param$0[1]){var f=param$0[2],param$0=f(0);continue}
550549
var _g_=i + 1 | 0;
551550
if(4 !== i){var i=_g_;continue a}
552551
var

0 commit comments

Comments
 (0)