From 73729d23ac13275c0d28d23bc1b1f6056104e5d9 Mon Sep 17 00:00:00 2001 From: xleroy Date: Mon, 4 Sep 2006 15:08:29 +0000 Subject: Fusion de la branche "traces": - Ajout de traces d'evenements d'E/S dans les semantiques - Ajout constructions switch et allocation dynamique - Initialisation des variables globales - Portage Coq 8.1 beta Debut d'integration du front-end C: - Traduction Clight -> Csharpminor dans cfrontend/ - Modifications de Csharpminor et Globalenvs en consequence. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@72 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- backend/Parallelmove.v | 2759 +++++------------------------------------------- 1 file changed, 260 insertions(+), 2499 deletions(-) (limited to 'backend/Parallelmove.v') diff --git a/backend/Parallelmove.v b/backend/Parallelmove.v index f95416eb..b2ec930b 100644 --- a/backend/Parallelmove.v +++ b/backend/Parallelmove.v @@ -1,2529 +1,290 @@ -(** Translation of parallel moves into sequences of individual moves *) +Require Import Coqlib. +Require Parmov. +Require Import Values. +Require Import Events. +Require Import AST. +Require Import Locations. +Require Import Conventions. -(** 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. +Definition temp_for (l: loc) : loc := + match Loc.type l with Tint => R IT2 | Tfloat => R FT2 end. - 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. +Definition parmove (srcs dsts: list loc) := + Parmov.parmove2 loc temp_for Loc.eq srcs dsts. - 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 - ## -*) +Definition moves := (list (loc * loc))%type. -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)). +Definition exec_seq (m: moves) (e: Locmap.t) : Locmap.t := + Parmov.exec_seq loc val Loc.eq m e. + +Lemma temp_for_charact: + forall l, temp_for l = R IT2 \/ temp_for l = R FT2. 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. + intro; unfold temp_for. destruct (Loc.type l); tauto. 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. + +Lemma is_not_temp_charact: + forall l, + Parmov.is_not_temp loc temp_for l <-> l <> R IT2 /\ l <> R FT2. +Proof. + intros. unfold Parmov.is_not_temp. + destruct (Loc.eq l (R IT2)). + subst l. intuition. apply (H (R IT2)). reflexivity. discriminate. + destruct (Loc.eq l (R FT2)). + subst l. intuition. apply (H (R FT2)). reflexivity. + assert (forall d, l <> temp_for d). + intro. elim (temp_for_charact d); congruence. + intuition. Qed. - -Lemma step_inv_NoOverlap: - forall (s1 s2 : State) r, - step s1 s2 -> notemporary r -> stepInv s1 -> NoOverlap r s1 -> NoOverlap r s2. + +Lemma disjoint_temp_not_temp: + forall l, Loc.notin l temporaries -> Parmov.is_not_temp loc temp_for l. 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. + intros. rewrite is_not_temp_charact. + unfold temporaries in H; simpl in H. + split; apply Loc.diff_not_eq; tauto. 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)). + +Lemma loc_norepet_norepet: + forall l, Loc.norepet l -> list_norepet l. 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. + induction 1; constructor. + apply Loc.notin_not_in; auto. auto. 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. + +Lemma parmove_prop_1: + forall srcs dsts, + List.length srcs = List.length dsts -> + Loc.norepet dsts -> + Loc.disjoint srcs temporaries -> + Loc.disjoint dsts temporaries -> + forall e, + let e' := exec_seq (parmove srcs dsts) e in + List.map e' dsts = List.map e srcs /\ + forall l, ~In l dsts -> l <> R IT2 -> l <> R FT2 -> e' l = e l. +Proof. + intros. + assert (NR: list_norepet dsts) by (apply loc_norepet_norepet; auto). + assert (NTS: forall r, In r srcs -> Parmov.is_not_temp loc temp_for r). + intros. apply disjoint_temp_not_temp. apply Loc.disjoint_notin with srcs; auto. + assert (NTD: forall r, In r dsts -> Parmov.is_not_temp loc temp_for r). + intros. apply disjoint_temp_not_temp. apply Loc.disjoint_notin with dsts; auto. + generalize (Parmov.parmove2_correctness loc temp_for val Loc.eq srcs dsts H NR NTS NTD e). + change (Parmov.exec_seq loc val Loc.eq (Parmov.parmove2 loc temp_for Loc.eq srcs dsts) e) with e'. + intros [A B]. + split. auto. intros. apply B. auto. rewrite is_not_temp_charact; 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. + +Lemma parmove_prop_2: + forall srcs dsts s d, + In (s, d) (parmove srcs dsts) -> + (In s srcs \/ s = R IT2 \/ s = R FT2) + /\ (In d dsts \/ d = R IT2 \/ d = R FT2). +Proof. + intros srcs dsts. + set (mu := List.combine srcs dsts). + assert (forall s d, Parmov.wf_move loc temp_for mu s d -> + (In s srcs \/ s = R IT2 \/ s = R FT2) + /\ (In d dsts \/ d = R IT2 \/ d = R FT2)). + unfold mu; induction 1. + split. + left. eapply List.in_combine_l; eauto. + left. eapply List.in_combine_r; eauto. + split. + right. apply temp_for_charact. + tauto. + split. + tauto. + right. apply temp_for_charact. + intros. apply H. + apply (Parmov.parmove2_wf_moves loc temp_for Loc.eq srcs dsts s d H0). Qed. - -Lemma dstep_inv: - forall (r1 r2 : State), dstep r1 r2 -> stepInv r1 -> stepInv r2. + +Lemma loc_type_temp_for: + forall l, Loc.type (temp_for l) = Loc.type l. Proof. -intros. -apply (stepp_inv r1 r2); auto. -apply dstep_step; auto. + intros; unfold temp_for. destruct (Loc.type l); reflexivity. 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. + +Lemma loc_type_combine: + forall srcs dsts, + List.map Loc.type srcs = List.map Loc.type dsts -> + forall s d, + In (s, d) (List.combine srcs dsts) -> + Loc.type s = Loc.type d. +Proof. + induction srcs; destruct dsts; simpl; intros; try discriminate. + elim H0. + elim H0; intros. inversion H1; subst. congruence. + apply IHsrcs with dsts. congruence. 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. + +Lemma parmove_prop_3: + forall srcs dsts, + List.map Loc.type srcs = List.map Loc.type dsts -> + forall s d, + In (s, d) (parmove srcs dsts) -> Loc.type s = Loc.type d. +Proof. + intros srcs dsts TYP. + set (mu := List.combine srcs dsts). + assert (forall s d, Parmov.wf_move loc temp_for mu s d -> + Loc.type s = Loc.type d). + unfold mu; induction 1. + eapply loc_type_combine; eauto. + rewrite loc_type_temp_for; auto. + rewrite loc_type_temp_for; auto. + intros. apply H. + apply (Parmov.parmove2_wf_moves loc temp_for Loc.eq srcs dsts s d H0). 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. +Section EQUIVALENCE. -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. +Variables srcs dsts: list loc. +Hypothesis LENGTH: List.length srcs = List.length dsts. +Hypothesis NOREPET: Loc.norepet dsts. +Hypothesis NO_OVERLAP: Loc.no_overlap srcs dsts. +Hypothesis NO_SRCS_TEMP: Loc.disjoint srcs temporaries. +Hypothesis NO_DSTS_TEMP: Loc.disjoint dsts temporaries. + +Definition no_overlap_dests (l: loc) : Prop := + forall d, In d dsts -> l = d \/ Loc.diff l d. + +Lemma dests_no_overlap_dests: + forall l, In l dsts -> no_overlap_dests l. +Proof. + assert (forall d, Loc.norepet d -> + forall l1 l2, In l1 d -> In l2 d -> l1 = l2 \/ Loc.diff l1 l2). + induction 1; simpl; intros. + contradiction. + elim H1; intro; elim H2; intro. + left; congruence. + right. subst l1. eapply Loc.in_notin_diff; eauto. + right. subst l2. apply Loc.diff_sym. eapply Loc.in_notin_diff; eauto. + eauto. + intros; red; intros. eauto. Qed. - -Lemma getsrc_map: forall p, getsrc p = map (fun x => fst x) p. + +Lemma notin_dests_no_overlap_dests: + forall l, Loc.notin l dsts -> no_overlap_dests l. Proof. -induction p. -simpl; auto. -destruct a; simpl. -rewrite IHp; auto. + intros; red; intros. + right. eapply Loc.in_notin_diff; eauto. 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). + +Lemma source_no_overlap_dests: + forall s, In s srcs \/ s = R IT2 \/ s = R FT2 -> no_overlap_dests 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). + intros. elim H; intro. exact (NO_OVERLAP s H0). + elim H0; intro; subst s; red; intros; + right; apply Loc.diff_sym; apply NO_DSTS_TEMP; auto; simpl; tauto. Qed. - -Lemma notindst_nW: forall a p, Loc.notin a (getdst p) -> noWrite p a. + +Lemma source_not_temp1: + forall s, In s srcs \/ s = R IT2 \/ s = R FT2 -> Loc.diff s (R IT1) /\ Loc.diff s (R FT1). 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. + intros. elim H; intro. + split; apply NO_SRCS_TEMP; auto; simpl; tauto. + elim H0; intro; subst s; simpl; split; congruence. 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. + +Lemma dest_noteq_diff: + forall d l, + In d dsts \/ d = R IT2 \/ d = R FT2 -> + l <> d -> + no_overlap_dests l -> + Loc.diff l d. +Proof. + intros. elim H; intro. + elim (H1 d H2); intro. congruence. auto. + assert (forall r, l <> R r -> Loc.diff l (R r)). + intros. destruct l; simpl. congruence. destruct s; auto. + elim H2; intro; subst d; 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. + +Definition locmap_equiv (e1 e2: Locmap.t): Prop := + forall l, + no_overlap_dests l -> Loc.diff l (R IT1) -> Loc.diff l (R FT1) -> e2 l = e1 l. + +Definition effect_move (src dst: loc) (e e': Locmap.t): Prop := + e' dst = e src /\ + forall l, Loc.diff l dst -> Loc.diff l (R IT1) -> Loc.diff l (R FT1) -> e' l = e l. + +Inductive effect_seqmove: list (loc * loc) -> Locmap.t -> Locmap.t -> Prop := + | effect_seqmove_nil: forall e, + effect_seqmove nil e e + | effect_seqmove_cons: forall s d m e1 e2 e3, + effect_move s d e1 e2 -> + effect_seqmove m e2 e3 -> + effect_seqmove ((s, d) :: m) e1 e3. + +Lemma effect_move_equiv: + forall s d e1 e2 e1', + (In s srcs \/ s = R IT2 \/ s = R FT2) -> + (In d dsts \/ d = R IT2 \/ d = R FT2) -> + locmap_equiv e1 e2 -> effect_move s d e1 e1' -> + locmap_equiv e1' (Parmov.update loc val Loc.eq d (e2 s) e2). +Proof. + intros. destruct H2. red; intros. + unfold Parmov.update. destruct (Loc.eq l d). + subst l. elim (source_not_temp1 _ H); intros. + rewrite H2. apply H1; auto. apply source_no_overlap_dests; auto. + rewrite H3; auto. apply dest_noteq_diff; auto. 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. + +Lemma effect_seqmove_equiv: + forall mu e1 e1', + effect_seqmove mu e1 e1' -> + forall e2, + (forall s d, In (s, d) mu -> + (In s srcs \/ s = R IT2 \/ s = R FT2) /\ + (In d dsts \/ d = R IT2 \/ d = R FT2)) -> + locmap_equiv e1 e2 -> + locmap_equiv e1' (exec_seq mu e2). +Proof. + induction 1; intros. + simpl. auto. + simpl. apply IHeffect_seqmove. + intros. apply H1. apply in_cons; auto. + destruct (H1 s d (in_eq _ _)). + eapply effect_move_equiv; eauto. 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. + +Lemma effect_parmove: + forall e e', + effect_seqmove (parmove srcs dsts) e e' -> + List.map e' dsts = List.map e srcs /\ + e' (R IT3) = e (R IT3) /\ + forall l, Loc.notin l dsts -> Loc.notin l temporaries -> e' l = e l. +Proof. + set (mu := parmove srcs dsts). intros. + assert (locmap_equiv e e) by (red; auto). + generalize (effect_seqmove_equiv mu e e' H e (parmove_prop_2 srcs dsts) H0). + intro. + generalize (parmove_prop_1 srcs dsts LENGTH NOREPET NO_SRCS_TEMP NO_DSTS_TEMP e). + fold mu. intros [A B]. + (* e' dsts = e srcs *) + split. rewrite <- A. apply list_map_exten; intros. + apply H1. apply dests_no_overlap_dests; auto. + apply NO_DSTS_TEMP; auto; simpl; tauto. + apply NO_DSTS_TEMP; auto; simpl; tauto. + (* e' IT3 = e IT3 *) + split. + assert (Loc.notin (R IT3) dsts). + apply Loc.disjoint_notin with temporaries. + apply Loc.disjoint_sym; auto. simpl; tauto. + transitivity (exec_seq mu e (R IT3)). + symmetry. apply H1. apply notin_dests_no_overlap_dests. auto. + simpl; congruence. simpl; congruence. + apply B. apply Loc.notin_not_in; auto. congruence. congruence. + (* other locations *) + intros. transitivity (exec_seq mu e l). + symmetry. apply H1. apply notin_dests_no_overlap_dests; auto. + eapply Loc.in_notin_diff; eauto. simpl; tauto. + eapply Loc.in_notin_diff; eauto. simpl; tauto. + apply B. apply Loc.notin_not_in; auto. + apply Loc.diff_not_eq. eapply Loc.in_notin_diff; eauto. simpl; tauto. + apply Loc.diff_not_eq. eapply Loc.in_notin_diff; eauto. simpl; tauto. Qed. + +End EQUIVALENCE. + -- cgit