let phase2 f ~info = 
  let n_blocks = Array.length f.body in
  let new_body = Array.make n_blocks [] in
  for i = 0 to n_blocks - 1 do
    let body_instrs = convert_block ~f ~info i in
    let phi_assignments = make_phi_assigns info.(i).phi_assignments_at_bottom in
    let main, last_branch = separate_last_branch body_instrs in
    (* insert unconditional GOTO to skip inserted trampoline blocks *)
    let last_branch = 
      if last_branch = [] && i < n_blocks - 1 && info.(i + 1).trampoline_blocks <> []
      then
        [make_il0 (IL0stmtGoto(label_direct (i + 1)))]
      else
        last_branch
    in
    let phi = make_phi_assigns info.(i).phi_assignments_at_bottom in
    let make_trampoline from assigns = 
      (make_il0 (IL0stmtLabel (label_trampoline from i))) ::
      [make_phi_assigns assigns]
    in 
    let trampoline_instrs = 
      let rec iter = function
          [] -> []
        | [from, assigns] -> make_trampoline from assigns
        | (from, assigns)::tl -> 
            make_trampoline from assigns @ (make_il0 (IL0stmtGoto (label_direct i)) :: iter tl)
      in
      iter info.(i).trampoline_blocks
    in
    let main_label = [make_il0 (IL0stmtLabel (label_direct i))] in
    new_body.(i) <- trampoline_instrs @ main_label @ main @ phi :: last_branch
  done;
  let l = Array.fold_right 
      (fun l r -> l @ r) new_body []
  in
  enclose_sequence l