@@ -42,11 +42,35 @@ type t = { unambiguous_non_escaping : unit Var.Hashtbl.t }
4242let direct_calls_only info f =
4343 Config.Flag. optcall () && Var.Hashtbl. mem info.unambiguous_non_escaping f
4444
45- let call_graph p info call_info =
45+ let callee_if_known info call_info exact f =
46+ match get_approx info f with
47+ | Top -> None
48+ | Values { known; others } ->
49+ if
50+ exact
51+ && (not others)
52+ && Var.Set. for_all (fun f -> direct_calls_only call_info f) known
53+ then Some (Var.Set. choose known)
54+ else None
55+
56+ let propagate nodes edges eligible =
57+ let rec propagate n =
58+ List. iter
59+ ~f: (fun n' ->
60+ if (not (Var.Hashtbl. mem nodes n')) && eligible n'
61+ then (
62+ Var.Hashtbl. add nodes n' () ;
63+ propagate n'))
64+ (Var.Hashtbl. find_all edges n)
65+ in
66+ Var.Hashtbl. iter (fun n () -> propagate n) nodes
67+
68+ let call_graph p info call_info eligible =
4669 let under_handler = Var.Hashtbl. create 16 in
4770 let callees = Var.Hashtbl. create 16 in
4871 let callers = Var.Hashtbl. create 16 in
4972 let has_tail_calls = Var.Hashtbl. create 16 in
73+ let tail_callers = Var.Hashtbl. create 16 in
5074 let rec traverse name_opt pc visited nesting =
5175 if not (Addr.Set. mem pc visited)
5276 then (
@@ -92,8 +116,11 @@ let call_graph p info call_info =
92116 match block.branch with
93117 | Return x -> (
94118 match last_instr block.body with
95- | Some (Let (x' , Apply _ )) when Code.Var. equal x x' ->
96- Var.Hashtbl. replace has_tail_calls f ()
119+ | Some (Let (x', Apply { f = g; exact; _ })) when Code.Var. equal x x'
120+ -> (
121+ match callee_if_known info call_info exact g with
122+ | None -> Var.Hashtbl. replace has_tail_calls f ()
123+ | Some g -> Var.Hashtbl. add tail_callers g f)
97124 | _ -> () )
98125 | _ -> () )
99126 pc
@@ -118,6 +145,7 @@ let call_graph p info call_info =
118145 p
119146 (fun name_opt _ (pc , _ ) _ () -> ignore (traverse name_opt pc Addr.Set. empty 0 ))
120147 () ;
148+ propagate has_tail_calls tail_callers eligible;
121149 under_handler, callers, callees, has_tail_calls
122150
123151let function_do_raise p pc =
@@ -134,20 +162,10 @@ let function_do_raise p pc =
134162 p.blocks
135163 false
136164
137- let propagate nodes edges eligible =
138- let rec propagate n =
139- List. iter
140- ~f: (fun n' ->
141- if (not (Var.Hashtbl. mem nodes n')) && eligible n'
142- then (
143- Var.Hashtbl. add nodes n' () ;
144- propagate n'))
145- (Var.Hashtbl. find_all edges n)
146- in
147- Var.Hashtbl. iter (fun n () -> propagate n) nodes
148-
149165let raising_functions p info call_info eligible =
150- let under_handler, callers, callees, has_tail_calls = call_graph p info call_info in
166+ let under_handler, callers, callees, has_tail_calls =
167+ call_graph p info call_info eligible
168+ in
151169 propagate under_handler callees (fun f ->
152170 eligible f && not (Var.Hashtbl. mem has_tail_calls f));
153171 let h = Var.Hashtbl. create 16 in
0 commit comments