summaryrefslogtreecommitdiff
path: root/asmcomp/liveness.ml
diff options
context:
space:
mode:
authorPierre Chambart <pierre.chambart@ocamlpro.com>2016-10-25 16:09:53 +0100
committerPierre Chambart <chambart@users.noreply.github.com>2016-10-28 13:03:59 +0200
commitc3d056de682de562e98c6d91cee706f6b7131fba (patch)
tree1697f50c061bdaca186cd373412a87cf756ac535 /asmcomp/liveness.ml
parent4c03ef70fd1563d283d038dda180c3b855c37517 (diff)
downloadocaml-c3d056de682de562e98c6d91cee706f6b7131fba.tar.gz
Change Cmm Ccatch construct to allow recursive cases
Diffstat (limited to 'asmcomp/liveness.ml')
-rw-r--r--asmcomp/liveness.ml51
1 files changed, 43 insertions, 8 deletions
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index c3d2f87884..6cad00daaa 100644
--- a/asmcomp/liveness.ml
+++ b/asmcomp/liveness.ml
@@ -22,7 +22,9 @@ let live_at_exit = ref []
let find_live_at_exit k =
try
- List.assoc k !live_at_exit
+ let (used, set) = List.assoc k !live_at_exit in
+ used := true;
+ set
with
| Not_found -> Misc.fatal_error "Liveness.find_live_at_exit"
@@ -101,14 +103,47 @@ let rec live i finally =
end;
i.live <- !at_top;
!at_top
- | Icatch(nfail, body, handler) ->
+ | Icatch(handlers, body) ->
let at_join = live i.next finally in
- let before_handler = live handler at_join in
- let before_body =
- live_at_exit := (nfail,before_handler) :: !live_at_exit ;
- let before_body = live body at_join in
- live_at_exit := List.tl !live_at_exit ;
- before_body in
+
+ let aux (nfail,handler) (nfail', before_handler) =
+ assert(nfail = nfail');
+ let before_handler' = live handler at_join in
+ nfail, Reg.Set.union before_handler before_handler' in
+
+ let aux_equal (nfail, before_handler) (nfail', before_handler') =
+ assert(nfail = nfail');
+ Reg.Set.equal before_handler before_handler' in
+
+ let live_at_exit_before = !live_at_exit in
+
+ let live_at_exit_add before_handlers =
+ List.map (fun (nfail, before_handler) ->
+ (nfail, (ref false, before_handler)))
+ before_handlers in
+
+ let rec fixpoint before_handlers =
+ let live_at_exit_add = live_at_exit_add before_handlers in
+ live_at_exit := live_at_exit_add @ !live_at_exit;
+ let before_handlers' = List.map2 aux handlers before_handlers in
+ live_at_exit := live_at_exit_before;
+ let not_used = List.for_all
+ (fun (_,(used,_)) -> not !used) live_at_exit_add in
+ if not_used || List.for_all2 aux_equal before_handlers before_handlers'
+ then before_handlers'
+ else fixpoint before_handlers'
+ in
+
+ let init_state =
+ List.map (fun (nfail, _handler) -> nfail, Reg.Set.empty) handlers in
+ let before_handler = fixpoint init_state in
+ (* We could use handler.live instead of Reg.Set.empty as the initialisation
+ but we would need to clean the live field before doing the analysis
+ (to remove remaining of previous passes) *)
+
+ live_at_exit := (live_at_exit_add before_handler) @ !live_at_exit;
+ let before_body = live body at_join in
+ live_at_exit := live_at_exit_before;
i.live <- before_body;
before_body
| Iexit nfail ->