@@ -26,11 +26,6 @@ let stats = Debug.find "stats"
26
26
27
27
let debug_stats = Debug. find " stats-debug"
28
28
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
-
34
29
let add_event loc instrs =
35
30
match loc with
36
31
| Some loc -> Event loc :: instrs
@@ -40,83 +35,91 @@ let unknown_apply = function
40
35
| Let (_ , Apply { f = _ ; args = _ ; exact = false } ) -> true
41
36
| _ -> false
42
37
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 (
53
46
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 *)
62
53
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
64
55
let missing = Array. to_list missing in
65
56
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
68
58
let return' = Code.Var. fresh () in
59
+ let args = args @ params' in
60
+ assert (List. length args = arity);
69
61
{ 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 }) ]
74
63
; branch = Return return'
75
64
}
76
65
in
77
66
let expr = Closure (missing, (free_pc, missing), None ) in
78
67
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
82
86
83
- let specialize_instrs ~function_arity ~update_def opt_count p =
87
+ let specialize_instrs ~shape ~update_def opt_count p =
84
88
let blocks, free_pc =
89
+ let specialize_instrs = specialize_apply opt_count shape update_def in
85
90
Addr.Map. fold
86
91
(fun pc block (blocks , free_pc ) ->
87
92
if List. exists ~f: unknown_apply block.body
88
93
then
89
- let (body , free_pc, extra), _ =
94
+ let (body_rev , free_pc, extra), _ =
90
95
List. fold_left
91
96
block.body
92
97
~init: (([] , free_pc, [] ), None )
93
98
~f: (fun acc i ->
94
99
match i with
95
100
| 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 )
99
104
in
100
105
let blocks =
101
106
List. fold_left extra ~init: blocks ~f: (fun blocks (pc , b ) ->
102
107
Addr.Map. add pc b blocks)
103
108
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
105
110
else blocks, free_pc)
106
111
p.blocks
107
112
(p.blocks, p.free_pc)
108
113
in
109
114
{ p with blocks; free_pc }
110
115
111
- let f ~function_arity ~update_def p =
116
+ let f ~shape ~update_def p =
112
117
Code. invariant p;
113
118
let previous_p = p in
114
119
let t = Timer. make () in
115
120
let opt_count = ref 0 in
116
121
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
120
123
in
121
124
if times () then Format. eprintf " optcall: %a@." Timer. print t;
122
125
if stats () then Format. eprintf " Stats - optcall: %d@." ! opt_count;
0 commit comments