(** The proof of semantic preservation is a simulation argument based on diagrams of the following form: << st1 --------------- st2 |                   | t|                  ?|t |                   | v                   v st1'--------------- st2' >> The [match_states] predicate, defined below, captures the precondition between states [st1] and [st2], as well as the postcondition between [st1'] and [st2'].  One transition in the source code (left) can correspond to zero or one transition in the transformed code (right).  The "zero transition" case occurs when executing a [Lgoto] instruction in the source code that has been removed by tunneling.  In the definition of [match_states], what changes between the original and transformed codes is mainly the control-flow (in particular, the current program point [pc]), but also some values and memory states, since some [Vundef] values can become more defined as a consequence of eliminating useless [Lcond] instructions. *)
Definition tunneled_block (f: function) (b: bblock) :=
tunnel_block (record_gotos f) b.
Definition tunneled_code (f: function) :=
PTree.map1 (tunneled_block f) (fn_code f).
Definition locmap_lessdef (ls1 ls2: locset) : Prop :=
forall l, Val.lessdef (ls1 l) (ls2 l).
Inductive match_stackframes: stackframe -> stackframe -> Prop :=
| match_stackframes_intro:
forall f sp ls0 bb tls0,
locmap_lessdef ls0 tls0 ->
match_stackframes
(Stackframe f sp ls0 bb)
(Stackframe (tunnel_function f) sp tls0 (tunneled_block f bb)).
Inductive match_states: state -> state -> Prop :=
| match_states_intro:
forall s f sp pc ls m ts tls tm
(STK: list_forall2 match_stackframes s ts)
(LS: locmap_lessdef ls tls)
(MEM: Mem.extends m tm),
match_states (State s f sp pc ls m)
(State ts (tunnel_function f) sp (branch_target f pc) tls tm)
| match_states_block:
forall s f sp bb ls m ts tls tm
(STK: list_forall2 match_stackframes s ts)
(LS: locmap_lessdef ls tls)
(MEM: Mem.extends m tm),
match_states (Block s f sp bb ls m)
(Block ts (tunnel_function f) sp (tunneled_block f bb) tls tm)
| match_states_interm:
forall s f sp pc bb ls m ts tls tm
(STK: list_forall2 match_stackframes s ts)
(LS: locmap_lessdef ls tls)
(MEM: Mem.extends m tm),
match_states (Block s f sp (Lbranch pc :: bb) ls m)
(State ts (tunnel_function f) sp (branch_target f pc) tls tm)
| match_states_call:
forall s f ls m ts tls tm
(STK: list_forall2 match_stackframes s ts)
(LS: locmap_lessdef ls tls)
(MEM: Mem.extends m tm),
match_states (Callstate s f ls m)
(Callstate ts (tunnel_fundef f) tls tm)
| match_states_return:
forall s ls m ts tls tm
(STK: list_forall2 match_stackframes s ts)
(LS: locmap_lessdef ls tls)
(MEM: Mem.extends m tm),
match_states (Returnstate s ls m)
(Returnstate ts tls tm).
(** Properties of [locmap_lessdef] *)

Lemma locmap_set_lessdef:
forall ls1 ls2 v1 v2 l,
locmap_lessdef ls1 ls2 -> Val.lessdef v1 v2 -> locmap_lessdef (Locmap.set l v1 ls1) (Locmap.set l v2 ls2).