summaryrefslogtreecommitdiff
path: root/bytecomp
diff options
context:
space:
mode:
authorThomas Refis <thomas.refis@gmail.com>2018-05-25 11:03:03 +0100
committerThomas Refis <refis.thomas@gmail.com>2018-05-25 11:29:23 +0100
commit20c430383724496820feb2e7357185875ac92c7a (patch)
treede01fc1369c0bd317af19b3908ea77ee53cd2e27 /bytecomp
parente407ecf114f8f8d5d778c570ce64f8c9f85042c5 (diff)
downloadocaml-20c430383724496820feb2e7357185875ac92c7a.tar.gz
reindent bytecomp/switch.ml
Diffstat (limited to 'bytecomp')
-rw-r--r--bytecomp/switch.ml1204
1 files changed, 602 insertions, 602 deletions
diff --git a/bytecomp/switch.ml b/bytecomp/switch.ml
index b03982ddeb..c5d1b4de23 100644
--- a/bytecomp/switch.ml
+++ b/bytecomp/switch.ml
@@ -17,10 +17,10 @@
type 'a shared = Shared of 'a | Single of 'a
type ('a, 'ctx) t_store =
- {act_get : unit -> 'a array ;
- act_get_shared : unit -> 'a shared array ;
- act_store : 'ctx -> 'a -> int ;
- act_store_shared : 'ctx -> 'a -> int ; }
+ {act_get : unit -> 'a array ;
+ act_get_shared : unit -> 'a shared array ;
+ act_store : 'ctx -> 'a -> int ;
+ act_store_shared : 'ctx -> 'a -> int ; }
exception Not_simple
@@ -42,9 +42,9 @@ module CtxStore(A:CtxStored) = struct
Map.Make(struct type t = A.key let compare = A.compare_key end)
type intern =
- { mutable map : (bool * int) AMap.t ;
- mutable next : int ;
- mutable acts : (bool * A.t) list; }
+ { mutable map : (bool * int) AMap.t ;
+ mutable next : int ;
+ mutable acts : (bool * A.t) list; }
let mk_store () =
let st =
@@ -59,18 +59,18 @@ module CtxStore(A:CtxStored) = struct
i in
let store mustshare ctx act = match A.make_key ctx act with
- | Some key ->
- begin try
- let (shared,i) = AMap.find key st.map in
- if not shared then st.map <- AMap.add key (true,i) st.map ;
- i
- with Not_found ->
- let i = add mustshare act in
- st.map <- AMap.add key (mustshare,i) st.map ;
- i
- end
- | None ->
- add mustshare act
+ | Some key ->
+ begin try
+ let (shared,i) = AMap.find key st.map in
+ if not shared then st.map <- AMap.add key (true,i) st.map ;
+ i
+ with Not_found ->
+ let i = add mustshare act in
+ st.map <- AMap.add key (mustshare,i) st.map ;
+ i
+ end
+ | None ->
+ add mustshare act
and get () = Array.of_list (List.rev_map (fun (_,act) -> act) st.acts)
@@ -79,13 +79,13 @@ module CtxStore(A:CtxStored) = struct
Array.of_list
(List.rev_map
(fun (shared,act) ->
- if shared then Shared act else Single act)
+ if shared then Shared act else Single act)
st.acts) in
AMap.iter
(fun _ (shared,i) ->
- if shared then match acts.(i) with
- | Single act -> acts.(i) <- Shared act
- | Shared _ -> ())
+ if shared then match acts.(i) with
+ | Single act -> acts.(i) <- Shared act
+ | Shared _ -> ())
st.map ;
acts in
{act_store = store false ; act_store_shared = store true ;
@@ -107,27 +107,27 @@ end
module type S =
- sig
- type primitive
- val eqint : primitive
- val neint : primitive
- val leint : primitive
- val ltint : primitive
- val geint : primitive
- val gtint : primitive
- type act
-
- val bind : act -> (act -> act) -> act
- val make_const : int -> act
- val make_offset : act -> int -> act
- val make_prim : primitive -> act list -> act
- val make_isout : act -> act -> act
- val make_isin : act -> act -> act
- val make_if : act -> act -> act -> act
- val make_switch : Location.t -> act -> int array -> act array -> act
- val make_catch : act -> int * (act -> act)
- val make_exit : int -> act
- end
+sig
+ type primitive
+ val eqint : primitive
+ val neint : primitive
+ val leint : primitive
+ val ltint : primitive
+ val geint : primitive
+ val gtint : primitive
+ type act
+
+ val bind : act -> (act -> act) -> act
+ val make_const : int -> act
+ val make_offset : act -> int -> act
+ val make_prim : primitive -> act list -> act
+ val make_isout : act -> act -> act
+ val make_isin : act -> act -> act
+ val make_if : act -> act -> act -> act
+ val make_switch : Location.t -> act -> int array -> act array -> act
+ val make_catch : act -> int * (act -> act)
+ val make_exit : int -> act
+end
(* The module will ``produce good code for the case statement'' *)
(*
@@ -150,16 +150,16 @@ module type S =
test sequence in small cases and heuristics otherwise.
*)
module Make (Arg : S) =
- struct
+struct
- type 'a inter =
- {cases : (int * int * int) array ;
- actions : 'a array}
+ type 'a inter =
+ {cases : (int * int * int) array ;
+ actions : 'a array}
-type 'a t_ctx = {off : int ; arg : 'a}
+ type 'a t_ctx = {off : int ; arg : 'a}
-let cut = ref 8
-and more_cut = ref 16
+ let cut = ref 8
+ and more_cut = ref 16
(*
let pint chan i =
@@ -180,19 +180,19 @@ let prerr_inter i = Printf.fprintf stderr
"cases=%a" pcases i.cases
*)
-let get_act cases i =
- let _,_,r = cases.(i) in
- r
-and get_low cases i =
- let r,_,_ = cases.(i) in
- r
+ let get_act cases i =
+ let _,_,r = cases.(i) in
+ r
+ and get_low cases i =
+ let r,_,_ = cases.(i) in
+ r
-type ctests = {
+ type ctests = {
mutable n : int ;
mutable ni : int ;
}
-let too_much = {n=max_int ; ni=max_int}
+ let too_much = {n=max_int ; ni=max_int}
(*
let ptests chan {n=n ; ni=ni} =
@@ -204,30 +204,30 @@ let pta chan t =
done
*)
-let less_tests c1 c2 =
- if c1.n < c2.n then
- true
- else if c1.n = c2.n then begin
- if c1.ni < c2.ni then
+ let less_tests c1 c2 =
+ if c1.n < c2.n then
true
- else
+ else if c1.n = c2.n then begin
+ if c1.ni < c2.ni then
+ true
+ else
+ false
+ end else
false
- end else
- false
-and eq_tests c1 c2 = c1.n = c2.n && c1.ni=c2.ni
+ and eq_tests c1 c2 = c1.n = c2.n && c1.ni=c2.ni
-let less2tests (c1,d1) (c2,d2) =
- if eq_tests c1 c2 then
- less_tests d1 d2
- else
- less_tests c1 c2
+ let less2tests (c1,d1) (c2,d2) =
+ if eq_tests c1 c2 then
+ less_tests d1 d2
+ else
+ less_tests c1 c2
-let add_test t1 t2 =
- t1.n <- t1.n + t2.n ;
- t1.ni <- t1.ni + t2.ni ;
+ let add_test t1 t2 =
+ t1.n <- t1.n + t2.n ;
+ t1.ni <- t1.ni + t2.ni ;
-type t_ret = Inter of int * int | Sep of int | No
+ type t_ret = Inter of int * int | Sep of int | No
(*
let pret chan = function
@@ -236,84 +236,84 @@ let pret chan = function
| No -> Printf.fprintf chan "No"
*)
-let coupe cases i =
- let l,_,_ = cases.(i) in
- l,
- Array.sub cases 0 i,
- Array.sub cases i (Array.length cases-i)
-
-
-let case_append c1 c2 =
- let len1 = Array.length c1
- and len2 = Array.length c2 in
- match len1,len2 with
- | 0,_ -> c2
- | _,0 -> c1
- | _,_ ->
- let l1,h1,act1 = c1.(Array.length c1-1)
- and l2,h2,act2 = c2.(0) in
- if act1 = act2 then
- let r = Array.make (len1+len2-1) c1.(0) in
- for i = 0 to len1-2 do
- r.(i) <- c1.(i)
- done ;
-
- let l =
- if len1-2 >= 0 then begin
- let _,h,_ = r.(len1-2) in
- if h+1 < l1 then
- h+1
- else
+ let coupe cases i =
+ let l,_,_ = cases.(i) in
+ l,
+ Array.sub cases 0 i,
+ Array.sub cases i (Array.length cases-i)
+
+
+ let case_append c1 c2 =
+ let len1 = Array.length c1
+ and len2 = Array.length c2 in
+ match len1,len2 with
+ | 0,_ -> c2
+ | _,0 -> c1
+ | _,_ ->
+ let l1,h1,act1 = c1.(Array.length c1-1)
+ and l2,h2,act2 = c2.(0) in
+ if act1 = act2 then
+ let r = Array.make (len1+len2-1) c1.(0) in
+ for i = 0 to len1-2 do
+ r.(i) <- c1.(i)
+ done ;
+
+ let l =
+ if len1-2 >= 0 then begin
+ let _,h,_ = r.(len1-2) in
+ if h+1 < l1 then
+ h+1
+ else
+ l1
+ end else
l1
- end else
- l1
- and h =
- if 1 < len2-1 then begin
- let l,_,_ = c2.(1) in
- if h2+1 < l then
- l-1
- else
- h2
- end else
- h2 in
- r.(len1-1) <- (l,h,act1) ;
- for i=1 to len2-1 do
- r.(len1-1+i) <- c2.(i)
- done ;
- r
- else if h1 > l1 then
- let r = Array.make (len1+len2) c1.(0) in
- for i = 0 to len1-2 do
- r.(i) <- c1.(i)
- done ;
- r.(len1-1) <- (l1,l2-1,act1) ;
- for i=0 to len2-1 do
- r.(len1+i) <- c2.(i)
- done ;
- r
- else if h2 > l2 then
- let r = Array.make (len1+len2) c1.(0) in
- for i = 0 to len1-1 do
- r.(i) <- c1.(i)
- done ;
- r.(len1) <- (h1+1,h2,act2) ;
- for i=1 to len2-1 do
- r.(len1+i) <- c2.(i)
- done ;
- r
- else
- Array.append c1 c2
+ and h =
+ if 1 < len2-1 then begin
+ let l,_,_ = c2.(1) in
+ if h2+1 < l then
+ l-1
+ else
+ h2
+ end else
+ h2 in
+ r.(len1-1) <- (l,h,act1) ;
+ for i=1 to len2-1 do
+ r.(len1-1+i) <- c2.(i)
+ done ;
+ r
+ else if h1 > l1 then
+ let r = Array.make (len1+len2) c1.(0) in
+ for i = 0 to len1-2 do
+ r.(i) <- c1.(i)
+ done ;
+ r.(len1-1) <- (l1,l2-1,act1) ;
+ for i=0 to len2-1 do
+ r.(len1+i) <- c2.(i)
+ done ;
+ r
+ else if h2 > l2 then
+ let r = Array.make (len1+len2) c1.(0) in
+ for i = 0 to len1-1 do
+ r.(i) <- c1.(i)
+ done ;
+ r.(len1) <- (h1+1,h2,act2) ;
+ for i=1 to len2-1 do
+ r.(len1+i) <- c2.(i)
+ done ;
+ r
+ else
+ Array.append c1 c2
-let coupe_inter i j cases =
- let lcases = Array.length cases in
- let low,_,_ = cases.(i)
- and _,high,_ = cases.(j) in
- low,high,
- Array.sub cases i (j-i+1),
- case_append (Array.sub cases 0 i) (Array.sub cases (j+1) (lcases-(j+1)))
+ let coupe_inter i j cases =
+ let lcases = Array.length cases in
+ let low,_,_ = cases.(i)
+ and _,high,_ = cases.(j) in
+ low,high,
+ Array.sub cases i (j-i+1),
+ case_append (Array.sub cases 0 i) (Array.sub cases (j+1) (lcases-(j+1)))
-type kind = Kvalue of int | Kinter of int | Kempty
+ type kind = Kvalue of int | Kinter of int | Kempty
(*
let pkind chan = function
@@ -328,52 +328,52 @@ let rec pkey chan = function
Printf.fprintf chan "%a %a" pkey rem pkind k
*)
-let t = Hashtbl.create 17
-
-let make_key cases =
- let seen = ref []
- and count = ref 0 in
- let rec got_it act = function
- | [] ->
- seen := (act,!count):: !seen ;
- let r = !count in
- incr count ;
- r
- | (act0,index) :: rem ->
- if act0 = act then
- index
- else
- got_it act rem in
+ let t = Hashtbl.create 17
+
+ let make_key cases =
+ let seen = ref []
+ and count = ref 0 in
+ let rec got_it act = function
+ | [] ->
+ seen := (act,!count):: !seen ;
+ let r = !count in
+ incr count ;
+ r
+ | (act0,index) :: rem ->
+ if act0 = act then
+ index
+ else
+ got_it act rem in
- let make_one l h act =
- if l=h then
- Kvalue (got_it act !seen)
- else
- Kinter (got_it act !seen) in
+ let make_one l h act =
+ if l=h then
+ Kvalue (got_it act !seen)
+ else
+ Kinter (got_it act !seen) in
- let rec make_rec i pl =
- if i < 0 then
- []
- else
- let l,h,act = cases.(i) in
- if pl = h+1 then
- make_one l h act::make_rec (i-1) l
+ let rec make_rec i pl =
+ if i < 0 then
+ []
else
- Kempty::make_one l h act::make_rec (i-1) l in
+ let l,h,act = cases.(i) in
+ if pl = h+1 then
+ make_one l h act::make_rec (i-1) l
+ else
+ Kempty::make_one l h act::make_rec (i-1) l in
- let l,h,act = cases.(Array.length cases-1) in
- make_one l h act::make_rec (Array.length cases-2) l
+ let l,h,act = cases.(Array.length cases-1) in
+ make_one l h act::make_rec (Array.length cases-2) l
- let same_act t =
- let len = Array.length t in
- let a = get_act t (len-1) in
- let rec do_rec i =
- if i < 0 then true
- else
- let b = get_act t i in
- b=a && do_rec (i-1) in
- do_rec (len-2)
+ let same_act t =
+ let len = Array.length t in
+ let a = get_act t (len-1) in
+ let rec do_rec i =
+ if i < 0 then true
+ else
+ let b = get_act t i in
+ b=a && do_rec (i-1) in
+ do_rec (len-2)
(*
@@ -390,139 +390,58 @@ let make_key cases =
This condition is checked by zyva
*)
-let inter_limit = 1 lsl 16
-
-let ok_inter = ref false
-
-let rec opt_count top cases =
- let key = make_key cases in
- try
- Hashtbl.find t key
- with
- | Not_found ->
- let r =
- let lcases = Array.length cases in
- match lcases with
- | 0 -> assert false
- | _ when same_act cases -> No, ({n=0; ni=0},{n=0; ni=0})
- | _ ->
- if lcases < !cut then
- enum top cases
- else if lcases < !more_cut then
- heuristic cases
- else
- divide cases in
- Hashtbl.add t key r ;
- r
-
-and divide cases =
- let lcases = Array.length cases in
- let m = lcases/2 in
- let _,left,right = coupe cases m in
- let ci = {n=1 ; ni=0}
- and cm = {n=1 ; ni=0}
- and _,(cml,cleft) = opt_count false left
- and _,(cmr,cright) = opt_count false right in
- add_test ci cleft ;
- add_test ci cright ;
- if less_tests cml cmr then
- add_test cm cmr
- else
- add_test cm cml ;
- Sep m,(cm, ci)
-
-and heuristic cases =
- let lcases = Array.length cases in
-
- let sep,csep = divide cases
-
- and inter,cinter =
- if !ok_inter then begin
- let _,_,act0 = cases.(0)
- and _,_,act1 = cases.(lcases-1) in
- if act0 = act1 then begin
- let low, high, inside, outside = coupe_inter 1 (lcases-2) cases in
- let _,(cmi,cinside) = opt_count false inside
- and _,(cmo,coutside) = opt_count false outside
- and cmij = {n=1 ; ni=(if low=high then 0 else 1)}
- and cij = {n=1 ; ni=(if low=high then 0 else 1)} in
- add_test cij cinside ;
- add_test cij coutside ;
- if less_tests cmi cmo then
- add_test cmij cmo
- else
- add_test cmij cmi ;
- Inter (1,lcases-2),(cmij,cij)
- end else
- Inter (-1,-1),(too_much, too_much)
- end else
- Inter (-1,-1),(too_much, too_much) in
- if less2tests csep cinter then
- sep,csep
- else
- inter,cinter
-
-
-and enum top cases =
- let lcases = Array.length cases in
- let lim, with_sep =
- let best = ref (-1) and best_cost = ref (too_much,too_much) in
-
- for i = 1 to lcases-(1) do
- let _,left,right = coupe cases i in
- let ci = {n=1 ; ni=0}
- and cm = {n=1 ; ni=0}
- and _,(cml,cleft) = opt_count false left
- and _,(cmr,cright) = opt_count false right in
- add_test ci cleft ;
- add_test ci cright ;
- if less_tests cml cmr then
- add_test cm cmr
- else
- add_test cm cml ;
-
- if
- less2tests (cm,ci) !best_cost
- then begin
- if top then
- Printf.fprintf stderr "Get it: %d\n" i ;
- best := i ;
- best_cost := (cm,ci)
- end
- done ;
- !best, !best_cost in
-
- let ilow, ihigh, with_inter =
- if not !ok_inter then
- let rlow = ref (-1) and rhigh = ref (-1)
- and best_cost= ref (too_much,too_much) in
- for i=1 to lcases-2 do
- let low, high, inside, outside = coupe_inter i i cases in
- if low=high then begin
- let _,(cmi,cinside) = opt_count false inside
- and _,(cmo,coutside) = opt_count false outside
- and cmij = {n=1 ; ni=0}
- and cij = {n=1 ; ni=0} in
- add_test cij cinside ;
- add_test cij coutside ;
- if less_tests cmi cmo then
- add_test cmij cmo
- else
- add_test cmij cmi ;
- if less2tests (cmij,cij) !best_cost then begin
- rlow := i ;
- rhigh := i ;
- best_cost := (cmij,cij)
- end
- end
- done ;
- !rlow, !rhigh, !best_cost
+ let inter_limit = 1 lsl 16
+
+ let ok_inter = ref false
+
+ let rec opt_count top cases =
+ let key = make_key cases in
+ try
+ Hashtbl.find t key
+ with
+ | Not_found ->
+ let r =
+ let lcases = Array.length cases in
+ match lcases with
+ | 0 -> assert false
+ | _ when same_act cases -> No, ({n=0; ni=0},{n=0; ni=0})
+ | _ ->
+ if lcases < !cut then
+ enum top cases
+ else if lcases < !more_cut then
+ heuristic cases
+ else
+ divide cases in
+ Hashtbl.add t key r ;
+ r
+
+ and divide cases =
+ let lcases = Array.length cases in
+ let m = lcases/2 in
+ let _,left,right = coupe cases m in
+ let ci = {n=1 ; ni=0}
+ and cm = {n=1 ; ni=0}
+ and _,(cml,cleft) = opt_count false left
+ and _,(cmr,cright) = opt_count false right in
+ add_test ci cleft ;
+ add_test ci cright ;
+ if less_tests cml cmr then
+ add_test cm cmr
else
- let rlow = ref (-1) and rhigh = ref (-1)
- and best_cost= ref (too_much,too_much) in
- for i=1 to lcases-2 do
- for j=i to lcases-2 do
- let low, high, inside, outside = coupe_inter i j cases in
+ add_test cm cml ;
+ Sep m,(cm, ci)
+
+ and heuristic cases =
+ let lcases = Array.length cases in
+
+ let sep,csep = divide cases
+
+ and inter,cinter =
+ if !ok_inter then begin
+ let _,_,act0 = cases.(0)
+ and _,_,act1 = cases.(lcases-1) in
+ if act0 = act1 then begin
+ let low, high, inside, outside = coupe_inter 1 (lcases-2) cases in
let _,(cmi,cinside) = opt_count false inside
and _,(cmo,coutside) = opt_count false outside
and cmij = {n=1 ; ni=(if low=high then 0 else 1)}
@@ -533,47 +452,128 @@ and enum top cases =
add_test cmij cmo
else
add_test cmij cmi ;
- if less2tests (cmij,cij) !best_cost then begin
- rlow := i ;
- rhigh := j ;
- best_cost := (cmij,cij)
- end
- done
+ Inter (1,lcases-2),(cmij,cij)
+ end else
+ Inter (-1,-1),(too_much, too_much)
+ end else
+ Inter (-1,-1),(too_much, too_much) in
+ if less2tests csep cinter then
+ sep,csep
+ else
+ inter,cinter
+
+
+ and enum top cases =
+ let lcases = Array.length cases in
+ let lim, with_sep =
+ let best = ref (-1) and best_cost = ref (too_much,too_much) in
+
+ for i = 1 to lcases-(1) do
+ let _,left,right = coupe cases i in
+ let ci = {n=1 ; ni=0}
+ and cm = {n=1 ; ni=0}
+ and _,(cml,cleft) = opt_count false left
+ and _,(cmr,cright) = opt_count false right in
+ add_test ci cleft ;
+ add_test ci cright ;
+ if less_tests cml cmr then
+ add_test cm cmr
+ else
+ add_test cm cml ;
+
+ if
+ less2tests (cm,ci) !best_cost
+ then begin
+ if top then
+ Printf.fprintf stderr "Get it: %d\n" i ;
+ best := i ;
+ best_cost := (cm,ci)
+ end
done ;
- !rlow, !rhigh, !best_cost in
- let r = ref (Inter (ilow,ihigh)) and rc = ref with_inter in
- if less2tests with_sep !rc then begin
- r := Sep lim ; rc := with_sep
- end ;
- !r, !rc
-
- let make_if_test test arg i ifso ifnot =
- Arg.make_if
- (Arg.make_prim test [arg ; Arg.make_const i])
- ifso ifnot
-
- let make_if_lt arg i ifso ifnot = match i with
+ !best, !best_cost in
+
+ let ilow, ihigh, with_inter =
+ if not !ok_inter then
+ let rlow = ref (-1) and rhigh = ref (-1)
+ and best_cost= ref (too_much,too_much) in
+ for i=1 to lcases-2 do
+ let low, high, inside, outside = coupe_inter i i cases in
+ if low=high then begin
+ let _,(cmi,cinside) = opt_count false inside
+ and _,(cmo,coutside) = opt_count false outside
+ and cmij = {n=1 ; ni=0}
+ and cij = {n=1 ; ni=0} in
+ add_test cij cinside ;
+ add_test cij coutside ;
+ if less_tests cmi cmo then
+ add_test cmij cmo
+ else
+ add_test cmij cmi ;
+ if less2tests (cmij,cij) !best_cost then begin
+ rlow := i ;
+ rhigh := i ;
+ best_cost := (cmij,cij)
+ end
+ end
+ done ;
+ !rlow, !rhigh, !best_cost
+ else
+ let rlow = ref (-1) and rhigh = ref (-1)
+ and best_cost= ref (too_much,too_much) in
+ for i=1 to lcases-2 do
+ for j=i to lcases-2 do
+ let low, high, inside, outside = coupe_inter i j cases in
+ let _,(cmi,cinside) = opt_count false inside
+ and _,(cmo,coutside) = opt_count false outside
+ and cmij = {n=1 ; ni=(if low=high then 0 else 1)}
+ and cij = {n=1 ; ni=(if low=high then 0 else 1)} in
+ add_test cij cinside ;
+ add_test cij coutside ;
+ if less_tests cmi cmo then
+ add_test cmij cmo
+ else
+ add_test cmij cmi ;
+ if less2tests (cmij,cij) !best_cost then begin
+ rlow := i ;
+ rhigh := j ;
+ best_cost := (cmij,cij)
+ end
+ done
+ done ;
+ !rlow, !rhigh, !best_cost in
+ let r = ref (Inter (ilow,ihigh)) and rc = ref with_inter in
+ if less2tests with_sep !rc then begin
+ r := Sep lim ; rc := with_sep
+ end ;
+ !r, !rc
+
+ let make_if_test test arg i ifso ifnot =
+ Arg.make_if
+ (Arg.make_prim test [arg ; Arg.make_const i])
+ ifso ifnot
+
+ let make_if_lt arg i ifso ifnot = match i with
| 1 ->
make_if_test Arg.leint arg 0 ifso ifnot
| _ ->
make_if_test Arg.ltint arg i ifso ifnot
- and make_if_ge arg i ifso ifnot = match i with
+ and make_if_ge arg i ifso ifnot = match i with
| 1 ->
make_if_test Arg.gtint arg 0 ifso ifnot
| _ ->
make_if_test Arg.geint arg i ifso ifnot
- and make_if_eq arg i ifso ifnot =
- make_if_test Arg.eqint arg i ifso ifnot
+ and make_if_eq arg i ifso ifnot =
+ make_if_test Arg.eqint arg i ifso ifnot
- and make_if_ne arg i ifso ifnot =
- make_if_test Arg.neint arg i ifso ifnot
+ and make_if_ne arg i ifso ifnot =
+ make_if_test Arg.neint arg i ifso ifnot
- let do_make_if_out h arg ifso ifno =
- Arg.make_if (Arg.make_isout h arg) ifso ifno
+ let do_make_if_out h arg ifso ifno =
+ Arg.make_if (Arg.make_isout h arg) ifso ifno
- let make_if_out ctx l d mk_ifso mk_ifno = match l with
+ let make_if_out ctx l d mk_ifso mk_ifno = match l with
| 0 ->
do_make_if_out
(Arg.make_const d) ctx.arg (mk_ifso ctx) (mk_ifno ctx)
@@ -581,14 +581,14 @@ and enum top cases =
Arg.bind
(Arg.make_offset ctx.arg (-l))
(fun arg ->
- let ctx = {off= (-l+ctx.off) ; arg=arg} in
- do_make_if_out
- (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx))
+ let ctx = {off= (-l+ctx.off) ; arg=arg} in
+ do_make_if_out
+ (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx))
- let do_make_if_in h arg ifso ifno =
- Arg.make_if (Arg.make_isin h arg) ifso ifno
+ let do_make_if_in h arg ifso ifno =
+ Arg.make_if (Arg.make_isin h arg) ifso ifno
- let make_if_in ctx l d mk_ifso mk_ifno = match l with
+ let make_if_in ctx l d mk_ifso mk_ifno = match l with
| 0 ->
do_make_if_in
(Arg.make_const d) ctx.arg (mk_ifso ctx) (mk_ifno ctx)
@@ -596,282 +596,282 @@ and enum top cases =
Arg.bind
(Arg.make_offset ctx.arg (-l))
(fun arg ->
- let ctx = {off= (-l+ctx.off) ; arg=arg} in
- do_make_if_in
- (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx))
+ let ctx = {off= (-l+ctx.off) ; arg=arg} in
+ do_make_if_in
+ (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx))
- let rec c_test ctx ({cases=cases ; actions=actions} as s) =
- let lcases = Array.length cases in
- assert(lcases > 0) ;
- if lcases = 1 then
- actions.(get_act cases 0) ctx
+ let rec c_test ctx ({cases=cases ; actions=actions} as s) =
+ let lcases = Array.length cases in
+ assert(lcases > 0) ;
+ if lcases = 1 then
+ actions.(get_act cases 0) ctx
- else begin
+ else begin
- let w,_c = opt_count false cases in
+ let w,_c = opt_count false cases in
(*
Printf.fprintf stderr
"off=%d tactic=%a for %a\n"
ctx.off pret w pcases cases ;
*)
- match w with
- | No -> actions.(get_act cases 0) ctx
- | Inter (i,j) ->
- let low,high,inside, outside = coupe_inter i j cases in
- let _,(cinside,_) = opt_count false inside
- and _,(coutside,_) = opt_count false outside in
-(* Costs are retrieved to put the code with more remaining tests
- in the privileged (positive) branch of ``if'' *)
- if low=high then begin
- if less_tests coutside cinside then
- make_if_eq
- ctx.arg
- (low+ctx.off)
- (c_test ctx {s with cases=inside})
- (c_test ctx {s with cases=outside})
- else
+ match w with
+ | No -> actions.(get_act cases 0) ctx
+ | Inter (i,j) ->
+ let low,high,inside, outside = coupe_inter i j cases in
+ let _,(cinside,_) = opt_count false inside
+ and _,(coutside,_) = opt_count false outside in
+ (* Costs are retrieved to put the code with more remaining tests
+ in the privileged (positive) branch of ``if'' *)
+ if low=high then begin
+ if less_tests coutside cinside then
+ make_if_eq
+ ctx.arg
+ (low+ctx.off)
+ (c_test ctx {s with cases=inside})
+ (c_test ctx {s with cases=outside})
+ else
+ make_if_ne
+ ctx.arg
+ (low+ctx.off)
+ (c_test ctx {s with cases=outside})
+ (c_test ctx {s with cases=inside})
+ end else begin
+ if less_tests coutside cinside then
+ make_if_in
+ ctx
+ (low+ctx.off)
+ (high-low)
+ (fun ctx -> c_test ctx {s with cases=inside})
+ (fun ctx -> c_test ctx {s with cases=outside})
+ else
+ make_if_out
+ ctx
+ (low+ctx.off)
+ (high-low)
+ (fun ctx -> c_test ctx {s with cases=outside})
+ (fun ctx -> c_test ctx {s with cases=inside})
+ end
+ | Sep i ->
+ let lim,left,right = coupe cases i in
+ let _,(cleft,_) = opt_count false left
+ and _,(cright,_) = opt_count false right in
+ let left = {s with cases=left}
+ and right = {s with cases=right} in
+
+ if i=1 && (lim+ctx.off)=1 && get_low cases 0+ctx.off=0 then
make_if_ne
- ctx.arg
- (low+ctx.off)
- (c_test ctx {s with cases=outside})
- (c_test ctx {s with cases=inside})
- end else begin
- if less_tests coutside cinside then
- make_if_in
- ctx
- (low+ctx.off)
- (high-low)
- (fun ctx -> c_test ctx {s with cases=inside})
- (fun ctx -> c_test ctx {s with cases=outside})
+ ctx.arg 0
+ (c_test ctx right) (c_test ctx left)
+ else if less_tests cright cleft then
+ make_if_lt
+ ctx.arg (lim+ctx.off)
+ (c_test ctx left) (c_test ctx right)
else
- make_if_out
- ctx
- (low+ctx.off)
- (high-low)
- (fun ctx -> c_test ctx {s with cases=outside})
- (fun ctx -> c_test ctx {s with cases=inside})
- end
- | Sep i ->
- let lim,left,right = coupe cases i in
- let _,(cleft,_) = opt_count false left
- and _,(cright,_) = opt_count false right in
- let left = {s with cases=left}
- and right = {s with cases=right} in
-
- if i=1 && (lim+ctx.off)=1 && get_low cases 0+ctx.off=0 then
- make_if_ne
- ctx.arg 0
- (c_test ctx right) (c_test ctx left)
- else if less_tests cright cleft then
- make_if_lt
- ctx.arg (lim+ctx.off)
- (c_test ctx left) (c_test ctx right)
- else
- make_if_ge
- ctx.arg (lim+ctx.off)
- (c_test ctx right) (c_test ctx left)
-
- end
-
-
-(* Minimal density of switches *)
-let theta = ref 0.33333
-
-(* Minimal number of tests to make a switch *)
-let switch_min = ref 3
-
-(* Particular case 0, 1, 2 *)
-let particular_case cases i j =
- j-i = 2 &&
- (let l1,_h1,act1 = cases.(i)
- and l2,_h2,_act2 = cases.(i+1)
- and l3,h3,act3 = cases.(i+2) in
- l1+1=l2 && l2+1=l3 && l3=h3 &&
- act1 <> act3)
-
-let approx_count cases i j =
- let l = j-i+1 in
- if l < !cut then
- let _,(_,{n=ntests}) = opt_count false (Array.sub cases i l) in
- ntests
- else
- l-1
-
-(* Sends back a boolean that says whether is switch is worth or not *)
-
-let dense {cases} i j =
- if i=j then true
- else
- let l,_,_ = cases.(i)
- and _,h,_ = cases.(j) in
- let ntests = approx_count cases i j in
+ make_if_ge
+ ctx.arg (lim+ctx.off)
+ (c_test ctx right) (c_test ctx left)
+
+ end
+
+
+ (* Minimal density of switches *)
+ let theta = ref 0.33333
+
+ (* Minimal number of tests to make a switch *)
+ let switch_min = ref 3
+
+ (* Particular case 0, 1, 2 *)
+ let particular_case cases i j =
+ j-i = 2 &&
+ (let l1,_h1,act1 = cases.(i)
+ and l2,_h2,_act2 = cases.(i+1)
+ and l3,h3,act3 = cases.(i+2) in
+ l1+1=l2 && l2+1=l3 && l3=h3 &&
+ act1 <> act3)
+
+ let approx_count cases i j =
+ let l = j-i+1 in
+ if l < !cut then
+ let _,(_,{n=ntests}) = opt_count false (Array.sub cases i l) in
+ ntests
+ else
+ l-1
+
+ (* Sends back a boolean that says whether is switch is worth or not *)
+
+ let dense {cases} i j =
+ if i=j then true
+ else
+ let l,_,_ = cases.(i)
+ and _,h,_ = cases.(j) in
+ let ntests = approx_count cases i j in
(*
(ntests+1) >= theta * (h-l+1)
*)
- particular_case cases i j ||
- (ntests >= !switch_min &&
- float_of_int ntests +. 1.0 >=
- !theta *. (float_of_int h -. float_of_int l +. 1.0))
-
-(* Compute clusters by dynamic programming
- Adaptation of the correction to Bernstein
- ``Correction to `Producing Good Code for the Case Statement' ''
- S.K. Kannan and T.A. Proebsting
- Software Practice and Experience Vol. 24(2) 233 (Feb 1994)
-*)
+ particular_case cases i j ||
+ (ntests >= !switch_min &&
+ float_of_int ntests +. 1.0 >=
+ !theta *. (float_of_int h -. float_of_int l +. 1.0))
+
+ (* Compute clusters by dynamic programming
+ Adaptation of the correction to Bernstein
+ ``Correction to `Producing Good Code for the Case Statement' ''
+ S.K. Kannan and T.A. Proebsting
+ Software Practice and Experience Vol. 24(2) 233 (Feb 1994)
+ *)
-let comp_clusters s =
- let len = Array.length s.cases in
- let min_clusters = Array.make len max_int
- and k = Array.make len 0 in
- let get_min i = if i < 0 then 0 else min_clusters.(i) in
-
- for i = 0 to len-1 do
- for j = 0 to i do
- if
- dense s j i &&
- get_min (j-1) + 1 < min_clusters.(i)
- then begin
- k.(i) <- j ;
- min_clusters.(i) <- get_min (j-1) + 1
- end
+ let comp_clusters s =
+ let len = Array.length s.cases in
+ let min_clusters = Array.make len max_int
+ and k = Array.make len 0 in
+ let get_min i = if i < 0 then 0 else min_clusters.(i) in
+
+ for i = 0 to len-1 do
+ for j = 0 to i do
+ if
+ dense s j i &&
+ get_min (j-1) + 1 < min_clusters.(i)
+ then begin
+ k.(i) <- j ;
+ min_clusters.(i) <- get_min (j-1) + 1
+ end
+ done ;
done ;
- done ;
- min_clusters.(len-1),k
-
-(* Assume j > i *)
-let make_switch loc {cases=cases ; actions=actions} i j =
- let ll,_,_ = cases.(i)
- and _,hh,_ = cases.(j) in
- let tbl = Array.make (hh-ll+1) 0
- and t = Hashtbl.create 17
- and index = ref 0 in
- let get_index act =
- try
- Hashtbl.find t act
- with
- | Not_found ->
- let i = !index in
- incr index ;
- Hashtbl.add t act i ;
- i in
-
- for k=i to j do
- let l,h,act = cases.(k) in
- let index = get_index act in
- for kk=l-ll to h-ll do
- tbl.(kk) <- index
- done
- done ;
- let acts = Array.make !index actions.(0) in
- Hashtbl.iter
- (fun act i -> acts.(i) <- actions.(act))
- t ;
- (fun ctx ->
- match -ll-ctx.off with
- | 0 -> Arg.make_switch loc ctx.arg tbl acts
- | _ ->
- Arg.bind
- (Arg.make_offset ctx.arg (-ll-ctx.off))
- (fun arg -> Arg.make_switch loc arg tbl acts))
-
-
-let make_clusters loc ({cases=cases ; actions=actions} as s) n_clusters k =
- let len = Array.length cases in
- let r = Array.make n_clusters (0,0,0)
- and t = Hashtbl.create 17
- and index = ref 0
- and bidon = ref (Array.length actions) in
- let get_index act =
- try
- let i,_ = Hashtbl.find t act in
- i
- with
- | Not_found ->
- let i = !index in
- incr index ;
- Hashtbl.add
- t act
- (i,(fun _ -> actions.(act))) ;
+ min_clusters.(len-1),k
+
+ (* Assume j > i *)
+ let make_switch loc {cases=cases ; actions=actions} i j =
+ let ll,_,_ = cases.(i)
+ and _,hh,_ = cases.(j) in
+ let tbl = Array.make (hh-ll+1) 0
+ and t = Hashtbl.create 17
+ and index = ref 0 in
+ let get_index act =
+ try
+ Hashtbl.find t act
+ with
+ | Not_found ->
+ let i = !index in
+ incr index ;
+ Hashtbl.add t act i ;
+ i in
+
+ for k=i to j do
+ let l,h,act = cases.(k) in
+ let index = get_index act in
+ for kk=l-ll to h-ll do
+ tbl.(kk) <- index
+ done
+ done ;
+ let acts = Array.make !index actions.(0) in
+ Hashtbl.iter
+ (fun act i -> acts.(i) <- actions.(act))
+ t ;
+ (fun ctx ->
+ match -ll-ctx.off with
+ | 0 -> Arg.make_switch loc ctx.arg tbl acts
+ | _ ->
+ Arg.bind
+ (Arg.make_offset ctx.arg (-ll-ctx.off))
+ (fun arg -> Arg.make_switch loc arg tbl acts))
+
+
+ let make_clusters loc ({cases=cases ; actions=actions} as s) n_clusters k =
+ let len = Array.length cases in
+ let r = Array.make n_clusters (0,0,0)
+ and t = Hashtbl.create 17
+ and index = ref 0
+ and bidon = ref (Array.length actions) in
+ let get_index act =
+ try
+ let i,_ = Hashtbl.find t act in
i
- and add_index act =
- let i = !index in
- incr index ;
- incr bidon ;
- Hashtbl.add t !bidon (i,act) ;
- i in
-
- let rec zyva j ir =
- let i = k.(j) in
- begin if i=j then
- let l,h,act = cases.(i) in
- r.(ir) <- (l,h,get_index act)
- else (* assert i < j *)
- let l,_,_ = cases.(i)
- and _,h,_ = cases.(j) in
- r.(ir) <- (l,h,add_index (make_switch loc s i j))
- end ;
- if i > 0 then zyva (i-1) (ir-1) in
+ with
+ | Not_found ->
+ let i = !index in
+ incr index ;
+ Hashtbl.add
+ t act
+ (i,(fun _ -> actions.(act))) ;
+ i
+ and add_index act =
+ let i = !index in
+ incr index ;
+ incr bidon ;
+ Hashtbl.add t !bidon (i,act) ;
+ i in
+
+ let rec zyva j ir =
+ let i = k.(j) in
+ begin if i=j then
+ let l,h,act = cases.(i) in
+ r.(ir) <- (l,h,get_index act)
+ else (* assert i < j *)
+ let l,_,_ = cases.(i)
+ and _,h,_ = cases.(j) in
+ r.(ir) <- (l,h,add_index (make_switch loc s i j))
+ end ;
+ if i > 0 then zyva (i-1) (ir-1) in
- zyva (len-1) (n_clusters-1) ;
- let acts = Array.make !index (fun _ -> assert false) in
- Hashtbl.iter (fun _ (i,act) -> acts.(i) <- act) t ;
- {cases = r ; actions = acts}
-;;
+ zyva (len-1) (n_clusters-1) ;
+ let acts = Array.make !index (fun _ -> assert false) in
+ Hashtbl.iter (fun _ (i,act) -> acts.(i) <- act) t ;
+ {cases = r ; actions = acts}
+ ;;
-let do_zyva loc (low,high) arg cases actions =
- let old_ok = !ok_inter in
- ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ;
- if !ok_inter <> old_ok then Hashtbl.clear t ;
+ let do_zyva loc (low,high) arg cases actions =
+ let old_ok = !ok_inter in
+ ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ;
+ if !ok_inter <> old_ok then Hashtbl.clear t ;
- let s = {cases=cases ; actions=actions} in
+ let s = {cases=cases ; actions=actions} in
(*
Printf.eprintf "ZYVA: %B [low=%i,high=%i]\n" !ok_inter low high ;
pcases stderr cases ;
prerr_endline "" ;
*)
- let n_clusters,k = comp_clusters s in
- let clusters = make_clusters loc s n_clusters k in
- c_test {arg=arg ; off=0} clusters
-
-let abstract_shared actions =
- let handlers = ref (fun x -> x) in
- let actions =
- Array.map
- (fun act -> match act with
- | Single act -> act
- | Shared act ->
- let i,h = Arg.make_catch act in
- let oh = !handlers in
- handlers := (fun act -> h (oh act)) ;
- Arg.make_exit i)
- actions in
- !handlers,actions
-
-let zyva loc lh arg cases actions =
- assert (Array.length cases > 0) ;
- let actions = actions.act_get_shared () in
- let hs,actions = abstract_shared actions in
- hs (do_zyva loc lh arg cases actions)
-
-and test_sequence arg cases actions =
- assert (Array.length cases > 0) ;
- let actions = actions.act_get_shared () in
- let hs,actions = abstract_shared actions in
- let old_ok = !ok_inter in
- ok_inter := false ;
- if !ok_inter <> old_ok then Hashtbl.clear t ;
- let s =
- {cases=cases ;
- actions=Array.map (fun act -> (fun _ -> act)) actions} in
+ let n_clusters,k = comp_clusters s in
+ let clusters = make_clusters loc s n_clusters k in
+ c_test {arg=arg ; off=0} clusters
+
+ let abstract_shared actions =
+ let handlers = ref (fun x -> x) in
+ let actions =
+ Array.map
+ (fun act -> match act with
+ | Single act -> act
+ | Shared act ->
+ let i,h = Arg.make_catch act in
+ let oh = !handlers in
+ handlers := (fun act -> h (oh act)) ;
+ Arg.make_exit i)
+ actions in
+ !handlers,actions
+
+ let zyva loc lh arg cases actions =
+ assert (Array.length cases > 0) ;
+ let actions = actions.act_get_shared () in
+ let hs,actions = abstract_shared actions in
+ hs (do_zyva loc lh arg cases actions)
+
+ and test_sequence arg cases actions =
+ assert (Array.length cases > 0) ;
+ let actions = actions.act_get_shared () in
+ let hs,actions = abstract_shared actions in
+ let old_ok = !ok_inter in
+ ok_inter := false ;
+ if !ok_inter <> old_ok then Hashtbl.clear t ;
+ let s =
+ {cases=cases ;
+ actions=Array.map (fun act -> (fun _ -> act)) actions} in
(*
Printf.eprintf "SEQUENCE: %B\n" !ok_inter ;
pcases stderr cases ;
prerr_endline "" ;
*)
- hs (c_test {arg=arg ; off=0} s)
-;;
+ hs (c_test {arg=arg ; off=0} s)
+ ;;
end