let eliminate_unreachable f =
    let length = Array.length f in
    let mark = Array.create length false in
    let rec visit i =
        if not mark.(i) then begin
            mark.(i) <- true;
            let rec check = function
                [] -> visit (i + 1)
              |        i::l -> match i.il1_t with
                  IL1stmtDeclAutoScalar _ |
                  IL1stmtDeclBulk _ |
                  IL1stmtDefTemp _ |
                  IL1stmtReadToTemp _ |
                  IL1stmtWrite _ |
                  IL1stmtParallel _ -> check l
                | IL1stmtIf( _, _, n ) -> visit n; check l
                | IL1stmtSwitch( _, jump_table ) ->
                    List.iter (function _, n -> visit n) jump_table
                | IL1stmtGoto n -> visit n
                | IL1stmtReturn _ -> ()
                | IL1stmtSequence _ -> assert false
            in
            check f.(i).code
        end
    in
    visit 0;
    let rename_table = Array.create length (-1) in
    let reverse_table = Array.create length (-1) in
    let rename i = rename_table.(i) in
    let j = ref 0 in
    for i = 0 to length - 1 do
        if mark.(i) then begin
            rename_table.(i) <- !j;
            reverse_table.(!j) <- i;
            incr j
        end
    done;
    let new_length = !j in
    let rename_code i1 = 
      let mk i = { i1 with il1_t = i } in
      match i1.il1_t with
      | IL1stmtIf( v, e, n ) -> mk (IL1stmtIf( v, e, rename n ))
      | IL1stmtSwitch( e, jump_table ) ->
          mk (IL1stmtSwitch( e, List.map (function c, n -> c, rename n) jump_table ))
      | IL1stmtGoto n -> mk (IL1stmtGoto (rename n))
      |        _ -> i1
    in
    let rename_basic_block i =
        let j = reverse_table.(i) in
        {
          predecessor = List.map rename f.(j).predecessor;
          successor = List.map rename f.(j).successor;
          immediate_dominator = f.(j).immediate_dominator;
          code = List.map rename_code f.(j).code
        }
    in
    Array.init new_length rename_basic_block