Skip to content

Commit d5a8ad5

Browse files
committed
Compiler: Specialze.f use shapes to compute arity
1 parent ea0283b commit d5a8ad5

File tree

3 files changed

+52
-49
lines changed

3 files changed

+52
-49
lines changed

compiler/lib/driver.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ let specialize_1 (p, info) =
6464
if debug () then Format.eprintf "Specialize...@.";
6565
let return_values = Code.Var.Map.empty in
6666
Specialize.f
67-
~function_arity:(fun f -> Specialize.function_arity ~return_values info f)
67+
~shape:(fun f -> Flow.the_shape_of ~return_values ~pure:Pure_fun.empty info f)
6868
~update_def:(fun x expr -> Flow.Info.update_def info x expr)
6969
p
7070

@@ -140,7 +140,10 @@ let exact_calls (profile : Profile.t) ~deadcode_sentinal p =
140140
else p
141141
in
142142
Specialize.f
143-
~function_arity:(fun f -> Global_flow.function_arity info f)
143+
~shape:(fun f ->
144+
match Global_flow.function_arity info f with
145+
| None -> Shape.Top
146+
| Some arity -> Shape.Function { arity; pure = false; res = Top })
144147
~update_def:(fun x expr -> Global_flow.update_def info x expr)
145148
p
146149
| `Cps | `Double_translation -> p

compiler/lib/specialize.ml

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ let stats = Debug.find "stats"
2626

2727
let debug_stats = Debug.find "stats-debug"
2828

29-
let function_arity ~return_values info x =
30-
match Flow.the_shape_of ~return_values ~pure:Pure_fun.empty info x with
31-
| Top | Block _ -> None
32-
| Function { arity; _ } -> Some arity
33-
3429
let add_event loc instrs =
3530
match loc with
3631
| Some loc -> Event loc :: instrs
@@ -40,83 +35,91 @@ let unknown_apply = function
4035
| Let (_, Apply { f = _; args = _; exact = false }) -> true
4136
| _ -> false
4237

43-
let specialize_apply opt_count function_arity update_def ((acc, free_pc, extra), loc) i =
44-
match i with
45-
| Let (x, Apply { f; args; exact = false }) -> (
46-
let n' = List.length args in
47-
match function_arity f with
48-
| None -> i :: acc, free_pc, extra
49-
| Some n when n = n' ->
50-
incr opt_count;
51-
Let (x, Apply { f; args; exact = true }) :: acc, free_pc, extra
52-
| Some n when n < n' ->
38+
let specialize_apply opt_count shape update_def =
39+
let rec loop x f args shape loc (acc, free_pc, extra) =
40+
match (shape : Shape.t) with
41+
| Top | Block _ -> Let (x, Apply { f; args; exact = false }) :: acc, free_pc, extra
42+
| Function { arity; res; _ } ->
43+
let nargs = List.length args in
44+
if arity = nargs
45+
then (
5346
incr opt_count;
54-
let v = Code.Var.fresh () in
55-
let args, rest = List.take n args in
56-
( (* Reversed *)
57-
Let (x, Apply { f = v; args = rest; exact = false })
58-
:: add_event loc (Let (v, Apply { f; args; exact = true }) :: acc)
59-
, free_pc
60-
, extra )
61-
| Some n when n > n' ->
47+
let expr = Apply { f; args; exact = true } in
48+
update_def x expr;
49+
Let (x, expr) :: acc, free_pc, extra)
50+
else if arity > nargs
51+
then (
52+
(* under application *)
6253
incr opt_count;
63-
let missing = Array.init (n - n') ~f:(fun _ -> Code.Var.fresh ()) in
54+
let missing = Array.init (arity - nargs) ~f:(fun _ -> Code.Var.fresh ()) in
6455
let missing = Array.to_list missing in
6556
let block =
66-
let params' = Array.init (n - n') ~f:(fun _ -> Code.Var.fresh ()) in
67-
let params' = Array.to_list params' in
57+
let params' = List.map missing ~f:Code.Var.fork in
6858
let return' = Code.Var.fresh () in
59+
let args = args @ params' in
60+
assert (List.length args = arity);
6961
{ params = params'
70-
; body =
71-
add_event
72-
loc
73-
[ Let (return', Apply { f; args = args @ params'; exact = true }) ]
62+
; body = add_event loc [ Let (return', Apply { f; args; exact = true }) ]
7463
; branch = Return return'
7564
}
7665
in
7766
let expr = Closure (missing, (free_pc, missing), None) in
7867
update_def x expr;
79-
Let (x, expr) :: acc, free_pc + 1, (free_pc, block) :: extra
80-
| Some _ -> assert false)
81-
| _ -> i :: acc, free_pc, extra
68+
Let (x, expr) :: acc, free_pc + 1, (free_pc, block) :: extra)
69+
else (
70+
assert (arity < nargs);
71+
(* over application *)
72+
incr opt_count;
73+
let v = Code.Var.fresh () in
74+
let args, rest = List.take arity args in
75+
let exact_expr = Apply { f; args; exact = true } in
76+
let body =
77+
(* Reversed *)
78+
add_event loc (Let (v, exact_expr) :: acc)
79+
in
80+
loop x v rest res loc (body, free_pc, extra))
81+
in
82+
fun i (((body_rev, free_pc, extra) as acc), loc) ->
83+
match i with
84+
| Let (x, Apply { f; args; exact = false }) -> loop x f args (shape f) loc acc
85+
| _ -> i :: body_rev, free_pc, extra
8286

83-
let specialize_instrs ~function_arity ~update_def opt_count p =
87+
let specialize_instrs ~shape ~update_def opt_count p =
8488
let blocks, free_pc =
89+
let specialize_instrs = specialize_apply opt_count shape update_def in
8590
Addr.Map.fold
8691
(fun pc block (blocks, free_pc) ->
8792
if List.exists ~f:unknown_apply block.body
8893
then
89-
let (body, free_pc, extra), _ =
94+
let (body_rev, free_pc, extra), _ =
9095
List.fold_left
9196
block.body
9297
~init:(([], free_pc, []), None)
9398
~f:(fun acc i ->
9499
match i with
95100
| Event loc ->
96-
let (body, free_pc, extra), _ = acc in
97-
(i :: body, free_pc, extra), Some loc
98-
| _ -> specialize_apply opt_count function_arity update_def acc i, None)
101+
let (body_rev, free_pc, extra), _ = acc in
102+
(i :: body_rev, free_pc, extra), Some loc
103+
| _ -> specialize_instrs i acc, None)
99104
in
100105
let blocks =
101106
List.fold_left extra ~init:blocks ~f:(fun blocks (pc, b) ->
102107
Addr.Map.add pc b blocks)
103108
in
104-
Addr.Map.add pc { block with Code.body = List.rev body } blocks, free_pc
109+
Addr.Map.add pc { block with Code.body = List.rev body_rev } blocks, free_pc
105110
else blocks, free_pc)
106111
p.blocks
107112
(p.blocks, p.free_pc)
108113
in
109114
{ p with blocks; free_pc }
110115

111-
let f ~function_arity ~update_def p =
116+
let f ~shape ~update_def p =
112117
Code.invariant p;
113118
let previous_p = p in
114119
let t = Timer.make () in
115120
let opt_count = ref 0 in
116121
let p =
117-
if Config.Flag.optcall ()
118-
then specialize_instrs ~function_arity ~update_def opt_count p
119-
else p
122+
if Config.Flag.optcall () then specialize_instrs ~shape ~update_def opt_count p else p
120123
in
121124
if times () then Format.eprintf " optcall: %a@." Timer.print t;
122125
if stats () then Format.eprintf "Stats - optcall: %d@." !opt_count;

compiler/lib/specialize.mli

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

21-
val function_arity :
22-
return_values:Code.Var.Set.t Code.Var.Map.t -> Flow.Info.t -> Code.Var.t -> int option
23-
2421
val f :
25-
function_arity:(Code.Var.t -> int option)
22+
shape:(Code.Var.t -> Shape.t)
2623
-> update_def:(Code.Var.t -> Code.expr -> unit)
2724
-> Code.program
2825
-> Code.program

0 commit comments

Comments
 (0)