From 2ae43be7b9d4118335c9d2cef6e098f9b9f807fe Mon Sep 17 00:00:00 2001 From: xleroy Date: Thu, 9 Feb 2006 14:55:48 +0000 Subject: Initial import of compcert git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- backend/Parallelmove.v | 2529 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2529 insertions(+) create mode 100644 backend/Parallelmove.v (limited to 'backend/Parallelmove.v') diff --git a/backend/Parallelmove.v b/backend/Parallelmove.v new file mode 100644 index 00000000..f95416eb --- /dev/null +++ b/backend/Parallelmove.v @@ -0,0 +1,2529 @@ +(** Translation of parallel moves into sequences of individual moves *) + +(** The ``parallel move'' problem, also known as ``parallel assignment'', + is the following. We are given a list of (source, destination) pairs + of locations. The goal is to find a sequence of elementary + moves ([loc <- loc] assignments) such that, at the end of the sequence, + location [dst] contains the value of location [src] at the beginning of + the sequence, for each ([src], [dst]) pairs in the given problem. + Moreover, other locations should keep their values, except one register + of each type, which can be used as temporaries in the generated sequences. + + The parallel move problem is trivial if the sources and destinations do + not overlap. For instance, +<< + (R1, R2) <- (R3, R4) becomes R1 <- R3; R2 <- R4 +>> + However, arbitrary overlap is allowed between sources and destinations. + This requires some care in ordering the individual moves, as in +<< + (R1, R2) <- (R3, R1) becomes R2 <- R1; R1 <- R3 +>> + Worse, cycles (permutations) can require the use of temporaries, as in +<< + (R1, R2, R3) <- (R2, R3, R1) becomes T <- R1; R1 <- R2; R2 <- R3; R3 <- T; +>> + An amazing fact is that for any parallel move problem, at most one temporary + (or in our case one integer temporary and one float temporary) is needed. + + The development in this section was contributed by Laurence Rideau and + Bernard Serpette. It is described in their paper + ``Coq à la conquête des moulins'', JFLA 2005, + ## + http://www-sop.inria.fr/lemme/Laurence.Rideau/RideauSerpetteJFLA05.ps + ## +*) + +Require Omega. +Require Import Wf_nat. +Require Import Conventions. +Require Import Coqlib. +Require Import Bool_nat. +Require Import TheoryList. +Require Import Bool. +Require Import Arith. +Require Import Peano_dec. +Require Import EqNat. +Require Import Values. +Require Import LTL. +Require Import EqNat. +Require Import Locations. +Require Import AST. + +Section pmov. + +Ltac caseEq name := generalize (refl_equal name); pattern name at -1; case name. +Hint Resolve beq_nat_eq . + +Lemma neq_is_neq: forall (x y : nat), x <> y -> beq_nat x y = false. +Proof. +unfold not; intros. +caseEq (beq_nat x y); auto. +intro. +elim H; auto. +Qed. +Hint Resolve neq_is_neq . + +Lemma app_nil: forall (A : Set) (l : list A), l ++ nil = l. +Proof. +intros A l; induction l as [|a l Hrecl]; auto; simpl; rewrite Hrecl; auto. +Qed. + +Lemma app_cons: + forall (A : Set) (l1 l2 : list A) (a : A), (a :: l1) ++ l2 = a :: (l1 ++ l2). +Proof. +auto. +Qed. + +Lemma app_app: + forall (A : Set) (l1 l2 l3 : list A), l1 ++ (l2 ++ l3) = (l1 ++ l2) ++ l3. +Proof. +intros A l1; induction l1 as [|a l1 Hrecl1]; simpl; auto; intros; + rewrite Hrecl1; auto. +Qed. + +Lemma app_rewrite: + forall (A : Set) (l : list A) (x : A), + (exists y : A , exists r : list A , l ++ (x :: nil) = y :: r ). +Proof. +intros A l x; induction l as [|a l Hrecl]. +exists x; exists (nil (A:=A)); auto. +inversion Hrecl; inversion H. +exists a; exists (l ++ (x :: nil)); auto. +Qed. + +Lemma app_rewrite2: + forall (A : Set) (l l2 : list A) (x : A), + (exists y : A , exists r : list A , l ++ (x :: l2) = y :: r ). +Proof. +intros A l l2 x; induction l as [|a l Hrecl]. +exists x; exists l2; auto. +inversion Hrecl; inversion H. +exists a; exists (l ++ (x :: l2)); auto. +Qed. + +Lemma app_rewriter: + forall (A : Set) (l : list A) (x : A), + (exists y : A , exists r : list A , x :: l = r ++ (y :: nil) ). +Proof. +intros A l x; induction l as [|a l Hrecl]. +exists x; exists (nil (A:=A)); auto. +inversion Hrecl; inversion H. +generalize H0; case x1; simpl; intros; inversion H1. +exists a; exists (x0 :: nil); simpl; auto. +exists x0; exists (a0 :: (a :: l0)); simpl; auto. +Qed. +Hint Resolve app_rewriter . + +Definition Reg := loc. + +Definition T := + fun (r : loc) => + match Loc.type r with Tint => R IT2 | Tfloat => R FT2 end. + +Definition notemporary := fun (r : loc) => forall x, Loc.diff r (T x). + +Definition Move := (Reg * Reg)%type. + +Definition Moves := list Move. + +Definition State := ((Moves * Moves) * Moves)%type. + +Definition StateToMove (r : State) : Moves := + match r with ((t, b), l) => t end. + +Definition StateBeing (r : State) : Moves := + match r with ((t, b), l) => b end. + +Definition StateDone (r : State) : Moves := + match r with ((t, b), l) => l end. + +Fixpoint noRead (p : Moves) (r : Reg) {struct p} : Prop := + match p with + nil => True + | (s, d) :: l => Loc.diff s r /\ noRead l r + end. + +Lemma noRead_app: + forall (l1 l2 : Moves) (r : Reg), + noRead l1 r -> noRead l2 r -> noRead (l1 ++ l2) r. +Proof. +intros; induction l1 as [|a l1 Hrecl1]; simpl; auto. +destruct a. +elim H; intros; split; auto. +Qed. + +Inductive step : State -> State -> Prop := + step_nop: + forall (r : Reg) (t1 t2 l : Moves), + step (t1 ++ ((r, r) :: t2), nil, l) (t1 ++ t2, nil, l) + | step_start: + forall (t1 t2 l : Moves) (m : Move), + step (t1 ++ (m :: t2), nil, l) (t1 ++ t2, m :: nil, l) + | step_push: + forall (t1 t2 b l : Moves) (s d r : Reg), + step + (t1 ++ ((d, r) :: t2), (s, d) :: b, l) + (t1 ++ t2, (d, r) :: ((s, d) :: b), l) + | step_loop: + forall (t b l : Moves) (s d r0 r0ounon : Reg), + step + (t, (s, r0ounon) :: (b ++ ((r0, d) :: nil)), l) + (t, (s, r0ounon) :: (b ++ ((T r0, d) :: nil)), (r0, T r0) :: l) + | step_pop: + forall (t b l : Moves) (s0 d0 sn dn : Reg), + noRead t dn -> + Loc.diff dn s0 -> + step + (t, (sn, dn) :: (b ++ ((s0, d0) :: nil)), l) + (t, b ++ ((s0, d0) :: nil), (sn, dn) :: l) + | step_last: + forall (t l : Moves) (s d : Reg), + noRead t d -> step (t, (s, d) :: nil, l) (t, nil, (s, d) :: l) . +Hint Resolve step_nop step_start step_push step_loop step_pop step_last . + +Fixpoint path (l : Moves) : Prop := + match l with + nil => True + | (s, d) :: l => + match l with + nil => True + | (ss, dd) :: l2 => s = dd /\ path l + end + end. + +Lemma path_pop: forall (m : Move) (l : Moves), path (m :: l) -> path l. +Proof. +simpl; intros m l; destruct m as [ms md]; case l; auto. +intros m0; destruct m0; intros; inversion H; auto. +Qed. + +Fixpoint noWrite (p : Moves) (r : Reg) {struct p} : Prop := + match p with + nil => True + | (s, d) :: l => Loc.diff d r /\ noWrite l r + end. + +Lemma noWrite_pop: + forall (p1 p2 : Moves) (m : Move) (r : Reg), + noWrite (p1 ++ (m :: p2)) r -> noWrite (p1 ++ p2) r. +Proof. +intros; induction p1 as [|a p1 Hrecp1]. +generalize H; simpl; case m; intros; inversion H0; auto. +generalize H; rewrite app_cons; rewrite app_cons. +simpl; case a; intros. +inversion H0; split; auto. +Qed. + +Lemma noWrite_in: + forall (p1 p2 : Moves) (r0 r1 r2 : Reg), + noWrite (p1 ++ ((r1, r2) :: p2)) r0 -> Loc.diff r0 r2. +Proof. +intros; induction p1 as [|a p1 Hrecp1]; simpl; auto. +generalize H; simpl; intros; inversion H0; auto. +apply Loc.diff_sym; auto. +generalize H; rewrite app_cons; simpl; case a; intros. +apply Hrecp1; inversion H0; auto. +Qed. + +Lemma noWrite_swap: + forall (p : Moves) (m1 m2 : Move) (r : Reg), + noWrite (m1 :: (m2 :: p)) r -> noWrite (m2 :: (m1 :: p)) r. +Proof. +intros p m1 m2 r; simpl; case m1; case m2. +intros; inversion H; inversion H1; split; auto. +Qed. + +Lemma noWrite_movFront: + forall (p1 p2 : Moves) (m : Move) (r0 : Reg), + noWrite (p1 ++ (m :: p2)) r0 -> noWrite (m :: (p1 ++ p2)) r0. +Proof. +intros p1 p2 m r0; induction p1 as [|a p1 Hrecp1]; auto. +case a; intros r1 r2; rewrite app_cons; rewrite app_cons. +intros; apply noWrite_swap; rewrite <- app_cons. +simpl in H |-; inversion H; unfold noWrite; fold noWrite; auto. +Qed. + +Lemma noWrite_insert: + forall (p1 p2 : Moves) (m : Move) (r0 : Reg), + noWrite (m :: (p1 ++ p2)) r0 -> noWrite (p1 ++ (m :: p2)) r0. +Proof. +intros p1 p2 m r0; induction p1 as [|a p1 Hrecp1]. +simpl; auto. +destruct a; simpl. +destruct m. +intros [H1 [H2 H3]]; split; auto. +apply Hrecp1. +simpl; auto. +Qed. + +Lemma noWrite_tmpLast: + forall (t : Moves) (r s d : Reg), + noWrite (t ++ ((s, d) :: nil)) r -> + forall (x : Reg), noWrite (t ++ ((x, d) :: nil)) r. +Proof. +intros; induction t as [|a t Hrect]. +simpl; auto. +generalize H; simpl; case a; intros; inversion H0; split; auto. +Qed. + +Fixpoint simpleDest (p : Moves) : Prop := + match p with + nil => True + | (s, d) :: l => noWrite l d /\ simpleDest l + end. + +Lemma simpleDest_Pop: + forall (m : Move) (l1 l2 : Moves), + simpleDest (l1 ++ (m :: l2)) -> simpleDest (l1 ++ l2). +Proof. +intros; induction l1 as [|a l1 Hrecl1]. +generalize H; simpl; case m; intros; inversion H0; auto. +generalize H; rewrite app_cons; rewrite app_cons. +simpl; case a; intros; inversion H0; split; auto. +apply (noWrite_pop l1 l2 m); auto. +Qed. + +Lemma simpleDest_pop: + forall (m : Move) (l : Moves), simpleDest (m :: l) -> simpleDest l. +Proof. +intros m l; simpl; case m; intros _ r [X Y]; auto. +Qed. + +Lemma simpleDest_right: + forall (l1 l2 : Moves), simpleDest (l1 ++ l2) -> simpleDest l2. +Proof. +intros l1; induction l1 as [|a l1 Hrecl1]; auto. +intros l2; rewrite app_cons; intros; apply Hrecl1. +apply (simpleDest_pop a); auto. +Qed. + +Lemma simpleDest_swap: + forall (m1 m2 : Move) (l : Moves), + simpleDest (m1 :: (m2 :: l)) -> simpleDest (m2 :: (m1 :: l)). +Proof. +intros m1 m2 l; simpl; case m1; case m2. +intros _ r0 _ r2 [[X Y] [Z U]]; auto. +(repeat split); auto. +apply Loc.diff_sym; auto. +Qed. + +Lemma simpleDest_pop2: + forall (m1 m2 : Move) (l : Moves), + simpleDest (m1 :: (m2 :: l)) -> simpleDest (m1 :: l). +Proof. +intros; apply (simpleDest_pop m2); apply simpleDest_swap; auto. +Qed. + +Lemma simpleDest_movFront: + forall (p1 p2 : Moves) (m : Move), + simpleDest (p1 ++ (m :: p2)) -> simpleDest (m :: (p1 ++ p2)). +Proof. +intros p1 p2 m; induction p1 as [|a p1 Hrecp1]. +simpl; auto. +rewrite app_cons; rewrite app_cons. +case a; intros; simpl in H |-; inversion H. +apply simpleDest_swap; simpl; auto. +destruct m. +cut (noWrite ((r1, r2) :: (p1 ++ p2)) r0). +cut (simpleDest ((r1, r2) :: (p1 ++ p2))). +intro; (repeat split); elim H3; elim H2; intros; auto. +apply Hrecp1; auto. +apply noWrite_movFront; auto. +Qed. + +Lemma simpleDest_insert: + forall (p1 p2 : Moves) (m : Move), + simpleDest (m :: (p1 ++ p2)) -> simpleDest (p1 ++ (m :: p2)). +Proof. +intros p1 p2 m; induction p1 as [|a p1 Hrecp1]. +simpl; auto. +rewrite app_cons; intros. +simpl. +destruct a as [a1 a2]. +split. +destruct m; simpl in H |-. +apply noWrite_insert. +simpl; split; elim H; intros [H1 H2] [H3 H4]; auto. +apply Loc.diff_sym; auto. +apply Hrecp1. +apply simpleDest_pop2 with (a1, a2); auto. +Qed. + +Lemma simpleDest_movBack: + forall (p1 p2 : Moves) (m : Move), + simpleDest (p1 ++ (m :: p2)) -> simpleDest ((p1 ++ p2) ++ (m :: nil)). +Proof. +intros. +apply (simpleDest_insert (p1 ++ p2) nil m). +rewrite app_nil; apply simpleDest_movFront; auto. +Qed. + +Lemma simpleDest_swap_app: + forall (t1 t2 t3 : Moves) (m : Move), + simpleDest (t1 ++ (m :: (t2 ++ t3))) -> simpleDest ((t1 ++ t2) ++ (m :: t3)). +Proof. +intros. +apply (simpleDest_insert (t1 ++ t2) t3 m). +rewrite <- app_app. +apply simpleDest_movFront; auto. +Qed. + +Lemma simpleDest_tmpLast: + forall (t : Moves) (s d : Reg), + simpleDest (t ++ ((s, d) :: nil)) -> + forall (r : Reg), simpleDest (t ++ ((r, d) :: nil)). +Proof. +intros t s d; induction t as [|a t Hrect]. +simpl; auto. +simpl; case a; intros; inversion H; split; auto. +apply (noWrite_tmpLast t r0 s); auto. +Qed. + +Fixpoint noTmp (b : Moves) : Prop := + match b with + nil => True + | (s, d) :: l => + (forall r, Loc.diff s (T r)) /\ + ((forall r, Loc.diff d (T r)) /\ noTmp l) + end. + +Fixpoint noTmpLast (b : Moves) : Prop := + match b with + nil => True + | (s, d) :: nil => forall r, Loc.diff d (T r) + | (s, d) :: l => + (forall r, Loc.diff s (T r)) /\ + ((forall r, Loc.diff d (T r)) /\ noTmpLast l) + end. + +Lemma noTmp_app: + forall (l1 l2 : Moves) (m : Move), + noTmp l1 -> noTmpLast (m :: l2) -> noTmpLast (l1 ++ (m :: l2)). +Proof. +intros. +induction l1 as [|a l1 Hrecl1]. +simpl; auto. +simpl. +caseEq (l1 ++ (m :: l2)); intro. +destruct a. +elim H; intros; auto. +inversion H; auto. +elim H3; auto. +intros; destruct a as [a1 a2]. +elim H; intros H2 [H3 H4]; auto. +(repeat split); auto. +rewrite H1 in Hrecl1; apply Hrecl1; auto. +Qed. + +Lemma noTmpLast_popBack: + forall (t : Moves) (m : Move), noTmpLast (t ++ (m :: nil)) -> noTmp t. +Proof. +intros. +induction t as [|a t Hrect]. +simpl; auto. +destruct a as [a1 a2]. +rewrite app_cons in H. +simpl. +simpl in H |-. +generalize H; caseEq (t ++ (m :: nil)); intros. +destruct t; inversion H0. +elim H1. +intros H2 [H3 H4]; (repeat split); auto. +rewrite <- H0 in H4. +apply Hrect; auto. +Qed. + +Fixpoint getsrc (p : Moves) : list Reg := + match p with + nil => nil + | (s, d) :: l => s :: getsrc l + end. + +Fixpoint getdst (p : Moves) : list Reg := + match p with + nil => nil + | (s, d) :: l => d :: getdst l + end. + +Fixpoint noOverlap_aux (r : Reg) (l : list Reg) {struct l} : Prop := + match l with + nil => True + | b :: m => (b = r \/ Loc.diff b r) /\ noOverlap_aux r m + end. + +Definition noOverlap (p : Moves) : Prop := + forall l, In l (getsrc p) -> noOverlap_aux l (getdst p). + +Definition stepInv (r : State) : Prop := + path (StateBeing r) /\ + (simpleDest (StateToMove r ++ StateBeing r) /\ + (noOverlap (StateToMove r ++ StateBeing r) /\ + (noTmp (StateToMove r) /\ noTmpLast (StateBeing r)))). + +Definition Value := val. + +Definition Env := locset. + +Definition get (e : Env) (r : Reg) := Locmap.get r e. + +Definition update (e : Env) (r : Reg) (v : Value) : Env := Locmap.set r v e. + +Fixpoint sexec (p : Moves) (e : Env) {struct p} : Env := + match p with + nil => e + | (s, d) :: l => let e' := sexec l e in + update e' d (get e' s) + end. + +Fixpoint pexec (p : Moves) (e : Env) {struct p} : Env := + match p with + nil => e + | (s, d) :: l => update (pexec l e) d (get e s) + end. + +Lemma get_update: + forall (e : Env) (r1 r2 : Reg) (v : Value), + get (update e r1 v) r2 = + (if Loc.eq r1 r2 then v else if Loc.overlap r1 r2 then Vundef else get e r2). +Proof. +intros. +unfold update, get, Locmap.get, Locmap.set; trivial. +Qed. + +Lemma get_update_id: + forall (e : Env) (r1 : Reg) (v : Value), get (update e r1 v) r1 = v. +Proof. +intros e r1 v; rewrite (get_update e r1 r1); auto. +case (Loc.eq r1 r1); auto. +intros H; elim H; trivial. +Qed. + +Lemma get_update_diff: + forall (e : Env) (r1 r2 : Reg) (v : Value), + Loc.diff r1 r2 -> get (update e r1 v) r2 = get e r2. +Proof. +intros; unfold update, get, Locmap.get, Locmap.set. +case (Loc.eq r1 r2); intro. +absurd (r1 = r2); [apply Loc.diff_not_eq; trivial | trivial]. +caseEq (Loc.overlap r1 r2); intro; trivial. +absurd (Loc.diff r1 r2); [apply Loc.overlap_not_diff; assumption | assumption]. +Qed. + +Lemma get_update_ndiff: + forall (e : Env) (r1 r2 : Reg) (v : Value), + r1 <> r2 -> not (Loc.diff r1 r2) -> get (update e r1 v) r2 = Vundef. +Proof. +intros; unfold update, get, Locmap.get, Locmap.set. +case (Loc.eq r1 r2); intro. +absurd (r1 = r2); assumption. +caseEq (Loc.overlap r1 r2); intro; trivial. +absurd (Loc.diff r1 r2); (try assumption). +apply Loc.non_overlap_diff; assumption. +Qed. + +Lemma pexec_swap: + forall (m1 m2 : Move) (t : Moves), + simpleDest (m1 :: (m2 :: t)) -> + forall (e : Env) (r : Reg), + get (pexec (m1 :: (m2 :: t)) e) r = get (pexec (m2 :: (m1 :: t)) e) r. +Proof. +intros; destruct m1 as [m1s m1d]; destruct m2 as [m2s m2d]. +generalize H; simpl; intros [[NEQ NW] [NW2 HSD]]; clear H. +case (Loc.eq m1d r); case (Loc.eq m2d r); intros. +absurd (m1d = m2d); + [apply Loc.diff_not_eq; apply Loc.diff_sym; assumption | + rewrite e0; rewrite e1; trivial]. +caseEq (Loc.overlap m2d r); intro. +absurd (Loc.diff m2d m1d); [apply Loc.overlap_not_diff; rewrite e0 | idtac]; + (try assumption). +subst m1d; rewrite get_update_id; rewrite get_update_diff; + (try rewrite get_update_id); auto. +caseEq (Loc.overlap m1d r); intro. +absurd (Loc.diff m1d m2d); + [apply Loc.overlap_not_diff; rewrite e0 | apply Loc.diff_sym]; assumption. +subst m2d; (repeat rewrite get_update_id); rewrite get_update_diff; + [rewrite get_update_id; trivial | apply Loc.diff_sym; trivial]. +caseEq (Loc.overlap m1d r); caseEq (Loc.overlap m2d r); intros. +(repeat rewrite get_update_ndiff); + (try (apply Loc.overlap_not_diff; assumption)); trivial. +assert (~ Loc.diff m1d r); + [apply Loc.overlap_not_diff; assumption | + intros; rewrite get_update_ndiff; auto]. +rewrite get_update_diff; + [rewrite get_update_ndiff; auto | apply Loc.non_overlap_diff; auto]. +cut (~ Loc.diff m2d r); [idtac | apply Loc.overlap_not_diff; auto]. +cut (Loc.diff m1d r); [idtac | apply Loc.non_overlap_diff; auto]. +intros; rewrite get_update_diff; auto. +(repeat rewrite get_update_ndiff); auto. +cut (Loc.diff m1d r); [idtac | apply Loc.non_overlap_diff; auto]. +cut (Loc.diff m2d r); [idtac | apply Loc.non_overlap_diff; auto]. +intros; (repeat rewrite get_update_diff); auto. +Qed. + +Lemma pexec_add: + forall (t1 t2 : Moves) (r : Reg) (e : Env), + get (pexec t1 e) r = get (pexec t2 e) r -> + forall (a : Move), get (pexec (a :: t1) e) r = get (pexec (a :: t2) e) r. +Proof. +intros. +case a. +simpl. +intros a1 a2. +unfold get, update, Locmap.set, Locmap.get. +case (Loc.eq a2 r); case (Loc.overlap a2 r); auto. +Qed. + +Lemma pexec_movBack: + forall (t1 t2 : Moves) (m : Move), + simpleDest (m :: (t1 ++ t2)) -> + forall (e : Env) (r : Reg), + get (pexec (m :: (t1 ++ t2)) e) r = get (pexec (t1 ++ (m :: t2)) e) r. +Proof. +intros t1 t2 m; induction t1 as [|a t1 Hrect1]. +simpl; auto. +rewrite app_cons. +intros; rewrite pexec_swap; auto; rewrite app_cons; auto. +apply pexec_add. +apply Hrect1. +apply (simpleDest_pop2 m a); auto. +Qed. + +Lemma pexec_movFront: + forall (t1 t2 : Moves) (m : Move), + simpleDest (t1 ++ (m :: t2)) -> + forall (e : Env) (r : Reg), + get (pexec (t1 ++ (m :: t2)) e) r = get (pexec (m :: (t1 ++ t2)) e) r. +Proof. +intros; rewrite <- pexec_movBack; eauto. +apply simpleDest_movFront; auto. +Qed. + +Lemma pexec_mov: + forall (t1 t2 t3 : Moves) (m : Move), + simpleDest ((t1 ++ (m :: t2)) ++ t3) -> + forall (e : Env) (r : Reg), + get (pexec ((t1 ++ (m :: t2)) ++ t3) e) r = + get (pexec ((t1 ++ t2) ++ (m :: t3)) e) r. +Proof. +intros t1 t2 t3 m. +rewrite <- app_app. +rewrite app_cons. +intros. +rewrite pexec_movFront; auto. +cut (simpleDest (m :: (t1 ++ (t2 ++ t3)))). +rewrite app_app. +rewrite <- pexec_movFront; auto. +apply simpleDest_swap_app; auto. +apply simpleDest_movFront; auto. +Qed. + +Definition diff_dec: + forall (x y : Reg), ({ Loc.diff x y }) + ({ not (Loc.diff x y) }). +intros. +case (Loc.eq x y). +intros heq; right. +red; intro; absurd (x = y); auto. +apply Loc.diff_not_eq; auto. +intro; caseEq (Loc.overlap x y). +intro; right. +apply Loc.overlap_not_diff; auto. +intro; left; apply Loc.non_overlap_diff; auto. +Defined. + +Lemma get_pexec_id_noWrite: + forall (t : Moves) (d : Reg), + noWrite t d -> + forall (e : Env) (v : Value), v = get (pexec t (update e d v)) d. +Proof. +intros. +induction t as [|a t Hrect]. +simpl. +rewrite get_update_id; auto. +generalize H; destruct a as [a1 a2]; simpl; intros [NEQ R]. +rewrite get_update_diff; auto. +Qed. + +Lemma pexec_nop: + forall (t : Moves) (r : Reg) (e : Env) (x : Reg), + Loc.diff r x -> get (pexec ((r, r) :: t) e) x = get (pexec t e) x. +Proof. +intros. +simpl. +rewrite get_update_diff; auto. +Qed. + +Lemma sD_nW: forall t r s, simpleDest ((s, r) :: t) -> noWrite t r. +Proof. +induction t. +simpl; auto. +simpl. +destruct a. +intros r1 r2 H; split; [try assumption | idtac]. +elim H; + [intros H0 H1; elim H0; [intros H2 H3; (try clear H0 H); (try exact H2)]]. +elim H; + [intros H0 H1; elim H0; [intros H2 H3; (try clear H0 H); (try exact H3)]]. +Qed. + +Lemma sD_pexec: + forall (t : Moves) (s d : Reg), + simpleDest ((s, d) :: t) -> forall (e : Env), get (pexec t e) d = get e d. +Proof. +intros. +induction t as [|a t Hrect]; simpl; auto. +destruct a as [a1 a2]. +simpl in H |-; elim H; intros [H0 H1] [H2 H3]; clear H. +case (Loc.eq a2 d); intro. +absurd (a2 = d); [apply Loc.diff_not_eq | trivial]; assumption. +rewrite get_update_diff; (try assumption). +apply Hrect. +simpl; (split; assumption). +Qed. + +Lemma noOverlap_nil: noOverlap nil. +Proof. +unfold noOverlap, noOverlap_aux, getsrc, getdst; trivial. +Qed. + +Lemma getsrc_add: + forall (m : Move) (l1 l2 : Moves) (l : Reg), + In l (getsrc (l1 ++ l2)) -> In l (getsrc (l1 ++ (m :: l2))). +Proof. +intros m l1 l2 l; destruct m; induction l1; simpl; auto. +destruct a; simpl; intros. +elim H; intros H0; [left | right]; auto. +Qed. + +Lemma getdst_add: + forall (r1 r2 : Reg) (l1 l2 : Moves), + getdst (l1 ++ ((r1, r2) :: l2)) = getdst l1 ++ (r2 :: getdst l2). +Proof. +intros r1 r2 l1 l2; induction l1; simpl; auto. +destruct a; simpl; rewrite IHl1; auto. +Qed. + +Lemma getdst_app: + forall (l1 l2 : Moves), getdst (l1 ++ l2) = getdst l1 ++ getdst l2. +Proof. +intros; induction l1; simpl; auto. +destruct a; simpl; rewrite IHl1; auto. +Qed. + +Lemma noOverlap_auxpop: + forall (x r : Reg) (l : list Reg), + noOverlap_aux x (r :: l) -> noOverlap_aux x l. +Proof. +induction l; simpl; auto. +intros [H1 [H2 H3]]; split; auto. +Qed. + +Lemma noOverlap_auxPop: + forall (x r : Reg) (l1 l2 : list Reg), + noOverlap_aux x (l1 ++ (r :: l2)) -> noOverlap_aux x (l1 ++ l2). +Proof. +intros x r l1 l2; (try assumption). +induction l1 as [|a l1 Hrecl1]; simpl app. +intro; apply (noOverlap_auxpop x r); auto. +(repeat rewrite app_cons); simpl. +intros [H1 H2]; split; auto. +Qed. + +Lemma noOverlap_pop: + forall (m : Move) (l : Moves), noOverlap (m :: l) -> noOverlap l. +Proof. +induction l. +intro; apply noOverlap_nil. +unfold noOverlap; simpl; destruct m; destruct a; simpl; intros. +elim (H l0); intros; (try assumption). +elim H0; intros H1; right; [left | right]; assumption. +Qed. + +Lemma noOverlap_Pop: + forall (m : Move) (l1 l2 : Moves), + noOverlap (l1 ++ (m :: l2)) -> noOverlap (l1 ++ l2). +Proof. +intros m l1 l2; induction l1 as [|a l1 Hrecl1]; simpl. +simpl; apply noOverlap_pop. +(repeat rewrite app_cons); unfold noOverlap; destruct a; simpl. +intros H l H0; split. +elim (H l); [intros H1 H2 | idtac]; auto. +elim H0; [intros H3; left | intros H3; right; apply getsrc_add]; auto. +unfold noOverlap in Hrecl1 |-. +elim H0; intros H1; clear H0. +destruct m; rewrite getdst_app; apply noOverlap_auxPop with ( r := r2 ). +rewrite getdst_add in H. +elim H with ( l := l ); [intros H0 H2; (try clear H); (try exact H2) | idtac]. +left; (try assumption). +apply Hrecl1 with ( l := l ); auto. +intros l0 H0; (try assumption). +elim H with ( l := l0 ); [intros H2 H3; (try clear H); (try exact H3) | idtac]; + auto. +Qed. + +Lemma noOverlap_right: + forall (l1 l2 : Moves), noOverlap (l1 ++ l2) -> noOverlap l2. +Proof. +intros l1; induction l1 as [|a l1 Hrecl1]; auto. +intros l2; rewrite app_cons; intros; apply Hrecl1. +apply (noOverlap_pop a); auto. +Qed. + +Lemma pexec_update: + forall t e d r v, + Loc.diff d r -> + noRead t d -> get (pexec t (update e d v)) r = get (pexec t e) r. +Proof. +induction t; simpl. +intros; rewrite get_update_diff; auto. +destruct a as [a1 a2]; intros; case (Loc.eq a2 r); intro. +subst a2; (repeat rewrite get_update_id). +rewrite get_update_diff; auto; apply Loc.diff_sym; elim H0; auto. +case (diff_dec a2 r); intro. +(repeat rewrite get_update_diff); auto. +apply IHt; auto. +elim H0; auto. +(repeat rewrite get_update_ndiff); auto. +Qed. + +Lemma pexec_push: + forall (t l : Moves) (s d : Reg), + noRead t d -> + simpleDest ((s, d) :: t) -> + forall (e : Env) (r : Reg), + r = d \/ Loc.diff d r -> + get (pexec ((s, d) :: t) (sexec l e)) r = + get (pexec t (sexec ((s, d) :: l) e)) r. +Proof. +intros; simpl. +elim H1; intros e1. +rewrite e1; rewrite get_update_id; auto. +rewrite (sD_pexec t s d); auto; rewrite get_update_id; auto. +rewrite pexec_update; auto. +rewrite get_update_diff; auto. +Qed. + +Definition exec (s : State) (e : Env) := + pexec (StateToMove s ++ StateBeing s) (sexec (StateDone s) e). + +Definition sameEnv (e1 e2 : Env) := + forall (r : Reg), notemporary r -> get e1 r = get e2 r. + +Definition NoOverlap (r : Reg) (s : State) := + noOverlap ((r, r) :: (StateToMove s ++ StateBeing s)). + +Lemma noOverlapaux_swap2: + forall (l1 l2 : list Reg) (m l : Reg), + noOverlap_aux l (l1 ++ (m :: l2)) -> noOverlap_aux l (m :: (l1 ++ l2)). +Proof. +intros l1 l2 m l; induction l1; simpl noOverlap_aux; auto. +intros; elim H; intros H0 H1; (repeat split); auto. +simpl in IHl1 |-. +elim IHl1; [intros H2 H3; (try exact H2) | idtac]; auto. +apply (noOverlap_auxpop l m). +apply IHl1; auto. +Qed. + +Lemma noTmp_noReadTmp: forall t, noTmp t -> forall s, noRead t (T s). +Proof. +induction t; simpl; auto. +destruct a as [a1 a2]; intros. +split; [idtac | apply IHt]; elim H; intros H1 [H2 H3]; auto. +Qed. + +Lemma noRead_by_path: + forall (b t : Moves) (r0 r1 r7 r8 : Reg), + simpleDest ((r7, r8) :: (b ++ ((r0, r1) :: nil))) -> + path (b ++ ((r0, r1) :: nil)) -> Loc.diff r8 r0 -> noRead b r8. +Proof. +intros; induction b as [|a b Hrecb]; simpl; auto. +destruct a as [a1 a2]; generalize H H0; rewrite app_cons; intros; split. +simpl in H3 |-; caseEq (b ++ ((r0, r1) :: nil)); intro. +destruct b; inversion H4. +intros l H4. +rewrite H4 in H3. +destruct m. +rewrite H4 in H2; simpl in H2 |-. +elim H3; [intros H5 H6; (try clear H3); (try exact H5)]. +rewrite H5. +elim H2; intros [H3 [H7 H8]] [H9 [H10 H11]]; (try assumption). +apply Hrecb. +apply (simpleDest_pop (a1, a2)); apply simpleDest_swap; auto. +apply (path_pop (a1, a2)); auto. +Qed. + +Lemma noOverlap_swap: + forall (m1 m2 : Move) (l : Moves), + noOverlap (m1 :: (m2 :: l)) -> noOverlap (m2 :: (m1 :: l)). +Proof. +intros m1 m2 l; simpl; destruct m1 as [m1s m1d]; destruct m2 as [m2s m2d]. +unfold noOverlap; simpl; intros. +assert (m1s = l0 \/ (m2s = l0 \/ In l0 (getsrc l))). +elim H0; [intros H1 | intros [H1|H2]]. +right; left; (try assumption). +left; (try assumption). +right; right; (try assumption). +(repeat split); + (elim (H l0); [intros H2 H3; elim H3; [intros H4 H5] | idtac]; auto). +Qed. + +Lemma getsrc_add1: + forall (r1 r2 : Reg) (l1 l2 : Moves), + getsrc (l1 ++ ((r1, r2) :: l2)) = getsrc l1 ++ (r1 :: getsrc l2). +Proof. +intros r1 r2 l1 l2; induction l1; simpl; auto. +destruct a; simpl; rewrite IHl1; auto. +Qed. + +Lemma getsrc_app: + forall (l1 l2 : Moves), getsrc (l1 ++ l2) = getsrc l1 ++ getsrc l2. +Proof. +intros; induction l1; simpl; auto. +destruct a; simpl; rewrite IHl1; auto. +Qed. + +Lemma Ingetsrc_swap: + forall (m : Move) (l1 l2 : Moves) (l : Reg), + In l (getsrc (m :: (l1 ++ l2))) -> In l (getsrc (l1 ++ (m :: l2))). +Proof. +intros; destruct m as [m1 m2]; simpl; auto. +simpl in H |-. +elim H; intros H0; auto. +rewrite H0; rewrite getsrc_add1; auto. +apply (in_or_app (getsrc l1) (l :: getsrc l2)); auto. +right; apply in_eq; auto. +apply getsrc_add; auto. +Qed. + +Lemma noOverlap_movFront: + forall (p1 p2 : Moves) (m : Move), + noOverlap (p1 ++ (m :: p2)) -> noOverlap (m :: (p1 ++ p2)). +Proof. +intros p1 p2 m; unfold noOverlap. +destruct m; rewrite getdst_add; simpl getdst; rewrite getdst_app; intros. +apply noOverlapaux_swap2. +apply (H l); apply Ingetsrc_swap; auto. +Qed. + +Lemma step_inv_loop_aux: + forall (t l : Moves) (s d : Reg), + simpleDest (t ++ ((s, d) :: nil)) -> + noTmp t -> + forall (e : Env) (r : Reg), + notemporary r -> + d = r \/ Loc.diff d r -> + get (pexec (t ++ ((s, d) :: nil)) (sexec l e)) r = + get (pexec (t ++ ((T s, d) :: nil)) (sexec ((s, T s) :: l) e)) r. +Proof. +intros; (repeat rewrite pexec_movFront); auto. +(repeat rewrite app_nil); simpl; elim H2; intros e1. +subst d; (repeat rewrite get_update_id); auto. +(repeat rewrite get_update_diff); auto. +rewrite pexec_update; auto. +apply Loc.diff_sym; unfold notemporary in H1 |-; auto. +apply noTmp_noReadTmp; auto. +apply (simpleDest_tmpLast t s); auto. +Qed. + +Lemma step_inv_loop: + forall (t l : Moves) (s d : Reg), + simpleDest (t ++ ((s, d) :: nil)) -> + noTmpLast (t ++ ((s, d) :: nil)) -> + forall (e : Env) (r : Reg), + notemporary r -> + d = r \/ Loc.diff d r -> + get (pexec (t ++ ((s, d) :: nil)) (sexec l e)) r = + get (pexec (t ++ ((T s, d) :: nil)) (sexec ((s, T s) :: l) e)) r. +Proof. +intros; apply step_inv_loop_aux; auto. +apply (noTmpLast_popBack t (s, d)); auto. +Qed. + +Definition sameExec (s1 s2 : State) := + forall (e : Env) (r : Reg), + (let A := + getdst + ((StateToMove s1 ++ StateBeing s1) ++ (StateToMove s2 ++ StateBeing s2)) + in + notemporary r -> + (forall x, In x A -> r = x \/ Loc.diff r x) -> + get (exec s1 e) r = get (exec s2 e) r). + +Lemma get_noWrite: + forall (t : Moves) (d : Reg), + noWrite t d -> forall (e : Env), get e d = get (pexec t e) d. +Proof. +intros; induction t as [|a t Hrect]; simpl; auto. +generalize H; destruct a as [a1 a2]; simpl; intros [NEQ R]. +unfold get, Locmap.get, update, Locmap.set. +case (Loc.eq a2 d); intro; auto. +absurd (a2 = d); auto; apply Loc.diff_not_eq; (try assumption). +caseEq (Loc.overlap a2 d); intro. +absurd (Loc.diff a2 d); auto; apply Loc.overlap_not_diff; auto. +unfold get, Locmap.get in Hrect |-; apply Hrect; auto. +Qed. + +Lemma step_sameExec: + forall (r1 r2 : State), step r1 r2 -> stepInv r1 -> sameExec r1 r2. +Proof. +intros r1 r2 STEP; inversion STEP; + unfold stepInv, sameExec, NoOverlap, exec, StateToMove, StateBeing, StateDone; + (repeat rewrite app_nil); intros [P [SD [NO [TT TB]]]]; intros. +rewrite pexec_movFront; simpl; auto. +case (Loc.eq r r0); intros e0. +subst r0; rewrite get_update_id; apply get_noWrite; apply sD_nW with r; + apply simpleDest_movFront; auto. +elim H2 with ( x := r ); + [intros H3; absurd (r = r0); auto | + intros H3; rewrite get_update_diff; auto; apply Loc.diff_sym; auto | idtac]. +(repeat (rewrite getdst_app; simpl)); apply in_or_app; left; apply in_or_app; + right; simpl; auto. +(repeat rewrite pexec_movFront); auto. +rewrite app_nil; auto. +apply simpleDest_movBack; auto. +apply pexec_mov; auto. +repeat (rewrite <- app_cons; rewrite app_app). +apply step_inv_loop; auto. +repeat (rewrite <- app_app; rewrite app_cons; auto). +repeat (rewrite <- app_app; rewrite app_cons; auto). +apply noTmp_app; auto. +elim H2 with ( x := d ); + [intros H3; left; auto | intros H3; right; apply Loc.diff_sym; auto + | try clear H2]. +repeat (rewrite getdst_app; simpl). +apply in_or_app; left; apply in_or_app; right; simpl; right; apply in_or_app; + right; simpl; left; trivial. +rewrite pexec_movFront; auto; apply pexec_push; auto. +apply noRead_app; auto. +apply noRead_app. +apply (noRead_by_path b b s0 d0 sn dn); auto. +apply (simpleDest_right t); auto. +apply (path_pop (sn, dn)); auto. +simpl; split; [apply Loc.diff_sym | idtac]; auto. +apply simpleDest_movFront; auto. +elim H4 with ( x := dn ); [intros H5 | intros H5 | try clear H4]. +left; (try assumption). +right; apply Loc.diff_sym; (try assumption). +repeat (rewrite getdst_app; simpl). +apply in_or_app; left; apply in_or_app; right; simpl; left; trivial. +rewrite pexec_movFront; auto. +rewrite app_nil; auto. +apply pexec_push; auto. +rewrite <- (app_nil _ t). +apply simpleDest_movFront; auto. +elim (H3 d); (try intros H4). +left; (try assumption). +right; apply Loc.diff_sym; (try assumption). +(repeat rewrite getdst_app); simpl; apply in_or_app; left; apply in_or_app; + right; simpl; left; trivial. +Qed. + +Lemma path_tmpLast: + forall (s d : Reg) (l : Moves), + path (l ++ ((s, d) :: nil)) -> path (l ++ ((T s, d) :: nil)). +Proof. +intros; induction l as [|a l Hrecl]. +simpl; auto. +generalize H; (repeat rewrite app_cons). +case a; generalize Hrecl; case l; intros; auto. +destruct m; intros. +inversion H0; split; auto. +Qed. + +Lemma step_inv_path: + forall (r1 r2 : State), step r1 r2 -> stepInv r1 -> path (StateBeing r2). +Proof. +intros r1 r2 STEP; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + intros [P [SD [TT TB]]]; (try (simpl; auto; fail)). +simpl; case m; auto. +generalize P; rewrite <- app_cons; rewrite <- app_cons. +apply (path_tmpLast r0). +generalize P; apply path_pop. +Qed. + +Lemma step_inv_simpleDest: + forall (r1 r2 : State), + step r1 r2 -> stepInv r1 -> simpleDest (StateToMove r2 ++ StateBeing r2). +Proof. +intros r1 r2 STEP; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + (repeat rewrite app_nil); intros [P [SD [TT TB]]]. +apply (simpleDest_Pop (r, r)); assumption. +apply simpleDest_movBack; assumption. +apply simpleDest_insert; rewrite <- app_app; apply simpleDest_movFront. +rewrite <- app_cons; rewrite app_app; auto. +generalize SD; (repeat rewrite <- app_cons); (repeat rewrite app_app). +generalize (simpleDest_tmpLast (t ++ ((s, r0ounon) :: b)) r0 d); auto. +generalize SD; apply simpleDest_Pop. +rewrite <- (app_nil _ t); generalize SD; apply simpleDest_Pop. +Qed. + +Lemma noTmp_pop: + forall (m : Move) (l1 l2 : Moves), noTmp (l1 ++ (m :: l2)) -> noTmp (l1 ++ l2). +Proof. +intros; induction l1 as [|a l1 Hrecl1]; generalize H. +simpl; case m; intros; inversion H0; inversion H2; auto. +rewrite app_cons; rewrite app_cons; simpl; case a. +intros; inversion H0; inversion H2; auto. +Qed. + +Lemma step_inv_noTmp: + forall (r1 r2 : State), step r1 r2 -> stepInv r1 -> noTmp (StateToMove r2). +Proof. +intros r1 r2 STEP; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + intros [P [SD [NO [TT TB]]]]; generalize TT; (try apply noTmp_pop); auto. +Qed. + +Lemma noTmp_noTmpLast: forall (l : Moves), noTmp l -> noTmpLast l. +Proof. +intros; induction l as [|a l Hrecl]; (try (simpl; auto; fail)). +generalize H; simpl; case a; generalize Hrecl; case l; + (intros; inversion H0; inversion H2; auto). +Qed. + +Lemma noTmpLast_pop: + forall (m : Move) (l : Moves), noTmpLast (m :: l) -> noTmpLast l. +Proof. +intros m l; simpl; case m; case l. +simpl; auto. +intros; inversion H; inversion H1; auto. +Qed. + +Lemma noTmpLast_Pop: + forall (m : Move) (l1 l2 : Moves), + noTmpLast (l1 ++ (m :: l2)) -> noTmpLast (l1 ++ l2). +Proof. +intros; induction l1 as [|a l1 Hrecl1]; generalize H. +simpl; case m; case l2. +simpl; auto. +intros. +elim H0; [intros H1 H2; elim H2; [intros H3 H4; (try exact H4)]]. +(repeat rewrite app_cons); simpl; case a. +generalize Hrecl1; case l1. +simpl; case m; case l2; intros; inversion H0; inversion H2; auto. +intros m0 l R r r0; rewrite app_cons; rewrite app_cons. +intros; inversion H0; inversion H2; auto. +Qed. + +Lemma noTmpLast_push: + forall (m : Move) (t1 t2 t3 : Moves), + noTmp (t1 ++ (m :: t2)) -> noTmpLast t3 -> noTmpLast (m :: t3). +Proof. +intros; induction t1 as [|a t1 Hrect1]; generalize H. +simpl; case m; intros r r0 [N1 [N2 NT]]; generalize H0; case t3; auto. +rewrite app_cons; intros; apply Hrect1. +generalize H1. +simpl; case m; case a; intros; inversion H2; inversion H4; auto. +Qed. + +Lemma noTmpLast_tmpLast: + forall (s d : Reg) (l : Moves), + noTmpLast (l ++ ((s, d) :: nil)) -> noTmpLast (l ++ ((T s, d) :: nil)). +Proof. +intros; induction l as [|a l Hrecl]. +simpl; auto. +generalize H; rewrite app_cons; rewrite app_cons; simpl. +case a; generalize Hrecl; case l. +simpl; auto. +intros m l0 REC r r0; generalize REC; rewrite app_cons; rewrite app_cons. +case m; intros; inversion H0; inversion H2; split; auto. +Qed. + +Lemma step_inv_noTmpLast: + forall (r1 r2 : State), step r1 r2 -> stepInv r1 -> noTmpLast (StateBeing r2). +Proof. +intros r1 r2 STEP; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + intros [P [SD [NO [TT TB]]]]; auto. +apply (noTmpLast_push m t1 t2); auto. +apply (noTmpLast_push (d, r) t1 t2); auto. +generalize TB; rewrite <- app_cons; rewrite <- app_cons; apply noTmpLast_tmpLast. +apply (noTmpLast_pop (sn, dn)); auto. +Qed. + +Lemma noOverlapaux_insert: + forall (l1 l2 : list Reg) (r x : Reg), + noOverlap_aux x (r :: (l1 ++ l2)) -> noOverlap_aux x (l1 ++ (r :: l2)). +Proof. +simpl; intros; induction l1; simpl; split. +elim H; [intros H0 H1; (try exact H0)]. +elim H; [intros H0 H1; (try exact H1)]. +simpl in H |-. +elim H; + [intros H0 H1; elim H1; [intros H2 H3; (try clear H1 H); (try exact H2)]]. +apply IHl1. +split. +elim H; [intros H0 H1; (try exact H0)]. +rewrite app_cons in H. +apply noOverlap_auxpop with ( r := a ). +elim H; [intros H0 H1; (try exact H1)]. +Qed. + +Lemma Ingetsrc_swap2: + forall (m : Move) (l1 l2 : Moves) (l : Reg), + In l (getsrc (l1 ++ (m :: l2))) -> In l (getsrc (m :: (l1 ++ l2))). +Proof. +intros; destruct m as [m1 m2]; simpl; auto. +induction l1; simpl. +simpl in H |-; auto. +destruct a; simpl. +simpl in H |-. +elim H; [intros H0 | intros H0; (try exact H0)]. +right; left; (try assumption). +elim IHl1; intros; auto. +Qed. + +Lemma noOverlap_insert: + forall (p1 p2 : Moves) (m : Move), + noOverlap (m :: (p1 ++ p2)) -> noOverlap (p1 ++ (m :: p2)). +Proof. +unfold noOverlap; destruct m; rewrite getdst_add; simpl getdst; + rewrite getdst_app. +intros. +apply noOverlapaux_insert. +generalize (H l); intros H1; lapply H1; + [intros H2; (try clear H1); (try exact H2) | idtac]. +simpl getsrc. +generalize (Ingetsrc_swap2 (r, r0)); simpl; (intros; auto). +Qed. + +Lemma noOverlap_movBack: + forall (p1 p2 : Moves) (m : Move), + noOverlap (p1 ++ (m :: p2)) -> noOverlap ((p1 ++ p2) ++ (m :: nil)). +Proof. +intros. +apply (noOverlap_insert (p1 ++ p2) nil m). +rewrite app_nil; apply noOverlap_movFront; auto. +Qed. + +Lemma noOverlap_movBack0: + forall (t : Moves) (s d : Reg), + noOverlap ((s, d) :: t) -> noOverlap (t ++ ((s, d) :: nil)). +Proof. +intros t s d H; (try assumption). +apply noOverlap_insert. +rewrite app_nil; auto. +Qed. + +Lemma noOverlap_Front0: + forall (t : Moves) (s d : Reg), + noOverlap (t ++ ((s, d) :: nil)) -> noOverlap ((s, d) :: t). +Proof. +intros t s d H; (try assumption). +cut ((s, d) :: t = (s, d) :: (t ++ nil)). +intros e; rewrite e. +apply noOverlap_movFront; auto. +rewrite app_nil; auto. +Qed. + +Lemma noTmpL_diff: + forall (t : Moves) (s d : Reg), + noTmpLast (t ++ ((s, d) :: nil)) -> notemporary d. +Proof. +intros t s d; unfold notemporary; induction t; (try (simpl; intros; auto; fail)). +rewrite app_cons. +intros; apply IHt. +apply (noTmpLast_pop a); auto. +Qed. + +Lemma noOverlap_aux_app: + forall l1 l2 (r : Reg), + noOverlap_aux r l1 -> noOverlap_aux r l2 -> noOverlap_aux r (l1 ++ l2). +Proof. +induction l1; simpl; auto. +intros; split. +elim H; [intros H1 H2; (try clear H); (try exact H1)]. +apply IHl1; auto. +elim H; [intros H1 H2; (try clear H); (try exact H2)]. +Qed. + +Lemma noTmP_noOverlap_aux: + forall t (r : Reg), noTmp t -> noOverlap_aux (T r) (getdst t). +Proof. +induction t; simpl; auto. +destruct a; simpl; (intros; split). +elim H; intros; elim H1; intros. +right; apply H2. +apply IHt; auto. +elim H; + [intros H0 H1; elim H1; [intros H2 H3; (try clear H1 H); (try exact H3)]]. +Qed. + +Lemma noTmp_append: forall l1 l2, noTmp l1 -> noTmp l2 -> noTmp (l1 ++ l2). +Proof. +induction l1; simpl; auto. +destruct a. +intros l2 [H1 [H2 H3]] H4. +(repeat split); auto. +Qed. + +Lemma step_inv_noOverlap: + forall (r1 r2 : State), + step r1 r2 -> stepInv r1 -> noOverlap (StateToMove r2 ++ StateBeing r2). +Proof. +intros r1 r2 STEP; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + (repeat rewrite app_nil); intros [P [SD [NO [TT TB]]]]; + (try (generalize NO; apply noOverlap_Pop; auto; fail)). +apply noOverlap_movBack; auto. +apply noOverlap_insert; rewrite <- app_app; apply noOverlap_movFront; + rewrite <- app_cons; rewrite app_app; auto. +generalize NO; (repeat rewrite <- app_cons); (repeat rewrite app_app); + (clear NO; intros NO); apply noOverlap_movBack0. +assert (noOverlap ((r0, d) :: (t ++ ((s, r0ounon) :: b)))); + [apply noOverlap_Front0; auto | idtac]. +generalize H; unfold noOverlap; simpl; clear H; intros. +elim H0; intros; [idtac | apply (H l0); (right; (try assumption))]. +split; [right; (try assumption) | idtac]. +generalize TB; simpl; caseEq (b ++ ((r0, d) :: nil)); intro. +elim (app_eq_nil b ((r0, d) :: nil)); intros; auto; inversion H4. +subst l0; intros; rewrite <- H1 in TB0. +elim TB0; [intros H2 H3; elim H3; [intros H4 H5; (try clear H3 TB0)]]. +generalize (noTmpL_diff b r0 d); unfold notemporary; intro; apply H3; auto. +rewrite <- H1; apply noTmP_noOverlap_aux; apply noTmp_append; auto; + rewrite <- app_cons in TB; apply noTmpLast_popBack with (r0, d); auto. +rewrite <- (app_nil _ t); apply (noOverlap_Pop (s, d)); assumption. +Qed. + +Lemma step_inv: forall (r1 r2 : State), step r1 r2 -> stepInv r1 -> stepInv r2. +Proof. +intros; unfold stepInv; (repeat split). +apply (step_inv_path r1 r2); auto. +apply (step_inv_simpleDest r1 r2); auto. +apply (step_inv_noOverlap r1 r2); auto. +apply (step_inv_noTmp r1 r2); auto. +apply (step_inv_noTmpLast r1 r2); auto. +Qed. + +Definition step_NF (r : State) : Prop := ~ (exists s : State , step r s ). + +Inductive stepp : State -> State -> Prop := + stepp_refl: forall (r : State), stepp r r + | stepp_trans: + forall (r1 r2 r3 : State), step r1 r2 -> stepp r2 r3 -> stepp r1 r3 . +Hint Resolve stepp_refl stepp_trans . + +Lemma stepp_transitive: + forall (r1 r2 r3 : State), stepp r1 r2 -> stepp r2 r3 -> stepp r1 r3. +Proof. +intros; induction H as [r|r1 r2 r0 H H1 HrecH]; eauto. +Qed. + +Lemma step_stepp: forall (s1 s2 : State), step s1 s2 -> stepp s1 s2. +Proof. +eauto. +Qed. + +Lemma stepp_inv: + forall (r1 r2 : State), stepp r1 r2 -> stepInv r1 -> stepInv r2. +Proof. +intros; induction H as [r|r1 r2 r3 H H1 HrecH]; auto. +apply HrecH; auto. +apply (step_inv r1 r2); auto. +Qed. + +Lemma noTmpLast_lastnoTmp: + forall l s d, noTmpLast (l ++ ((s, d) :: nil)) -> notemporary d. +Proof. +induction l. +simpl. +intros; unfold notemporary; auto. +destruct a as [a1 a2]; intros. +change (noTmpLast ((a1, a2) :: (l ++ ((s, d) :: nil)))) in H |-. +apply IHl with s. +apply noTmpLast_pop with (a1, a2); auto. +Qed. + +Lemma step_inv_NoOverlap: + forall (s1 s2 : State) r, + step s1 s2 -> notemporary r -> stepInv s1 -> NoOverlap r s1 -> NoOverlap r s2. +Proof. +intros s1 s2 r STEP notempr; inversion_clear STEP; unfold stepInv; + unfold stepInv, sameExec, sameEnv, exec, StateToMove, StateBeing, StateDone; + intros [P [SD [NO [TT TB]]]]; unfold NoOverlap; simpl. +simpl; (repeat rewrite app_nil); simpl; (repeat rewrite <- app_cons); intro; + apply noOverlap_Pop with ( m := (r0, r0) ); auto. +(repeat rewrite app_nil); simpl; rewrite app_ass; (repeat rewrite <- app_cons); + intro; rewrite ass_app; apply noOverlap_movBack; auto. +simpl; (repeat (rewrite app_ass; simpl)); (repeat rewrite <- app_cons); intro. +rewrite ass_app; apply noOverlap_insert; rewrite app_ass; + apply noOverlap_movFront; auto. +simpl; (repeat rewrite <- app_cons); intro; rewrite ass_app; + apply noOverlap_movBack0; auto. +generalize H; (repeat (rewrite app_ass; simpl)); intro. +assert (noOverlap ((r0, d) :: (((r, r) :: t) ++ ((s, r0ounon) :: b)))); + [apply noOverlap_Front0 | idtac]; auto. +generalize H0; (repeat (rewrite app_ass; simpl)); auto. +generalize H1; unfold noOverlap; simpl; intros. +elim H3; intros H4; clear H3. +split. +right; assert (notemporary d). +change (noTmpLast (((s, r0ounon) :: b) ++ ((r0, d) :: nil))) in TB |-; + apply (noTmpLast_lastnoTmp ((s, r0ounon) :: b) r0); auto. +rewrite <- H4; unfold notemporary in H3 |-; apply H3. +split. +right; rewrite <- H4; unfold notemporary in notempr |-; apply notempr. +rewrite <- H4; apply noTmP_noOverlap_aux; auto. +apply noTmp_append; auto. +change (noTmpLast (((s, r0ounon) :: b) ++ ((r0, d) :: nil))) in TB |-; + apply noTmpLast_popBack with ( m := (r0, d) ); auto. +apply (H2 l0). +elim H4; intros H3; right; [left | right]; assumption. +intro; + change (noOverlap (((r, r) :: t) ++ ((sn, dn) :: (b ++ ((s0, d0) :: nil))))) in + H1 |-. +change (noOverlap (((r, r) :: t) ++ (b ++ ((s0, d0) :: nil)))); + apply (noOverlap_Pop (sn, dn)); auto. +(repeat rewrite <- app_cons); apply noOverlap_Pop. +Qed. + +Lemma step_inv_getdst: + forall (s1 s2 : State) r, + step s1 s2 -> + In r (getdst (StateToMove s2 ++ StateBeing s2)) -> + In r (getdst (StateToMove s1 ++ StateBeing s1)). +Proof. +intros s1 s2 r STEP; inversion_clear STEP; + unfold StateToMove, StateBeing, StateDone. +(repeat rewrite getdst_app); simpl; (repeat rewrite app_nil); intro; + apply in_or_app. +elim (in_app_or (getdst t1) (getdst t2) r); auto. +intro; right; simpl; right; assumption. +(repeat rewrite getdst_app); destruct m as [m1 m2]; simpl; + (repeat rewrite app_nil); intro; apply in_or_app. +elim (in_app_or (getdst t1 ++ getdst t2) (m2 :: nil) r); auto; intro. +elim (in_app_or (getdst t1) (getdst t2) r); auto; intro. +right; simpl; right; assumption. +elim H0; intros H1; [right; simpl; left; (try assumption) | inversion H1]. +(repeat rewrite getdst_app); simpl; (repeat rewrite app_nil); intro; + apply in_or_app. +elim (in_app_or (getdst t1 ++ getdst t2) (r0 :: (d :: getdst b)) r); auto; + intro. +elim (in_app_or (getdst t1) (getdst t2) r); auto; intro. +left; apply in_or_app; left; assumption. +left; apply in_or_app; right; simpl; right; assumption. +elim H0; intro. +left; apply in_or_app; right; simpl; left; trivial. +elim H1; intro. +right; (simpl; left; trivial). +right; simpl; right; assumption. +(repeat (rewrite getdst_app; simpl)); trivial. +(repeat (rewrite getdst_app; simpl)); intro. +elim (in_app_or (getdst t) (getdst b ++ (d0 :: nil)) r); auto; intro; + apply in_or_app; auto. +elim (in_app_or (getdst b) (d0 :: nil) r); auto; intro. +right; simpl; right; apply in_or_app; auto. +elim H3; intro. +right; simpl; right; apply in_or_app; right; simpl; auto. +inversion H4. +rewrite app_nil; (repeat (rewrite getdst_app; simpl)); intro. +apply in_or_app; left; assumption. +Qed. + +Lemma stepp_sameExec: + forall (r1 r2 : State), stepp r1 r2 -> stepInv r1 -> sameExec r1 r2. +Proof. +intros; induction H as [r|r1 r2 r3 H H1 HrecH]. +unfold sameExec; intros; auto. +cut (sameExec r1 r2); [idtac | apply (step_sameExec r1); auto]. +unfold sameExec; unfold sameExec in HrecH |-; intros. +rewrite H2; auto. +rewrite HrecH; auto. +apply (step_inv r1); auto. +intros x H5; apply H4. +generalize H5; (repeat rewrite getdst_app); intros; apply in_or_app. +elim + (in_app_or + (getdst (StateToMove r2) ++ getdst (StateBeing r2)) + (getdst (StateToMove r3) ++ getdst (StateBeing r3)) x); auto; intro. +generalize (step_inv_getdst r1 r2 x); (repeat rewrite getdst_app); intro. +left; apply H8; auto. +intros x H5; apply H4. +generalize H5; (repeat rewrite getdst_app); intros; apply in_or_app. +elim + (in_app_or + (getdst (StateToMove r1) ++ getdst (StateBeing r1)) + (getdst (StateToMove r2) ++ getdst (StateBeing r2)) x); auto; intro. +generalize (step_inv_getdst r1 r2 x); (repeat rewrite getdst_app); intro. +left; apply H8; auto. +Qed. + +Inductive dstep : State -> State -> Prop := + dstep_nop: + forall (r : Reg) (t l : Moves), dstep ((r, r) :: t, nil, l) (t, nil, l) + | dstep_start: + forall (t l : Moves) (s d : Reg), + s <> d -> dstep ((s, d) :: t, nil, l) (t, (s, d) :: nil, l) + | dstep_push: + forall (t1 t2 b l : Moves) (s d r : Reg), + noRead t1 d -> + dstep + (t1 ++ ((d, r) :: t2), (s, d) :: b, l) + (t1 ++ t2, (d, r) :: ((s, d) :: b), l) + | dstep_pop_loop: + forall (t b l : Moves) (s d r0 : Reg), + noRead t r0 -> + dstep + (t, (s, r0) :: (b ++ ((r0, d) :: nil)), l) + (t, b ++ ((T r0, d) :: nil), (s, r0) :: ((r0, T r0) :: l)) + | dstep_pop: + forall (t b l : Moves) (s0 d0 sn dn : Reg), + noRead t dn -> + Loc.diff dn s0 -> + dstep + (t, (sn, dn) :: (b ++ ((s0, d0) :: nil)), l) + (t, b ++ ((s0, d0) :: nil), (sn, dn) :: l) + | dstep_last: + forall (t l : Moves) (s d : Reg), + noRead t d -> dstep (t, (s, d) :: nil, l) (t, nil, (s, d) :: l) . +Hint Resolve dstep_nop dstep_start dstep_push . +Hint Resolve dstep_pop_loop dstep_pop dstep_last . + +Lemma dstep_step: + forall (r1 r2 : State), dstep r1 r2 -> stepInv r1 -> stepp r1 r2. +Proof. +intros r1 r2 DS; inversion_clear DS; intros SI; eauto. +change (stepp (nil ++ ((r, r) :: t), nil, l) (t, nil, l)); apply step_stepp; + apply (step_nop r nil t). +change (stepp (nil ++ ((s, d) :: t), nil, l) (t, (s, d) :: nil, l)); + apply step_stepp; apply (step_start nil t l). +apply + (stepp_trans + (t, (s, r0) :: (b ++ ((r0, d) :: nil)), l) + (t, (s, r0) :: (b ++ ((T r0, d) :: nil)), (r0, T r0) :: l) + (t, b ++ ((T r0, d) :: nil), (s, r0) :: ((r0, T r0) :: l))); auto. +apply step_stepp; apply step_pop; auto. +unfold stepInv in SI |-; generalize SI; intros [X [Y [Z [U V]]]]. +generalize V; unfold StateBeing, noTmpLast. +case (b ++ ((r0, d) :: nil)); auto. +intros m l0 [R1 [OK PP]]; auto. +Qed. + +Lemma dstep_inv: + forall (r1 r2 : State), dstep r1 r2 -> stepInv r1 -> stepInv r2. +Proof. +intros. +apply (stepp_inv r1 r2); auto. +apply dstep_step; auto. +Qed. + +Inductive dstepp : State -> State -> Prop := + dstepp_refl: forall (r : State), dstepp r r + | dstepp_trans: + forall (r1 r2 r3 : State), dstep r1 r2 -> dstepp r2 r3 -> dstepp r1 r3 . +Hint Resolve dstepp_refl dstepp_trans . + +Lemma dstepp_stepp: + forall (s1 s2 : State), stepInv s1 -> dstepp s1 s2 -> stepp s1 s2. +Proof. +intros; induction H0 as [r|r1 r2 r3 H0 H1 HrecH0]; auto. +apply (stepp_transitive r1 r2 r3); auto. +apply dstep_step; auto. +apply HrecH0; auto. +apply (dstep_inv r1 r2); auto. +Qed. + +Lemma dstepp_sameExec: + forall (r1 r2 : State), dstepp r1 r2 -> stepInv r1 -> sameExec r1 r2. +Proof. +intros; apply stepp_sameExec; auto. +apply dstepp_stepp; auto. +Qed. + +End pmov. + +Fixpoint split_move' (m : Moves) (r : Reg) {struct m} : + option ((Moves * Reg) * Moves) := + match m with + (s, d) :: tail => + match diff_dec s r with + right _ => Some (nil, d, tail) + | left _ => + match split_move' tail r with + Some ((t1, r2, t2)) => Some ((s, d) :: t1, r2, t2) + | None => None + end + end + | nil => None + end. + +Fixpoint split_move (m : Moves) (r : Reg) {struct m} : + option ((Moves * Reg) * Moves) := + match m with + (s, d) :: tail => + match Loc.eq s r with + left _ => Some (nil, d, tail) + | right _ => + match split_move tail r with + Some ((t1, r2, t2)) => Some ((s, d) :: t1, r2, t2) + | None => None + end + end + | nil => None + end. + +Definition def : Move := (R IT1, R IT1). + +Fixpoint last (M : Moves) : Move := + match M with nil => def + | m :: nil => m + | m :: tail => last tail end. + +Fixpoint head_but_last (M : Moves) : Moves := + match M with + nil => nil + | m' :: nil => nil + | m' :: tail => m' :: head_but_last tail + end. + +Fixpoint replace_last_s (M : Moves) : Moves := + match M with + nil => nil + | m :: nil => + match m with (s, d) => (T s, d) :: nil end + | m :: tail => m :: replace_last_s tail + end. + +Ltac CaseEq name := generalize (refl_equal name); pattern name at -1; case name. + +Definition stepf' (S1 : State) : State := + match S1 with + (nil, nil, _) => S1 + | ((s, d) :: tl, nil, l) => + match diff_dec s d with + right _ => (tl, nil, l) + | left _ => (tl, (s, d) :: nil, l) + end + | (t, (s, d) :: b, l) => + match split_move t d with + Some ((t1, r, t2)) => + (t1 ++ t2, (d, r) :: ((s, d) :: b), l) + | None => + match b with + nil => (t, nil, (s, d) :: l) + | _ => + match diff_dec d (fst (last b)) with + right _ => + (t, replace_last_s b, (s, d) :: ((d, T d) :: l)) + | left _ => (t, b, (s, d) :: l) + end + end + end + end. + +Definition stepf (S1 : State) : State := + match S1 with + (nil, nil, _) => S1 + | ((s, d) :: tl, nil, l) => + match Loc.eq s d with + left _ => (tl, nil, l) + | right _ => (tl, (s, d) :: nil, l) + end + | (t, (s, d) :: b, l) => + match split_move t d with + Some ((t1, r, t2)) => + (t1 ++ t2, (d, r) :: ((s, d) :: b), l) + | None => + match b with + nil => (t, nil, (s, d) :: l) + | _ => + match Loc.eq d (fst (last b)) with + left _ => + (t, replace_last_s b, (s, d) :: ((d, T d) :: l)) + | right _ => (t, b, (s, d) :: l) + end + end + end + end. + +Lemma rebuild_l: + forall (l : Moves) (m : Move), + m :: l = head_but_last (m :: l) ++ (last (m :: l) :: nil). +Proof. +induction l; simpl; auto. +intros m; rewrite (IHl a); auto. +Qed. + +Lemma splitSome: + forall (l t1 t2 : Moves) (s d r : Reg), + noOverlap (l ++ ((r, s) :: nil)) -> + split_move l s = Some (t1, d, t2) -> noRead t1 s. +Proof. +induction l; simpl. +intros; discriminate. +destruct a as [a1 a2]. +intros t1 t2 s d r Hno; case (Loc.eq a1 s). +intros e H1; inversion H1. +simpl; auto. +CaseEq (split_move l s). +intros; (repeat destruct p). +inversion H0; auto. +simpl; split; auto. +change (noOverlap (((a1, a2) :: l) ++ ((r, s) :: nil))) in Hno |-. +assert (noOverlap ((r, s) :: ((a1, a2) :: l))). +apply noOverlap_Front0; auto. +unfold noOverlap in H1 |-; simpl in H1 |-. +elim H1 with ( l0 := a1 ); + [intros H5 H6; (try clear H1); (try exact H5) | idtac]. +elim H5; [intros H1; (try clear H5); (try exact H1) | intros H1; (try clear H5)]. +absurd (a1 = s); auto. +apply Loc.diff_sym; auto. +right; left; trivial. +apply (IHl m0 m s r0 r); auto. +apply (noOverlap_pop (a1, a2)); auto. +intros; discriminate. +Qed. + +Lemma unsplit_move: + forall (l t1 t2 : Moves) (s d r : Reg), + noOverlap (l ++ ((r, s) :: nil)) -> + split_move l s = Some (t1, d, t2) -> l = t1 ++ ((s, d) :: t2). +Proof. +induction l. +simpl; intros; discriminate. +intros t1 t2 s d r HnoO; destruct a as [a1 a2]; simpl; case (diff_dec a1 s); + intro. +case (Loc.eq a1 s); intro. +absurd (Loc.diff a1 s); auto. +rewrite e; apply Loc.same_not_diff. +CaseEq (split_move l s); intros; (try discriminate). +(repeat destruct p); inversion H0. +rewrite app_cons; subst t2; subst d; rewrite (IHl m0 m s r0 r); auto. +apply (noOverlap_pop (a1, a2)); auto. +case (Loc.eq a1 s); intros e H; inversion H; simpl. +rewrite e; auto. +cut (noOverlap_aux a1 (getdst ((r, s) :: nil))). +intros [[H5|H4] H0]; [try exact H5 | idtac]. +absurd (s = a1); auto. +absurd (Loc.diff a1 s); auto; apply Loc.diff_sym; auto. +generalize HnoO; rewrite app_cons; intro. +assert (noOverlap (l ++ ((a1, a2) :: ((r, s) :: nil)))); + (try (apply noOverlap_insert; assumption)). +assert (noOverlap ((a1, a2) :: ((r, s) :: nil))). +apply (noOverlap_right l); auto. +generalize H2; unfold noOverlap; simpl. +intros H5; elim (H5 a1); [idtac | left; trivial]. +intros H6 [[H7|H8] H9]. +absurd (s = a1); auto. +split; [right; (try assumption) | auto]. +Qed. + +Lemma cons_replace: + forall (a : Move) (l : Moves), + l <> nil -> replace_last_s (a :: l) = a :: replace_last_s l. +Proof. +intros; simpl. +CaseEq l. +intro; contradiction. +intros m l0 H0; auto. +Qed. + +Lemma last_replace: + forall (l : Moves) (s d : Reg), + replace_last_s (l ++ ((s, d) :: nil)) = l ++ ((T s, d) :: nil). +Proof. +induction l; (try (simpl; auto; fail)). +intros; (repeat rewrite <- app_comm_cons). +rewrite cons_replace. +rewrite IHl; auto. +red; intro. +elim (app_eq_nil l ((s, d) :: nil)); auto; intros; discriminate. +Qed. + +Lemma last_app: forall (l : Moves) (m : Move), last (l ++ (m :: nil)) = m. +Proof. +induction l; simpl; auto. +intros m; CaseEq (l ++ (m :: nil)). +intro; elim (app_eq_nil l (m :: nil)); auto; intros; discriminate. +intros m0 l0 H; (rewrite <- H; apply IHl). +Qed. + +Lemma last_cons: + forall (l : Moves) (m m0 : Move), last (m0 :: (m :: l)) = last (m :: l). +Proof. +intros; simpl; auto. +Qed. + +Lemma stepf_popLoop: + forall (t b l : Moves) (s d r0 : Reg), + split_move t d = None -> + stepf (t, (s, d) :: (b ++ ((d, r0) :: nil)), l) = + (t, b ++ ((T d, r0) :: nil), (s, d) :: ((d, T d) :: l)). +Proof. +intros; simpl; rewrite H; CaseEq (b ++ ((d, r0) :: nil)); intros. +destruct b; discriminate. +rewrite <- H0; rewrite last_app; simpl; rewrite last_replace. +case (Loc.eq d d); intro; intuition. +destruct t; (try destruct m0); simpl; auto. +Qed. + +Lemma stepf_pop: + forall (t b l : Moves) (s d r r0 : Reg), + split_move t d = None -> + d <> r -> + stepf (t, (s, d) :: (b ++ ((r, r0) :: nil)), l) = + (t, b ++ ((r, r0) :: nil), (s, d) :: l). +Proof. +intros; simpl; rewrite H; CaseEq (b ++ ((r, r0) :: nil)); intros. +destruct b; discriminate. +rewrite <- H1; rewrite last_app; simpl. +case (Loc.eq d r); intro. +absurd (d = r); auto. +destruct t; (try destruct m0); simpl; auto. +Qed. + +Lemma noOverlap_head: + forall l1 l2 m, noOverlap (l1 ++ (m :: l2)) -> noOverlap (l1 ++ (m :: nil)). +Proof. +induction l2; simpl; auto. +intros; apply IHl2. +cut (l1 ++ (m :: (a :: l2)) = (l1 ++ (m :: nil)) ++ (a :: l2)); + [idtac | rewrite app_ass; auto]. +intros e; rewrite e in H. +cut (l1 ++ (m :: l2) = (l1 ++ (m :: nil)) ++ l2); + [idtac | rewrite app_ass; auto]. +intros e'; rewrite e'; auto. +apply noOverlap_Pop with a; auto. +Qed. + +Lemma splitNone: + forall (l : Moves) (s d : Reg), + split_move l d = None -> noOverlap (l ++ ((s, d) :: nil)) -> noRead l d. +Proof. +induction l; intros s d; simpl; auto. +destruct a as [a1 a2]; case (Loc.eq a1 d); intro; (try (intro; discriminate)). +CaseEq (split_move l d); intros. +(repeat destruct p); discriminate. +split; (try assumption). +change (noOverlap (((a1, a2) :: l) ++ ((s, d) :: nil))) in H1 |-. +assert (noOverlap ((s, d) :: ((a1, a2) :: l))). +apply noOverlap_Front0; auto. +assert (noOverlap ((a1, a2) :: ((s, d) :: l))). +apply noOverlap_swap; auto. +unfold noOverlap in H3 |-; simpl in H3 |-. +elim H3 with ( l0 := a1 ); + [intros H5 H6; (try clear H1); (try exact H5) | idtac]. +elim H6; + [intros H1 H4; elim H1; + [intros H7; (try clear H1 H6); (try exact H7) | intros H7; (try clear H1 H6)]]. +absurd (a1 = d); auto. +apply Loc.diff_sym; auto. +left; trivial. +apply IHl with s; auto. +apply noOverlap_pop with (a1, a2); auto. +Qed. + +Lemma noO_diff: + forall l1 l2 s d r r0, + noOverlap (l1 ++ ((s, d) :: (l2 ++ ((r, r0) :: nil)))) -> + r = d \/ Loc.diff d r. +Proof. +intros. +assert (noOverlap ((s, d) :: (l2 ++ ((r, r0) :: nil)))); auto. +apply (noOverlap_right l1); auto. +assert (noOverlap ((l2 ++ ((r, r0) :: nil)) ++ ((s, d) :: nil))); auto. +apply (noOverlap_movBack0 (l2 ++ ((r, r0) :: nil))); auto. +assert + ((l2 ++ ((r, r0) :: nil)) ++ ((s, d) :: nil) = + l2 ++ (((r, r0) :: nil) ++ ((s, d) :: nil))); auto. +rewrite app_ass; auto. +rewrite H2 in H1. +simpl in H1 |-. +assert (noOverlap ((r, r0) :: ((s, d) :: nil))); auto. +apply (noOverlap_right l2); auto. +unfold noOverlap in H3 |-. +generalize (H3 r); simpl. +intros H4; elim H4; intros; [idtac | left; trivial]. +elim H6; intros [H9|H9] H10; [left | right]; auto. +Qed. + +Lemma f2ind: + forall (S1 S2 : State), + (forall (l : Moves), (S1 <> (nil, nil, l))) -> + noOverlap (StateToMove S1 ++ StateBeing S1) -> stepf S1 = S2 -> dstep S1 S2. +Proof. +intros S1 S2 Hneq HnoO; destruct S1 as [[t b] l]; destruct b. +destruct t. +elim (Hneq l); auto. +destruct m; simpl; case (Loc.eq r r0). +intros. +rewrite e; rewrite <- H; apply dstep_nop. +intros n H; rewrite <- H; generalize (dstep_start t l r r0); auto. +intros H; rewrite <- H; destruct m as [s d]. +CaseEq (split_move t d). +intros p H0; destruct p as [[t1 s0] t2]; simpl; rewrite H0; destruct t; simpl. +simpl in H0 |-; discriminate. +rewrite (unsplit_move (m :: t) t1 t2 d s0 s); auto. +destruct m; generalize dstep_push; intros H1; apply H1. +unfold StateToMove, StateBeing in HnoO |-. +apply (splitSome ((r, r0) :: t) t1 t2 d s0 s); auto. +apply noOverlap_head with b; auto. +unfold StateToMove, StateBeing in HnoO |-. +apply noOverlap_head with b; auto. +intros H0; destruct b. +simpl. +rewrite H0. +destruct t; (try destruct m); generalize dstep_last; intros H1; apply H1. +simpl; auto. +unfold StateToMove, StateBeing in HnoO |-. +apply splitNone with s; auto. +unfold StateToMove, StateBeing in HnoO |-. +generalize HnoO; clear HnoO; rewrite (rebuild_l b m); intros HnoO. +destruct (last (m :: b)). +case (Loc.eq d r). +intros e; rewrite <- e. +CaseEq (head_but_last (m :: b)); intros; [simpl | idtac]; + (try + (destruct t; (try destruct m0); rewrite H0; + (case (Loc.eq d d); intros h; (try (elim h; auto))))). +generalize (dstep_pop_loop nil nil); simpl; intros H3; apply H3; auto. +generalize (dstep_pop_loop ((r1, r2) :: t) nil); unfold T; simpl app; + intros H3; apply H3; clear H3; apply splitNone with s; (try assumption). +apply noOverlap_head with (head_but_last (m :: b) ++ ((r, r0) :: nil)); auto. +rewrite stepf_popLoop; auto. +generalize (dstep_pop_loop t (m0 :: l0)); simpl; intros H3; apply H3; clear H3; + apply splitNone with s; (try assumption). +apply noOverlap_head with (head_but_last (m :: b) ++ ((r, r0) :: nil)); auto. +intro; assert (Loc.diff d r). +assert (r = d \/ Loc.diff d r). +apply (noO_diff t (head_but_last (m :: b)) s d r r0); auto. +elim H1; [intros H2; absurd (d = r); auto | intros H2; auto]. +rewrite stepf_pop; auto. +generalize (dstep_pop t (head_but_last (m :: b))); intros H3; apply H3; auto. +clear H3; apply splitNone with s; (try assumption). +apply noOverlap_head with (head_but_last (m :: b) ++ ((r, r0) :: nil)); auto. +Qed. + +Lemma f2ind': + forall (S1 : State), + (forall (l : Moves), (S1 <> (nil, nil, l))) -> + noOverlap (StateToMove S1 ++ StateBeing S1) -> dstep S1 (stepf S1). +Proof. +intros S1 H noO; apply f2ind; auto. +Qed. + +Lemma appcons_length: + forall (l1 l2 : Moves) (m : Move), + length (l1 ++ (m :: l2)) = (length (l1 ++ l2) + 1%nat)%nat. +Proof. +induction l1; simpl; intros; [omega | idtac]. +rewrite IHl1; omega. +Qed. + +Definition mesure (S0 : State) : nat := + let (p, _) := S0 in let (t, b) := p in (2 * length t + length b)%nat. + +Lemma step_dec0: + forall (t1 t2 b1 b2 : Moves) (l1 l2 : Moves), + dstep (t1, b1, l1) (t2, b2, l2) -> + (2 * length t2 + length b2 < 2 * length t1 + length b1)%nat. +Proof. +intros t1 t2 b1 b2 l1 l2 H; inversion H; simpl; (try omega). +rewrite appcons_length; omega. +cut (length (b ++ ((T r0, d) :: nil)) = length (b ++ ((r0, d) :: nil))); + (try omega). +induction b; simpl; auto. +(repeat rewrite appcons_length); auto. +Qed. + +Lemma step_dec: + forall (S1 S2 : State), dstep S1 S2 -> (mesure S2 < mesure S1)%nat. +Proof. +unfold mesure; destruct S1 as [[t1 b1] l1]; destruct S2 as [[t2 b2] l2]. +intro; apply (step_dec0 t1 t2 b1 b2 l1 l2); trivial. +Qed. + +Lemma stepf_dec0: + forall (S1 S2 : State), + (forall (l : Moves), (S1 <> (nil, nil, l))) /\ + (S2 = stepf S1 /\ noOverlap (StateToMove S1 ++ StateBeing S1)) -> + (mesure S2 < mesure S1)%nat. +Proof. +intros S1 S2 [H1 [H2 H3]]; apply step_dec. +apply f2ind; trivial. +rewrite H2; reflexivity. +Qed. + +Lemma stepf_dec: + forall (S1 S2 : State), + S2 = stepf S1 /\ + ((forall (l : Moves), (S1 <> (nil, nil, l))) /\ + noOverlap (StateToMove S1 ++ StateBeing S1)) -> ltof _ mesure S2 S1. +Proof. +unfold ltof. +intros S1 S2 [H1 [H2 H3]]; apply step_dec. +apply f2ind; trivial. +rewrite H1; reflexivity. +Qed. + +Lemma replace_last_id: + forall l m m0, replace_last_s (m :: (m0 :: l)) = m :: replace_last_s (m0 :: l). +Proof. +intros; case l; simpl. +destruct m0; simpl; auto. +intros; case l0; auto. +Qed. + +Lemma length_replace: forall l, length (replace_last_s l) = length l. +Proof. +induction l; simpl; auto. +destruct l; destruct a; simpl; auto. +Qed. + +Lemma length_app: + forall (A : Set) (l1 l2 : list A), + (length (l1 ++ l2) = length l1 + length l2)%nat. +Proof. +intros A l1 l2; (try assumption). +induction l1; simpl; auto. +Qed. + +Lemma split_length: + forall (l t1 t2 : Moves) (s d : Reg), + split_move l s = Some (t1, d, t2) -> + (length l = (length t1 + length t2) + 1)%nat. +Proof. +induction l. +intros; discriminate. +intros t1 t2 s d; destruct a as [r r0]; simpl; case (Loc.eq r s); intro. +intros H; inversion H. +simpl; omega. +CaseEq (split_move l s); (try (intros; discriminate)). +(repeat destruct p); intros H H0; inversion H0. +rewrite H2; rewrite (IHl m0 m s r1); auto. +rewrite H4; rewrite <- H2; simpl; omega. +Qed. + +Lemma stepf_dec0': + forall (S1 : State), + (forall (l : Moves), (S1 <> (nil, nil, l))) -> + (mesure (stepf S1) < mesure S1)%nat. +Proof. +intros S1 H. +unfold mesure; destruct S1 as [[t1 b1] l1]. +destruct t1. +destruct b1. +generalize (H l1); intros H1; elim H1; auto. +destruct m; simpl. +destruct b1. +simpl; auto. +case (Loc.eq r0 (fst (last (m :: b1)))). +intros; rewrite length_replace; simpl; omega. +simpl; case b1; intros; simpl; omega. +destruct m. +destruct b1. +simpl. +case (Loc.eq r r0); intros; simpl; omega. +destruct m; simpl; case (Loc.eq r r2). +intros; simpl; omega. +CaseEq (split_move t1 r2); intros. +destruct p; destruct p; simpl. +rewrite (split_length t1 m0 m r2 r3); auto. +rewrite length_app; auto. +omega. +destruct b1. +simpl; omega. +case (Loc.eq r2 (fst (last (m :: b1)))); intros. +rewrite length_replace; simpl; omega. +simpl; omega. +Qed. + +Lemma stepf1_dec: + forall (S1 S2 : State), + (forall (l : Moves), (S1 <> (nil, nil, l))) -> + S2 = stepf S1 -> ltof _ mesure S2 S1. +Proof. +unfold ltof; intros S1 S2 H H0; rewrite H0. +apply stepf_dec0'; (try assumption). +Qed. + +Lemma disc1: + forall (a : Move) (l1 l2 l3 l4 : list Move), + ((a :: l1, l2, l3) <> (nil, nil, l4)). +Proof. +intros; discriminate. +Qed. + +Lemma disc2: + forall (a : Move) (l1 l2 l3 l4 : list Move), + ((l1, a :: l2, l3) <> (nil, nil, l4)). +Proof. +intros; discriminate. +Qed. +Hint Resolve disc1 disc2 . + +Lemma sameExec_reflexive: forall (r : State), sameExec r r. +Proof. +intros r; unfold sameExec, sameEnv, exec. +destruct r as [[t b] d]; trivial. +Qed. + +Definition base_case_Pmov_dec: + forall (s : State), + ({ exists l : list Move , s = (nil, nil, l) }) + + ({ forall l, (s <> (nil, nil, l)) }). +Proof. +destruct s as [[[|x tl] [|y tl']] l]; (try (right; intro; discriminate)). +left; exists l; auto. +Defined. + +Definition Pmov := + Fix + (well_founded_ltof _ mesure) (fun _ => State) + (fun (S1 : State) => + fun (Pmov : forall x, ltof _ mesure x S1 -> State) => + match base_case_Pmov_dec S1 with + left h => S1 + | right h => Pmov (stepf S1) (stepf_dec0' S1 h) end). + +Theorem Pmov_equation: forall S1, Pmov S1 = match S1 with + ((nil, nil), _) => S1 + | _ => Pmov (stepf S1) + end. +Proof. +intros S1; unfold Pmov at 1; + rewrite (Fix_eq + (well_founded_ltof _ mesure) (fun _ => State) + (fun (S1 : State) => + fun (Pmov : forall x, ltof _ mesure x S1 -> State) => + match base_case_Pmov_dec S1 with + left h => S1 + | right h => Pmov (stepf S1) (stepf_dec0' S1 h) end)). +fold Pmov. +destruct S1 as [[[|x tl] [|y tl']] l]; + match goal with + | |- match ?a with left _ => _ | right _ => _ end = _ => case a end; + (try (intros [l0 Heq]; discriminate Heq)); auto. +intros H; elim (H l); auto. +intros x f g Hfg_ext. +match goal with +| |- match ?a with left _ => _ | right _ => _ end = _ => case a end; auto. +Qed. + +Lemma sameExec_transitive: + forall (r1 r2 r3 : State), + (forall r, + In r (getdst (StateToMove r2 ++ StateBeing r2)) -> + In r (getdst (StateToMove r1 ++ StateBeing r1))) -> + (forall r, + In r (getdst (StateToMove r3 ++ StateBeing r3)) -> + In r (getdst (StateToMove r2 ++ StateBeing r2))) -> + sameExec r1 r2 -> sameExec r2 r3 -> sameExec r1 r3. +Proof. +intros r1 r2 r3; unfold sameExec, exec; (repeat rewrite getdst_app). +destruct r1 as [[t1 b1] d1]; destruct r2 as [[t2 b2] d2]; + destruct r3 as [[t3 b3] d3]; simpl. +intros Hin; intros. +rewrite H0; auto. +rewrite H1; auto. +intros. +apply (H3 x). +apply in_or_app; auto. +elim (in_app_or (getdst t2 ++ getdst b2) (getdst t3 ++ getdst b3) x); auto. +intros. +apply (H3 x). +apply in_or_app; auto. +elim (in_app_or (getdst t1 ++ getdst b1) (getdst t2 ++ getdst b2) x); auto. +Qed. + +Lemma dstep_inv_getdst: + forall (s1 s2 : State) r, + dstep s1 s2 -> + In r (getdst (StateToMove s2 ++ StateBeing s2)) -> + In r (getdst (StateToMove s1 ++ StateBeing s1)). +intros s1 s2 r STEP; inversion_clear STEP; + unfold StateToMove, StateBeing, StateDone; (repeat rewrite app_nil); + (repeat (rewrite getdst_app; simpl)); intro; auto. +Proof. +right; (try assumption). +elim (in_app_or (getdst t) (d :: nil) r); auto; (simpl; intros [H1|H1]); + [left; assumption | inversion H1]. +elim (in_app_or (getdst t1 ++ getdst t2) (r0 :: (d :: getdst b)) r); auto; + (simpl; intros). +elim (in_app_or (getdst t1) (getdst t2) r); auto; (simpl; intros). +apply in_or_app; left; apply in_or_app; left; assumption. +apply in_or_app; left; apply in_or_app; right; simpl; right; assumption. +elim H1; [intros H2 | intros [H2|H2]]. +apply in_or_app; left; apply in_or_app; right; simpl; left; auto. +apply in_or_app; right; simpl; left; auto. +apply in_or_app; right; simpl; right; assumption. +elim (in_app_or (getdst t) (getdst b ++ (d :: nil)) r); auto; (simpl; intros). +apply in_or_app; left; assumption. +elim (in_app_or (getdst b) (d :: nil) r); auto; (simpl; intros). +apply in_or_app; right; simpl; right; apply in_or_app; left; assumption. +elim H2; [intros H3 | intros H3; inversion H3]. +apply in_or_app; right; simpl; right; apply in_or_app; right; simpl; auto. +elim (in_app_or (getdst t) (getdst b ++ (d0 :: nil)) r); auto; (simpl; intros). +apply in_or_app; left; assumption. +elim (in_app_or (getdst b) (d0 :: nil) r); auto; simpl; + [intros H3 | intros [H3|H3]; [idtac | inversion H3]]. +apply in_or_app; right; simpl; right; apply in_or_app; left; assumption. +apply in_or_app; right; simpl; right; apply in_or_app; right; simpl; auto. +apply in_or_app; left; assumption. +Qed. + +Theorem STM_Pmov: forall (S1 : State), StateToMove (Pmov S1) = nil. +Proof. +intros S1; elim S1 using (well_founded_ind (Wf_nat.well_founded_ltof _ mesure)). +clear S1; intros S1; intros Hrec; destruct S1 as [[t b] d]; + rewrite Pmov_equation; destruct t. +destruct b; auto. +apply Hrec; apply stepf1_dec; auto. +apply Hrec; apply stepf1_dec; auto. +Qed. + +Theorem SB_Pmov: forall (S1 : State), StateBeing (Pmov S1) = nil. +Proof. +intros S1; elim S1 using (well_founded_ind (Wf_nat.well_founded_ltof _ mesure)). +clear S1; intros S1; intros Hrec; destruct S1 as [[t b] d]; + rewrite Pmov_equation; destruct t. +destruct b; auto. +apply Hrec; apply stepf1_dec; auto. +apply Hrec; apply stepf1_dec; auto. +Qed. + +Theorem Fpmov_correct: + forall (S1 : State), stepInv S1 -> sameExec S1 (Pmov S1). +Proof. +intros S1; elim S1 using (well_founded_ind (Wf_nat.well_founded_ltof _ mesure)). +clear S1; intros S1; intros Hrec Hinv; rewrite Pmov_equation; + destruct S1 as [[t b] d]. +assert + (forall (r : Reg) S1, + In r (getdst (StateToMove (Pmov (stepf S1)) ++ StateBeing (Pmov (stepf S1)))) -> + In r (getdst (StateToMove (stepf S1) ++ StateBeing (stepf S1)))). +intros r S1; rewrite (STM_Pmov (stepf S1)); rewrite SB_Pmov; simpl; intros. +inversion H. +destruct t. +destruct b. +apply sameExec_reflexive. +set (S1:=(nil (A:=Move), m :: b, d)). +assert (dstep S1 (stepf S1)); (try apply f2ind); unfold S1; auto. +elim Hinv; intros Hpath [SD [NO NT]]; assumption. +apply sameExec_transitive with (stepf S1); auto. +intros r; apply dstep_inv_getdst; auto. +apply dstepp_sameExec; auto; apply dstepp_trans with (stepf S1); auto. +apply dstepp_refl; auto. +apply Hrec; auto. +unfold ltof; apply step_dec; assumption. +apply (dstep_inv S1); assumption. +set (S1:=(m :: t, b, d)). +assert (dstep S1 (stepf S1)); (try apply f2ind); unfold S1; auto. +elim Hinv; intros Hpath [SD [NO NT]]; assumption. +apply sameExec_transitive with (stepf S1); auto. +intros r; apply dstep_inv_getdst; auto. +apply dstepp_sameExec; auto; apply dstepp_trans with (stepf S1); auto. +apply dstepp_refl; auto. +apply Hrec; auto. +unfold ltof; apply step_dec; assumption. +apply (dstep_inv S1); assumption. +Qed. + +Definition P_move := fun (p : Moves) => StateDone (Pmov (p, nil, nil)). + +Definition Sexec := sexec. + +Definition Get := get. + +Fixpoint listsLoc2Moves (src dst : list loc) {struct src} : Moves := + match src with + nil => nil + | s :: srcs => + match dst with + nil => nil + | d :: dsts => (s, d) :: listsLoc2Moves srcs dsts + end + end. + +Definition no_overlap (l1 l2 : list loc) := + forall r, In r l1 -> forall s, In s l2 -> r = s \/ Loc.diff r s. + +Definition no_overlap_state (S : State) := + no_overlap + (getsrc (StateToMove S ++ StateBeing S)) + (getdst (StateToMove S ++ StateBeing S)). + +Definition no_overlap_list := fun l => no_overlap (getsrc l) (getdst l). + +Lemma Indst_noOverlap_aux: + forall l1 l, + (forall (s : Reg), In s (getdst l1) -> l = s \/ Loc.diff l s) -> + noOverlap_aux l (getdst l1). +Proof. +intros; induction l1; simpl; auto. +destruct a as [a1 a2]; simpl; split. +elim (H a2); (try intros H0). +left; auto. +right; apply Loc.diff_sym; auto. +simpl; left; trivial. +apply IHl1; intros. +apply H; simpl; right; (try assumption). +Qed. + +Lemma no_overlap_noOverlap: + forall r, no_overlap_state r -> noOverlap (StateToMove r ++ StateBeing r). +Proof. +intros r; unfold noOverlap, no_overlap_state. +set (l1:=StateToMove r ++ StateBeing r). +unfold no_overlap; intros H l H0. +apply Indst_noOverlap_aux; intros; apply H; auto. +Qed. + +Theorem Fpmov_correctMoves: + forall p e r, + simpleDest p -> + no_overlap_list p -> + noTmp p -> + notemporary r -> + (forall (x : Reg), In x (getdst p) -> r = x \/ Loc.diff r x) -> + get (pexec p e) r = get (sexec (StateDone (Pmov (p, nil, nil))) e) r. +Proof. +intros p e r SD no_O notmp notempo. +generalize (Fpmov_correct (p, nil, nil)); unfold sameExec, exec; simpl; + rewrite SB_Pmov; rewrite STM_Pmov; simpl. +(repeat rewrite app_nil); intro. +apply H; auto. +unfold stepInv; simpl; (repeat split); (try (rewrite app_nil; assumption)); auto. +generalize (no_overlap_noOverlap (p, nil, nil)); simpl; intros; auto. +apply H0; auto; unfold no_overlap_list in H0 |-. +unfold no_overlap_state; simpl; (repeat rewrite app_nil); auto. +Qed. + +Theorem Fpmov_correct1: + forall (p : Moves) (e : Env) (r : Reg), + simpleDest p -> + no_overlap_list p -> + noTmp p -> + notemporary r -> + (forall (x : Reg), In x (getdst p) -> r = x \/ Loc.diff r x) -> + noWrite p r -> get e r = get (sexec (StateDone (Pmov (p, nil, nil))) e) r. +Proof. +intros p e r Hsd Hno_O HnoTmp Hrnotempo Hrno_Overlap Hnw. +rewrite <- (Fpmov_correctMoves p e); (try assumption). +destruct p; auto. +destruct m as [m1 m2]; simpl; case (Loc.eq m2 r); intros. +elim Hnw; intros; absurd (Loc.diff m2 r); auto. +rewrite e0; apply Loc.same_not_diff. +elim Hnw; intros H1 H2. +rewrite get_update_diff; (try assumption). +apply get_noWrite; (try assumption). +Qed. + +Lemma In_SD_diff: + forall (s d a1 a2 : Reg) (p : Moves), + In (s, d) p -> simpleDest ((a1, a2) :: p) -> Loc.diff a2 d. +Proof. +intros; induction p. +inversion H. +elim H; auto. +intro; subst a; elim H0; intros H1 H2; elim H1; intros; apply Loc.diff_sym; + assumption. +intro; apply IHp; auto. +apply simpleDest_pop2 with a; (try assumption). +Qed. + +Theorem pexec_correct: + forall (e : Env) (m : Move) (p : Moves), + In m p -> simpleDest p -> (let (s, d) := m in get (pexec p e) d = get e s). +Proof. +induction p; intros. +elim H. +destruct m. +elim (in_inv H); intro. +rewrite H1; simpl; rewrite get_update_id; auto. +destruct a as [a1 a2]; simpl. +rewrite get_update_diff. +apply IHp; auto. +apply (simpleDest_pop (a1, a2)); (try assumption). +apply (In_SD_diff r) with ( p := p ) ( a1 := a1 ); auto. +Qed. + +Lemma In_noTmp_notempo: + forall (s d : Reg) (p : Moves), In (s, d) p -> noTmp p -> notemporary d. +Proof. +intros; unfold notemporary; induction p. +inversion H. +elim H; intro. +subst a; elim H0; intros H1 [H3 H2]; (try assumption). +intro; apply IHp; auto. +destruct a; elim H0; intros _ [H2 H3]; (try assumption). +Qed. + +Lemma In_Indst: forall s d p, In (s, d) p -> In d (getdst p). +Proof. +intros; induction p; auto. +destruct a; simpl. +elim H; intro. +left; inversion H0; trivial. +right; apply IHp; auto. +Qed. + +Lemma In_SD_diff': + forall (d a1 a2 : Reg) (p : Moves), + In d (getdst p) -> simpleDest ((a1, a2) :: p) -> Loc.diff a2 d. +Proof. +intros d a1 a2 p H H0; induction p. +inversion H. +destruct a; elim H. +elim H0; simpl; intros. +subst r0. +elim H1; intros H3 H4; apply Loc.diff_sym; assumption. +intro; apply IHp; (try assumption). +apply simpleDest_pop2 with (r, r0); (try assumption). +Qed. + +Lemma In_SD_no_o: + forall (s d : Reg) (p : Moves), + In (s, d) p -> + simpleDest p -> forall (x : Reg), In x (getdst p) -> d = x \/ Loc.diff d x. +Proof. +intros s d p Hin Hsd; induction p. +inversion Hin. +destruct a as [a1 a2]; elim Hin; intros. +inversion H; subst d; subst s. +elim H0; intros H1; [left | right]; (try assumption). +apply (In_SD_diff' x a1 a2 p); auto. +elim H0. +intro; subst x. +right; apply Loc.diff_sym; apply (In_SD_diff s d a1 a2 p); auto. +intro; apply IHp; auto. +apply (simpleDest_pop (a1, a2)); assumption. +Qed. + +Lemma getdst_map: forall p, getdst p = map (fun x => snd x) p. +Proof. +induction p. +simpl; auto. +destruct a; simpl. +rewrite IHp; auto. +Qed. + +Lemma getsrc_map: forall p, getsrc p = map (fun x => fst x) p. +Proof. +induction p. +simpl; auto. +destruct a; simpl. +rewrite IHp; auto. +Qed. + +Theorem Fpmov_correct2: + forall (p : Moves) (e : Env) (m : Move), + In m p -> + simpleDest p -> + no_overlap_list p -> + noTmp p -> + (let (s, d) := m in get (sexec (StateDone (Pmov (p, nil, nil))) e) d = get e s). +Proof. +intros p e m Hin Hsd Hno_O HnoTmp; destruct m as [s d]; + generalize (Fpmov_correctMoves p e); intros. +rewrite <- H; auto. +apply pexec_correct with ( m := (s, d) ); auto. +apply (In_noTmp_notempo s d p); auto. +apply (In_SD_no_o s d p Hin Hsd). +Qed. + +Lemma notindst_nW: forall a p, Loc.notin a (getdst p) -> noWrite p a. +Proof. +induction p; simpl; auto. +destruct a0 as [a1 a2]. +simpl. +intros H; elim H; intro; split. +apply Loc.diff_sym; (try assumption). +apply IHp; auto. +Qed. + +Lemma disjoint_tmp__noTmp: + forall p, + Loc.disjoint (getsrc p) temporaries -> + Loc.disjoint (getdst p) temporaries -> noTmp p. +Proof. +induction p; simpl; auto. +destruct a as [a1 a2]; simpl getsrc; simpl getdst; unfold Loc.disjoint; intros; + (repeat split). +intro; unfold T; case (Loc.type r); apply H; (try (left; trivial; fail)). +right; left; trivial. +right; right; right; right; left; trivial. +intro; unfold T; case (Loc.type r); apply H0; (try (left; trivial; fail)). +right; left; trivial. +right; right; right; right; left; trivial. +apply IHp. +apply Loc.disjoint_cons_left with a1; auto. +apply Loc.disjoint_cons_left with a2; auto. +Qed. + +Theorem Fpmov_correct_IT3: + forall p rs, + simpleDest p -> + no_overlap_list p -> + Loc.disjoint (getsrc p) temporaries -> + Loc.disjoint (getdst p) temporaries -> + (sexec (StateDone (Pmov (p, nil, nil))) rs) (R IT3) = rs (R IT3). +Proof. +intros p rs Hsd Hno_O Hdistmpsrc Hdistmpdst. +generalize (Fpmov_correctMoves p rs); unfold get, Locmap.get; intros H2. +rewrite <- H2; auto. +generalize (get_noWrite p (R IT3)); unfold get, Locmap.get; intros. +rewrite <- H; auto. +apply notindst_nW. +apply (Loc.disjoint_notin temporaries). +apply Loc.disjoint_sym; auto. +right; right; left; trivial. +apply disjoint_tmp__noTmp; auto. +unfold notemporary, T. +intros x; case (Loc.type x); simpl; intro; discriminate. +intros x H; right; apply Loc.in_notin_diff with (getdst p); auto. +apply Loc.disjoint_notin with temporaries; auto. +apply Loc.disjoint_sym; auto. +right; right; left; trivial. +Qed. + +Theorem Fpmov_correct_map: + forall p rs, + simpleDest p -> + no_overlap_list p -> + Loc.disjoint (getsrc p) temporaries -> + Loc.disjoint (getdst p) temporaries -> + List.map (sexec (StateDone (Pmov (p, nil, nil))) rs) (getdst p) = + List.map rs (getsrc p). +Proof. +intros; rewrite getsrc_map; rewrite getdst_map; rewrite list_map_compose; + rewrite list_map_compose; apply list_map_exten; intros. +generalize (Fpmov_correct2 p rs x). +destruct x; simpl. +unfold get, Locmap.get; intros; auto. +rewrite H4; auto. +apply disjoint_tmp__noTmp; auto. +Qed. + +Theorem Fpmov_correct_ext: + forall p rs, + simpleDest p -> + no_overlap_list p -> + Loc.disjoint (getsrc p) temporaries -> + Loc.disjoint (getdst p) temporaries -> + forall l, + Loc.notin l (getdst p) -> + Loc.notin l temporaries -> + (sexec (StateDone (Pmov (p, nil, nil))) rs) l = rs l. +Proof. +intros; generalize (Fpmov_correct1 p rs l); unfold get, Locmap.get; intros. +rewrite <- H5; auto. +apply disjoint_tmp__noTmp; auto. +unfold notemporary; simpl in H4 |-; unfold T; intros x; case (Loc.type x). +elim H4; + [intros H6 H7; elim H7; [intros H8 H9; (try clear H7 H4); (try exact H8)]]. +elim H4; + [intros H6 H7; elim H7; + [intros H8 H9; elim H9; + [intros H10 H11; elim H11; + [intros H12 H13; elim H13; + [intros H14 H15; (try clear H13 H11 H9 H7 H4); (try exact H14)]]]]]. +unfold no_overlap_list, no_overlap in H0 |-; intros. +case (Loc.eq l x). +intros e; left; (try assumption). +intros n; right; (try assumption). +apply Loc.in_notin_diff with (getdst p); auto. +apply notindst_nW; auto. +Qed. -- cgit