1 (* Js_of_ocaml compiler
2 * http://www.ocsigen.org/js_of_ocaml/
3 * Copyright (C) 2010 Jérôme Vouillon
4 * Laboratoire PPS - CNRS Université Paris Diderot
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, with linking exception;
9 * either version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 FIX: is there a way to merge this with dead code elimination?
29 (* Postorder traversal of the whole program. *)
31 let traverse blocks pc f accu
=
32 let rec traverse_rec visited pc accu
=
33 if AddrSet.mem pc visited
then (visited
, accu
) else begin
34 let visited = AddrSet.add pc
visited in
35 let block = AddrMap.find pc blocks
in
38 (fun ((visited, accu
) as p
) i
->
40 Let
(_
, Closure
(_
, (pc
, _
))) ->
41 traverse_rec visited pc accu
44 (visited, accu
) block.body
47 match block.branch
with
48 Return _
| Raise _
| Stop
->
50 | Branch
(pc
, _
) | Poptrap
(pc
, _
) ->
51 traverse_rec visited pc accu
52 | Cond
(_
, _
, (pc1
, _
), (pc2
, _
)) ->
53 let (visited, accu
) = traverse_rec visited pc1 accu
in
54 traverse_rec visited pc2 accu
55 | Switch
(_
, a1
, a2
) ->
58 (fun (visited, accu
) (pc
, _
) -> traverse_rec visited pc accu
)
62 (fun (visited, accu
) (pc
, _
) -> traverse_rec visited pc accu
)
65 | Pushtrap
((pc1
, _
), _
, (pc2
, _
), _
) ->
66 let (visited, accu
) = traverse_rec visited pc1 accu
in
67 traverse_rec visited pc2 accu
72 snd
(traverse_rec AddrSet.empty pc accu
)
76 let is_trivial instr last
=
80 Return _
| Raise _
| Stop
| Branch _
-> true
81 | Cond _
| Poptrap _
| Switch _
| Pushtrap _
-> false
84 let resolve_branch blocks
(pc
, args
) =
85 match AddrMap.find pc blocks
with
86 {params
= []; body
= []; branch
= Branch
(pc'
, args'
)} ->
91 let concat_blocks pc instr params handler args params' instr' last'
=
92 (* This is only valid because we know that the params only occur in
94 let m = Subst.build_mapping params' args
in
95 let s = Subst.from_map
m in
98 body
= instr
@ Subst.instrs
s instr'
;
99 branch
= Subst.last
s last'
}
101 let rec block_simpl pc
(preds
, entries
, blocks
) =
102 Format.eprintf
"VV %d@." pc
;
104 Format.eprintf "RRRRRRRRRRRRRRR %d@." (AddrSet.cardinal (AddrMap.find 12644 preds));
106 let block = AddrMap.find pc blocks
in
107 match block.branch
with
108 Return _
| Raise _
| Stop
| Poptrap _
->
109 (preds
, entries
, blocks
)
110 | Branch
(pc'
, args
) ->
111 let block'
= AddrMap.find pc' blocks
in
115 not (AddrSet.mem pc' entries)
117 AddrSet.cardinal (AddrMap.find pc' preds) = 1
119 block'.params = [] && block'.handler = block.handler
122 Format.eprintf
"UU %d ==> %d@." pc pc'
;
126 (concat_blocks pc
block.body
block.params
block.handler args
127 block'
.params
block'
.body
block'
.branch
)
128 (AddrMap.remove pc' blocks
))
129 end else if false(*XXX args = [] && is_trivial block'.body block'.branch *)then begin
130 (AddrMap.add pc'
(AddrSet.remove pc
(AddrMap.find pc' preds
))
135 pc
block.body
block.params
block.handler args
136 block'
.params
block'
.body
block'
.branch
)
139 (preds
, entries
, blocks
)
140 | Cond
(c
, x
, cont1
, cont2
) ->
141 if cont1
= cont2
then begin
143 AddrMap.add pc
{block with branch
= Branch cont1
} blocks in
144 block_simpl pc
(preds
, entries
, blocks)
146 match resolve_branch blocks cont1
with
148 let pc1 = fst cont1
in let pc1'
= fst cont1'
in
152 (AddrSet.remove
pc1 (AddrMap.find
pc1'
preds)))
157 { block with branch
= Cond
(c
, x
, cont1'
, cont2
) } blocks
159 block_simpl pc
(preds, entries
, blocks)
161 match resolve_branch blocks cont2
with
163 let pc2 = fst cont2
in let pc2'
= fst cont2'
in
167 (AddrSet.remove
pc2 (AddrMap.find
pc2'
preds)))
172 { block with branch
= Cond
(c
, x
, cont1
, cont2'
) }
175 block_simpl pc
(preds, entries
, blocks)
177 (preds, entries
, blocks)
179 | Switch
(x
, a1
, a2
) ->
183 match resolve_branch blocks pc
with Some pc
-> pc
| None
-> pc
)
188 match resolve_branch blocks pc
with Some pc
-> pc
| None
-> pc
)
191 AddrMap.add pc
{ block with branch
= Switch
(x
, a1, a2) } blocks)
193 (preds, entries
, blocks)
195 let simpl (pc
, blocks, free_pc
) =
196 let preds = AddrMap.map
(fun _
-> AddrSet.empty
) blocks in
197 let entries = AddrSet.empty
in
198 let add_pred pc
(pc'
, _
) preds =
199 Format.eprintf
"%d ==> %d@." pc pc'
;
200 AddrMap.add pc'
(AddrSet.add pc
(AddrMap.find pc'
preds)) preds in
201 let (preds, entries) =
203 (fun pc
block (preds, entries) ->
208 Let
(_
, Closure
(_
, (pc
, _
))) ->
209 AddrSet.add pc
entries
215 match block.branch
with
216 Return _
| Raise _
| Stop
->
218 | Branch cont
| Poptrap cont
->
219 add_pred pc cont
preds
220 | Cond
(_
, _
, cont1
, cont2
)
221 | Pushtrap
(cont1
, _
, cont2
, _
) ->
222 add_pred pc cont1
(add_pred pc cont2
preds)
223 | Switch
(_
, a1, a2) ->
226 (fun preds cont
-> add_pred pc cont
preds) preds a1 in
229 (fun preds cont
-> add_pred pc cont
preds) preds a2 in
233 blocks (preds, entries)
236 Format.eprintf "RRRRRRRRRRRRRRR %d@." (AddrSet.cardinal (AddrMap.find 12644 preds));*)
238 traverse blocks pc
block_simpl (preds, entries, blocks) in
239 (pc
, blocks, free_pc
)