let make_basic_block stmt_list_list =
let length = List.length stmt_list_list in
let successor = Array.create length [] in
let predecessor = Array.create length [] in
let jump_destination = Hashtbl.create 32 in
let add_control_flow i j =
if not (List.mem j successor.(i)) then
successor.(i) <- j::successor.(i);
if not (List.mem i predecessor.(j)) then
predecessor.(j) <- i::predecessor.(j)
in
let add_jump_destination s i =
Hashtbl.add jump_destination s i
in
let get_jump_destination s =
Hashtbl.find jump_destination s
in
let code = Array.of_list stmt_list_list in
for i = 0 to length - 1 do
let set_jump_destination = function
{ il0_t = IL0stmtLabel s } -> add_jump_destination s i
| _ -> ()
in
List.iter set_jump_destination code.(i)
done;
for i = 0 to length - 1 do
let rec continue = function
[] ->
if i + 1 < length then
add_control_flow i (i + 1)
| stmt::l -> match stmt.il0_t with
IL0stmtIf( _, _, s ) ->
add_control_flow i (get_jump_destination s);
continue l
| IL0stmtSwitch( _, jump_table ) ->
List.iter (function _, s -> add_control_flow i (get_jump_destination s)) jump_table
| IL0stmtGoto s ->
add_control_flow i (get_jump_destination s)
| IL0stmtReturn _ -> ()
| _ -> continue l
in
continue code.(i)
done;
let rec il1s_of_il0s = function
[] -> []
| stmt0::l ->
let make_il1 i =
{ il1_defines = stmt0.il0_defines;
il1_depends = stmt0.il0_depends;
il1_t = i } in
match stmt0.il0_t with
IL0stmtDefTemp(v,ty,ex) -> make_il1 (IL1stmtDefTemp(v,ty,ex))::il1s_of_il0s l
| IL0stmtReadToTemp(v,ty,lv,fs) -> make_il1 (IL1stmtReadToTemp(v,ty,lv,fs))::il1s_of_il0s l
| IL0stmtWrite(lv,fs,v) -> make_il1 (IL1stmtWrite(lv,fs,v))::il1s_of_il0s l
| IL0stmtSequence(is) -> make_il1 (IL1stmtSequence(il1s_of_il0s is))::il1s_of_il0s l
| IL0stmtParallel(is) -> make_il1 (IL1stmtParallel(il1s_of_il0s is))::il1s_of_il0s l
| IL0stmtLabel _ -> il1s_of_il0s l
| IL0stmtDeclAutoScalar( c, t, s, i ) -> make_il1 (IL1stmtDeclAutoScalar( c, t, s, i ))::il1s_of_il0s l
| IL0stmtDeclBulk( c, t, s, i ) -> make_il1 (IL1stmtDeclBulk( c, t, s, i ))::il1s_of_il0s l
| IL0stmtIf( f, e, s ) -> make_il1 (IL1stmtIf( f, e, get_jump_destination s ))::il1s_of_il0s l
| IL0stmtSwitch( e, jump_table ) ->
make_il1 (IL1stmtSwitch( e, List.map (function c, s -> c, get_jump_destination s) jump_table ))::[]
| IL0stmtGoto s -> make_il1 (IL1stmtGoto (get_jump_destination s))::[]
| IL0stmtReturn e -> make_il1 (IL1stmtReturn e)::[]
in
let make_basic_block i =
{
predecessor = List.sort compare predecessor.(i);
successor = List.sort compare successor.(i);
immediate_dominator = -1;
code = il1s_of_il0s code.(i)
}
in
Array.init length make_basic_block