let rec local_opt_base_block base_block =
  let opt_instr2 x y =
    match (x, y) with
      | Unspill(_, v1), Mov_i(v1', _)
      | Mov_i(v1, _), Mov_i(v1', _) when get_var_reg v1' = get_var_reg v1 -> None
      | _ -> Some x
  in
    (* TODO: add some more *)
  let opt_instr = function
    | Add_i(v1, v2, v3) when get_var_value v3 = Some (Int 0) -> None
    | Div_i(v1, v2, v3) when get_var_value v3 = Some (Int 1) -> None
    | Div_i(v1, v2, v3) when get_var_value v2 = Some (Int 0) -> None
    | Sub_i(v1, v2, v3) when get_var_value v3 = Some (Int 0) -> None
    | x -> Some x
  in
  let rec opt_instrs = function
    | x :: y :: t ->
        (
          match opt_instr2 x y with
            | None -> opt_instrs (y :: t)
            | Some x' when x' == x -> (opt_instrs [x']) @ (opt_instrs (y :: t))
            | Some x' -> opt_instrs (x' :: y :: t)
        );
    | [x] ->
        (
          match opt_instr x with
            | Some x' -> [x']
            | None -> []
        )
    | [] -> []
  in
    (
      match base_block.bb_link with
        | If(_, b1, b2, b3) ->
            local_opt_base_block b1;
            local_opt_base_block b2;
            local_opt_base_block b3
        | While(_, be, b1, b2) ->
            local_opt_base_block be;
            local_opt_base_block b1;
            local_opt_base_block b2
        | End -> ()
    );
    base_block.bb_block <- opt_instrs base_block.bb_block