let phase1 f = 
  let n_blocks = Array.length f.body in
  let info = Array.init n_blocks
      (fun _ -> 
        { trampoline_blocks = [];
          phi_assignments_at_bottom = [];
        };
      ) in
  for i = 0 to n_blocks - 1 do
    let b = f.body.(i) in
    let bi = info.(i) in
    if b.phi_function = [] then
      ()
    else begin
      let n_pred = List.length b.predecessor in
      for j = 0 to n_pred - 1 do
        let pred = List.nth b.predecessor j in
        let phi_assignments = 
          List.map 
            (fun (target, ty, source_list) -> target, ty, source_list.(j))
            b.phi_function
        in
        if pred <> i - 1 && List.length (f.body.(pred).successor) >= 2 then begin
          (* branch edge is critical: insert trampoline block *)
          bi.trampoline_blocks <- (pred, phi_assignments) :: bi.trampoline_blocks
        end 
        else begin
          assert (info.(pred).phi_assignments_at_bottom = []);
          info.(pred).phi_assignments_at_bottom <- phi_assignments
        end
      done
    end
  done;
  info