Skip to content

Commit 9822fc7

Browse files
committed
More exact calls
1 parent 1ec84a6 commit 9822fc7

File tree

5 files changed

+73
-33
lines changed

5 files changed

+73
-33
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

0 commit comments

Comments
 (0)