Section PRESERVATION.
Variable prog: program.
Variable tprog : program.
Hypothesis TRANSF: match_prog prog tprog.
Let ge := Genv.globalenv prog.
Let tge := Genv.globalenv tprog.
Proof (Genv.find_symbol_match TRANSF).
Proof (Genv.senv_match TRANSF).
Proof (Genv.find_funct_match TRANSF).
Proof (Genv.find_funct_ptr_match TRANSF).
Definition transf_function' (f: function) (approxs: PMap.t numbering) : function :=
mkfunction
f.(fn_sig)
f.(fn_params)
f.(fn_stacksize)
(transf_code approxs f.(fn_code))
f.(fn_entrypoint).
Definition regs_lessdef (rs1 rs2: regset) : Prop :=
forall r, Val.lessdef (rs1#r) (rs2#r).
(** The proof of semantic preservation is a simulation argument using diagrams of the following form: << st1 --------------- st2 |                   | t|                   |t |                   | v                   v st1'--------------- st2' >> Left: RTL execution in the original program.  Right: RTL execution in the optimized program.  Precondition (top) and postcondition (bottom): agreement between the states, including the fact that the numbering at [pc] (returned by the static analysis) is satisfiable. *)
Definition analyze (cu: program) (f: function) :=
CSE.analyze f (vanalyze (romem_for cu) f).
Inductive match_stackframes: list stackframe -> list stackframe -> Prop :=
| match_stackframes_nil:
match_stackframes nil nil
| match_stackframes_cons:
forall res sp pc rs f s rs' s' cu approx
(LINK: linkorder cu prog)
(ANALYZE: analyze cu f = Some approx)
(SAT: forall v m, exists valu, numbering_holds valu ge sp (rs#res <- v) m approx!!pc)
(RLD: regs_lessdef rs rs')
(STACKS: match_stackframes s s'),
match_stackframes
(Stackframe res f sp pc rs :: s)
(Stackframe res (transf_function' f approx) sp pc rs' :: s').
Inductive match_states: state -> state -> Prop :=
| match_states_intro:
forall s sp pc rs m s' rs' m' f cu approx
(LINK: linkorder cu prog)
(ANALYZE: analyze cu f = Some approx)
(SAT: exists valu, numbering_holds valu ge sp rs m approx!!pc)
(RLD: regs_lessdef rs rs')
(MEXT: Mem.extends m m')
(STACKS: match_stackframes s s'),
match_states (State s f sp pc rs m)
(State s' (transf_function' f approx) sp pc rs' m')
| match_states_call:
forall s f tf args m s' args' m' cu
(LINK: linkorder cu prog)
(STACKS: match_stackframes s s')
(TFD: transf_fundef (romem_for cu) f = OK tf)
(ARGS: Val.lessdef_list args args')
(MEXT: Mem.extends m m'),
match_states (Callstate s f args m)
(Callstate s' tf args' m')
| match_states_return:
forall s s' v v' m m'
(STACK: match_stackframes s s')
(RES: Val.lessdef v v')
(MEXT: Mem.extends m m'),
match_states (Returnstate s v m)
(Returnstate s' v' m').
Ltac TransfInstr :=
match goal with
| H1: (PTree.get ?pc ?c = Some ?instr), f: function, approx: PMap.t numbering |- _ =>
cut ((transf_function' f approx).(fn_code)!pc = Some(transf_instr approx!!pc instr));
[ simpl transf_instr
| unfold transf_function', transf_code; simpl; rewrite PTree.gmap;
unfold option_map; rewrite H1; reflexivity ]
end.
(** The proof of simulation is a case analysis over the transition in the source code. *)

Lemma transf_step_correct:
forall s1 t s2, step ge s1 t s2 ->
forall s1' (MS: match_states s1 s1') (SOUND: sound_state prog s1),
exists s2', step tge s1' t s2' /\ match_states s2 s2'.