let hoist_declaration max_temp_id f =
    let size = Array.length f in
    let declaration = ref [] in
    let variable_counter = ref (max_temp_id + 1) in
    let new_temp_id() =
        let n = !variable_counter in
        incr variable_counter;
        n
    in
    let ctt_zero t = ILexpUndefined in
    let make_null_temp id t = 
      { il1_t = IL1stmtDefTemp( id, t, ctt_zero t );
        il1_depends = Set_list.empty;
        il1_defines = Set_list.singleton id }
    in
    let rec continue = function
        [] -> []
      |        i::l ->
          match i.il1_t with
              IL1stmtDeclAutoScalar( c, t, s, None ) ->
                declaration := ( c, t, s )::!declaration;
                let n = new_temp_id() in
                (make_null_temp n t)
                ::{ i with il1_t = IL1stmtWriteILlvVar( s, t ), [], n ) }
                ::continue l
            | IL1stmtDeclAutoScalar( c, t, s, Some v ) ->
                declaration := ( c, t, s )::!declaration;
                { i with il1_t = IL1stmtWriteILlvVar( s, t ), [], v ) }
                ::continue l
            | IL1stmtDeclBulk( c, t, s, _ ) ->
                declaration := ( c, t, s )::!declaration;
                i::continue l
            | IL1stmtSequence statement_list ->
                let i =
                    { i with il1_t = IL1stmtSequence (continue statement_list) }
                in
                i::continue l
            | IL1stmtParallel statement_list ->
                let i =
                    { i with il1_t = IL1stmtParallel (continue statement_list) }
                in
                i::continue l
            | _ ->
                i::continue l
    in
    for i = 0 to size - 1 do
        f.(i) <- { f.(i) with code = continue f.(i).code }
    done;
    !declaration