(** Correctness of clean-up *)
Inductive match_stackframes: stackframe -> stackframe -> Prop :=
| match_stackframe_intro:
forall f sp ls c,
incl c f.(fn_code) ->
match_stackframes
(Stackframe f sp ls c)
(Stackframe (transf_function f) sp ls
(remove_unused_labels (labels_branched_to f.(fn_code)) c)).
Inductive match_states: state -> state -> Prop :=
| match_states_intro:
forall s f sp c ls m ts
(STACKS: list_forall2 match_stackframes s ts)
(INCL: incl c f.(fn_code)),
match_states (State s f sp c ls m)
(State ts (transf_function f) sp (remove_unused_labels (labels_branched_to f.(fn_code)) c) ls m)
| match_states_call:
forall s f ls m ts,
list_forall2 match_stackframes s ts ->
match_states (Callstate s f ls m)
(Callstate ts (transf_fundef f) ls m)
| match_states_return:
forall s ls m ts,
list_forall2 match_stackframes s ts ->
match_states (Returnstate s ls m)
(Returnstate ts ls m).
Definition measure (st: state) : nat :=
match st with
| State s f sp c ls m => List.length c
| _ => O
end.

Lemma transf_initial_states:
forall st1, initial_state prog st1 ->
exists st2, initial_state tprog st2 /\ match_states st1 st2.