@@ -26,11 +26,6 @@ let stats = Debug.find "stats"
2626
2727let 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-
3429let 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;
0 commit comments