(** The relation [env_match] holds between two environments [e1] and [e2]
    if they assign the same values to all registers not in the adherence set. *)

Definition env_match (e1 e2: env) : Prop :=
  forall r, no_adherence r -> e1 r = e2 r.

(* Specifications: *)
Lemma weak_update_match: forall e1 e2 s d, (In s (srcs mu) \/ is_temp s) -> (In d (dests mu) \/ is_temp d) -> env_match e1 e2 -> env_match (update d (e1 s) e1) (weak_update d (e2 s) e2).
Lemma weak_exec_seq_match: forall m e1 e2, (forall s, In s (srcs m) -> In s (srcs mu) \/ is_temp s) -> (forall d, In d (dests m) -> In d (dests mu) \/ is_temp d) -> env_match e1 e2 -> env_match (exec_seq m e1) (weak_exec_seq m e2).
Theorem parmove2_correctness_with_overlap: forall sl dl, List.length sl = List.length dl -> (forall r, In r sl -> disjoint_temps r) -> (forall r, In r dl -> disjoint_temps r) -> pairwise_disjoint dl -> (forall s d, In s sl -> In d dl -> no_overlap s d) -> (forall t1 t2, is_temp t1 -> is_temp t2 -> no_overlap t1 t2) -> forall e, let e' := weak_exec_seq (parmove2 sl dl) e in List.map e' dl = List.map e sl /\ forall r, disjoint_list r dl -> disjoint_temps r -> e' r = e r.
Lemma weak_update_match: forall e1 e2 s d, (In s (srcs mu) \/ is_temp s) -> (In d (dests mu) \/ is_temp d) -> env_match e1 e2 -> env_match (update d (e1 s) e1) (weak_update d (e2 s) e2).
Lemma weak_exec_seq_match: forall m e1 e2, (forall s, In s (srcs m) -> In s (srcs mu) \/ is_temp s) -> (forall d, In d (dests m) -> In d (dests mu) \/ is_temp d) -> env_match e1 e2 -> env_match (exec_seq m e1) (weak_exec_seq m e2).
Theorem parmove2_correctness_with_overlap: forall sl dl, List.length sl = List.length dl -> (forall r, In r sl -> disjoint_temps r) -> (forall r, In r dl -> disjoint_temps r) -> pairwise_disjoint dl -> (forall s d, In s sl -> In d dl -> no_overlap s d) -> (forall t1 t2, is_temp t1 -> is_temp t2 -> no_overlap t1 t2) -> forall e, let e' := weak_exec_seq (parmove2 sl dl) e in List.map e' dl = List.map e sl /\ forall r, disjoint_list r dl -> disjoint_temps r -> e' r = e r.