Skip to content

Commit 60ae151

Browse files
committed
More precise tail-call analysis
1 parent fe7ccc9 commit 60ae151

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

compiler/lib-wasm/call_graph_analysis.ml

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,35 @@ type t = { unambiguous_non_escaping : unit Var.Hashtbl.t }
4242
let 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

123151
let 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-
149165
let 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

Comments
 (0)