aboutsummaryrefslogtreecommitdiffstats
path: root/backend/Alloctyping_aux.v
diff options
context:
space:
mode:
Diffstat (limited to 'backend/Alloctyping_aux.v')
-rw-r--r--backend/Alloctyping_aux.v895
1 files changed, 895 insertions, 0 deletions
diff --git a/backend/Alloctyping_aux.v b/backend/Alloctyping_aux.v
new file mode 100644
index 00000000..0013c240
--- /dev/null
+++ b/backend/Alloctyping_aux.v
@@ -0,0 +1,895 @@
+(** Type preservation for parallel move compilation. *)
+
+(** This file, contributed by Laurence Rideau, shows that the parallel
+ move compilation algorithm (file [Parallelmove]) generates a well-typed
+ sequence of LTL instructions, provided the original problem is well-typed:
+ the types of source and destination locations match pairwise. *)
+
+Require Import Coqlib.
+Require Import Locations.
+Require Import LTL.
+Require Import Allocation.
+Require Import LTLtyping.
+Require Import Allocproof_aux.
+Require Import Parallelmove.
+Require Import Inclusion.
+
+Section wt_move_correction.
+Variable tf : LTL.function.
+Variable loc_read_ok : loc -> Prop.
+Hypothesis loc_read_ok_R : forall r, loc_read_ok (R r).
+Variable loc_write_ok : loc -> Prop.
+Hypothesis loc_write_ok_R : forall r, loc_write_ok (R r).
+
+Let locs_read_ok (ll : list loc) : Prop :=
+ forall l, In l ll -> loc_read_ok l.
+
+Let locs_write_ok (ll : list loc) : Prop :=
+ forall l, In l ll -> loc_write_ok l.
+
+Hypothesis
+ wt_add_move :
+ forall (src dst : loc) (b : LTL.block),
+ loc_read_ok src ->
+ loc_write_ok dst ->
+ Loc.type src = Loc.type dst ->
+ wt_block tf b -> wt_block tf (add_move src dst b).
+
+Lemma in_move__in_srcdst:
+ forall m p, In m p -> In (fst m) (getsrc p) /\ In (snd m) (getdst p).
+Proof.
+intros; induction p.
+inversion H.
+destruct a as [a1 a2]; destruct m as [m1 m2]; simpl.
+elim H; intro.
+inversion H0.
+subst a2; subst a1.
+split; [left; trivial | left; trivial].
+split; right; (elim IHp; simpl; intros; auto).
+Qed.
+
+Lemma T_type: forall r, Loc.type r = Loc.type (T r).
+Proof.
+intro; unfold T.
+case (Loc.type r); auto.
+Qed.
+
+Theorem incl_nil: forall A (l : list A), incl nil l.
+Proof.
+intros A l a; simpl; intros H; case H.
+Qed.
+Hint Resolve incl_nil :datatypes.
+
+Lemma split_move_incl:
+ forall (l t1 t2 : Moves) (s d : Reg),
+ split_move l s = Some (t1, d, t2) -> incl t1 l /\ incl t2 l.
+Proof.
+induction l.
+simpl; (intros; discriminate).
+intros t1 t2 s d; destruct a as [a1 a2]; simpl.
+case (Loc.eq a1 s); intro.
+intros.
+inversion H.
+split; auto.
+apply incl_nil.
+apply incl_tl; apply incl_refl; auto.
+caseEq (split_move l s); intro; (try (intros; discriminate)).
+destruct p as [[p1 p2] p3].
+intros.
+inversion H0.
+elim (IHl p1 p3 s p2); intros; auto.
+subst p3.
+split; auto.
+generalize H1; unfold incl; simpl.
+intros H4 a [H7|H6]; [try exact H7 | idtac].
+left; (try assumption).
+right; apply H4; auto.
+apply incl_tl; auto.
+Qed.
+
+Lemma in_split_move:
+ forall (l t1 t2 : Moves) (s d : Reg),
+ split_move l s = Some (t1, d, t2) -> In (s, d) l.
+Proof.
+induction l.
+simpl; intros; discriminate.
+intros t1 t2 s d; simpl.
+destruct a as [a1 a2].
+case (Loc.eq a1 s).
+intros.
+inversion H.
+subst a1; left; auto.
+intro; caseEq (split_move l s); (intros; (try discriminate)).
+destruct p as [[p1 p2] p3].
+right; inversion H0.
+subst p2.
+apply (IHl p1 p3); auto.
+Qed.
+
+Lemma move_types_stepf:
+ forall S1,
+ (forall x1 x2,
+ In (x1, x2) (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)) ->
+ Loc.type x1 = Loc.type x2) ->
+ forall x1 x2,
+ In
+ (x1, x2)
+ (StateToMove (stepf S1) ++ (StateBeing (stepf S1) ++ StateDone (stepf S1))) ->
+ Loc.type x1 = Loc.type x2.
+Proof.
+intros S1 H x1 x2.
+destruct S1 as [[t1 b1] d1]; set (S1:=(t1, b1, d1)); destruct t1; destruct b1;
+ auto; simpl StateToMove in H |-; simpl StateBeing in H |-;
+ simpl StateDone in H |-; simpl app in H |-.
+intro;
+ elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+assert (StateToMove (stepf S1) = nil).
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq d (fst (last b1))); case b1; simpl; auto.
+rewrite H1; intros H2; inversion H2.
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+assert
+ (StateBeing (stepf S1) = nil \/
+ (StateBeing (stepf S1) = b1 \/ StateBeing (stepf S1) = replace_last_s b1)).
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq d (fst (last b1))); case b1; simpl; auto.
+elim H2; [intros H3; (try clear H2); (try exact H3) | intros H3; (try clear H2)].
+rewrite H3; intros H4; inversion H4.
+elim H3; [intros H2; (try clear H3); (try exact H2) | intros H2; (try clear H3)].
+rewrite H2; intros H4.
+apply H; (try in_tac).
+rewrite H2; intros H4.
+caseEq b1; intro; simpl; auto.
+rewrite H3 in H4; simpl in H4 |-; inversion H4.
+intros l H5; rewrite H5 in H4.
+generalize (app_rewriter _ l m0).
+intros [y [r H3]]; (try exact H3).
+rewrite H3 in H4.
+destruct y.
+rewrite last_replace in H4.
+elim (in_app_or r ((T r0, r1) :: nil) (x1, x2)); auto.
+intro; apply H.
+rewrite H5.
+rewrite H3; in_tac.
+intros H6; inversion H6.
+inversion H7.
+rewrite <- T_type.
+rewrite <- H10; apply H.
+rewrite H5; rewrite H3; (try in_tac).
+assert (In (r0, r1) ((r0, r1) :: nil)); [simpl; auto | in_tac].
+inversion H7.
+intro.
+destruct m as [s d].
+assert
+ (StateDone (stepf S1) = (s, d) :: d1 \/
+ StateDone (stepf S1) = (s, d) :: ((d, T d) :: d1)).
+simpl.
+case (Loc.eq d (fst (last b1))); case b1; simpl; auto.
+elim H3; [intros H4; (try clear H3); (try exact H4) | intros H4; (try clear H3)].
+apply H; (try in_tac).
+rewrite H4 in H2; in_tac.
+rewrite H4 in H2.
+simpl in H2 |-.
+elim H2; [intros H3; apply H | intros H3; elim H3; intros; [idtac | apply H]];
+ (try in_tac).
+simpl; left; auto.
+inversion H5; apply T_type.
+intro;
+ elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d); simpl; intros; apply H; in_tac.
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d); intros; apply H; (try in_tac).
+inversion H2.
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d); intros; apply H; (try in_tac).
+simpl in H2 |-; in_tac.
+simpl in H2 |-; in_tac.
+intro;
+ elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0); [simpl; intros; apply H; in_tac | idtac].
+caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+intros Hsplit Hd; simpl StateToMove; intro.
+elim (split_move_incl t1 t2 d2 d0 b2 Hsplit); auto.
+intros; apply H.
+assert (In (x1, x2) ((s, d) :: (t1 ++ t1))).
+generalize H1; simpl; intros.
+elim H4; [intros H5; left; (try exact H5) | intros H5; right].
+elim (in_app_or t2 d2 (x1, x2)); auto; intro; apply in_or_app; left.
+unfold incl in H2 |-.
+apply H2; auto.
+unfold incl in H3 |-; apply H3; auto.
+in_tac.
+intro; case (Loc.eq d0 (fst (last b1))); case b1; auto; simpl StateToMove;
+ intros; apply H; in_tac.
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0).
+intros e; rewrite <- e; simpl StateBeing.
+rewrite <- e in H.
+intro; apply H; in_tac.
+caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+simpl StateBeing.
+intros.
+apply H.
+generalize (in_split_move t1 t2 d2 d0 b2 H2).
+intros.
+elim H3; intros.
+rewrite <- H5.
+in_tac.
+in_tac.
+caseEq b1.
+simpl; intros e n F; elim F.
+intros m l H3 H4.
+case (Loc.eq d0 (fst (last (m :: l)))).
+generalize (app_rewriter Move l m).
+intros [y [r H5]]; rewrite H5.
+simpl StateBeing.
+destruct y as [y1 y2]; generalize (last_replace r y1 y2).
+simpl; intros heq H6.
+unfold Move in heq |-; unfold Move.
+rewrite heq.
+intro.
+elim (in_app_or r ((T y1, y2) :: nil) (x1, x2)); auto.
+intro; apply H.
+rewrite H3; rewrite H5; in_tac.
+simpl; intros [H8|H8]; inversion H8.
+rewrite <- T_type.
+apply H.
+rewrite H3; rewrite H5.
+rewrite <- H11; assert (In (y1, y2) ((y1, y2) :: nil)); auto.
+simpl; auto.
+in_tac.
+simpl StateBeing; intros.
+apply H; rewrite H3; (try in_tac).
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0); [simpl; intros; apply H; in_tac | idtac].
+caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+intros Hsplit Hd; simpl StateDone; intro.
+apply H; (try in_tac).
+case (Loc.eq d0 (fst (last b1))); case b1; simpl StateDone; intros;
+ (try (apply H; in_tac)).
+elim H3; intros.
+apply H.
+assert (In (x1, x2) ((s0, d0) :: nil)); auto.
+rewrite H4; auto.
+simpl; left; auto.
+in_tac.
+elim H4; intros.
+inversion H5; apply T_type.
+apply H; in_tac.
+Qed.
+
+Lemma move_types_res:
+ forall S1,
+ (forall x1 x2,
+ In (x1, x2) (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)) ->
+ Loc.type x1 = Loc.type x2) ->
+ forall x1 x2,
+ In
+ (x1, x2)
+ (StateToMove (Pmov S1) ++ (StateBeing (Pmov S1) ++ StateDone (Pmov S1))) ->
+ Loc.type x1 = Loc.type x2.
+Proof.
+intros S1; elim S1 using (well_founded_ind (Wf_nat.well_founded_ltof _ mesure)).
+clear S1; intros S1 Hrec.
+destruct S1 as [[t b] d]; set (S1:=(t, b, d)).
+unfold S1; rewrite Pmov_equation; intros.
+destruct t; auto.
+destruct b; auto.
+apply (Hrec (stepf S1)).
+apply stepf1_dec; auto.
+apply move_types_stepf; auto.
+unfold S1; auto.
+apply (Hrec (stepf S1)).
+apply stepf1_dec; auto.
+apply move_types_stepf; auto.
+unfold S1; auto.
+Qed.
+
+Lemma srcdst_tmp2_stepf:
+ forall S1 x1 x2,
+ In
+ (x1, x2)
+ (StateToMove (stepf S1) ++ (StateBeing (stepf S1) ++ StateDone (stepf S1))) ->
+ (In x1 temporaries2 \/
+ In x1 (getsrc (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)))) /\
+ (In x2 temporaries2 \/
+ In x2 (getdst (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)))).
+Proof.
+intros S1 x1 x2 H.
+(repeat rewrite getsrc_app); (repeat rewrite getdst_app).
+destruct S1 as [[t1 b1] d1]; set (S1:=(t1, b1, d1)); destruct t1; destruct b1;
+ auto.
+simpl in H |-.
+elim (in_move__in_srcdst (x1, x2) d1); intros; auto.
+elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+assert (StateToMove (stepf S1) = nil).
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq d (fst (last b1))); case b1; simpl; auto.
+rewrite H0; intros H2; inversion H2.
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+simpl stepf.
+destruct m as [s d].
+caseEq b1.
+simpl.
+intros h1 h2; inversion h2.
+intros m l heq; generalize (app_rewriter _ l m).
+intros [y [r H3]]; (try exact H3).
+rewrite H3.
+destruct y.
+rewrite last_app; simpl fst.
+case (Loc.eq d r0).
+intros heqd.
+rewrite last_replace.
+simpl.
+intro; elim (in_app_or r ((T r0, r1) :: nil) (x1, x2)); auto.
+rewrite heq; rewrite H3.
+rewrite getsrc_app; simpl; rewrite getdst_app; simpl.
+intro; elim (in_move__in_srcdst (x1, x2) r); auto; simpl; intros; split; right;
+ right; in_tac.
+intro.
+inversion H2; inversion H4.
+split.
+unfold T; case (Loc.type r0); left; [left | right]; auto.
+right; right; (try assumption).
+rewrite heq; rewrite H3.
+rewrite H7; simpl.
+rewrite getdst_app; simpl.
+assert (In x2 (x2 :: nil)); simpl; auto.
+in_tac.
+simpl StateBeing.
+intros; elim (in_move__in_srcdst (x1, x2) (r ++ ((r0, r1) :: nil))); auto;
+ intros; split; right; right.
+unfold snd in H4 |-; unfold fst in H2 |-; rewrite heq; rewrite H3; (try in_tac).
+unfold snd in H4 |-; unfold fst in H2 |-; rewrite heq; rewrite H3; (try in_tac).
+simpl stepf.
+destruct m as [s d].
+caseEq b1; intro.
+simpl StateDone; intro.
+unfold S1, StateToMove, StateBeing.
+simpl app.
+elim (in_move__in_srcdst (x1, x2) ((s, d) :: d1)); auto; intros; split; right.
+simpl snd in H4 |-; simpl fst in H3 |-; simpl getdst in H4 |-;
+ simpl getsrc in H3 |-; (try in_tac).
+simpl snd in H4 |-; simpl fst in H3 |-; simpl getdst in H4 |-;
+ simpl getsrc in H3 |-; (try in_tac).
+intros; generalize (app_rewriter _ l m).
+intros [y [r H4]].
+generalize H2; rewrite H4; rewrite last_app.
+destruct y as [y1 y2].
+simpl fst.
+case (Loc.eq d y1).
+simpl StateDone; intros.
+elim H3; [intros H6; inversion H6; (try exact H6) | intros H6; (try clear H5)].
+simpl; split; right; left; auto.
+elim H6; [intros H5; inversion H5; (try exact H5) | intros H5; (try clear H6)].
+split; [right; simpl; right | left].
+rewrite H1; rewrite H4; rewrite getsrc_app; simpl getsrc.
+rewrite <- e; rewrite H8; assert (In x1 (x1 :: nil)); simpl; auto; (try in_tac).
+unfold T; case (Loc.type x1); simpl; auto.
+elim (in_move__in_srcdst (x1, x2) d1); auto; intros; split; right; right;
+ (try in_tac).
+intro; simpl StateDone.
+unfold S1, StateToMove, StateBeing, StateDone.
+simpl getsrc; simpl app; (try in_tac).
+intro; elim (in_move__in_srcdst (x1, x2) ((s, d) :: d1));
+ (auto; (simpl fst; simpl snd; simpl getsrc; simpl getdst); intros);
+ (split; right; (try in_tac)).
+unfold S1, StateToMove, StateBeing, StateDone.
+elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d).
+simpl StateToMove.
+intros; elim (in_move__in_srcdst (x1, x2) t1); auto;
+ (repeat (rewrite getsrc_app; simpl getsrc));
+ (repeat (rewrite getdst_app; simpl getdst)); simpl fst; simpl snd; intros;
+ split; right; simpl; right; (try in_tac).
+simpl StateToMove.
+intros; elim (in_move__in_srcdst (x1, x2) t1); auto;
+ (repeat (rewrite getsrc_app; simpl getsrc));
+ (repeat (rewrite getdst_app; simpl getdst)); simpl fst; simpl snd; intros;
+ split; right; simpl; right; (try in_tac).
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d).
+simpl StateBeing; intros h1 h2; inversion h2.
+simpl StateBeing; intros h1 h2.
+elim (in_move__in_srcdst (x1, x2) ((s, d) :: nil)); auto; simpl fst; simpl snd;
+ simpl; intros; split; right; (try in_tac).
+elim H1; [intros H3; left; (try exact H3) | intros H3; inversion H3].
+elim H2; [intros H3; left; (try exact H3) | intros H3; inversion H3].
+simpl stepf.
+destruct m as [s d].
+case (Loc.eq s d).
+simpl StateDone; intros h1 h2.
+elim (in_move__in_srcdst (x1, x2) d1); auto; simpl fst; simpl snd; simpl;
+ intros; split; right; right; (try in_tac).
+simpl StateDone; intros h1 h2.
+elim (in_move__in_srcdst (x1, x2) d1); auto; simpl fst; simpl snd; simpl;
+ intros; split; right; right; (try in_tac).
+elim
+ (in_app_or
+ (StateToMove (stepf S1)) (StateBeing (stepf S1) ++ StateDone (stepf S1))
+ (x1, x2)); auto.
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0).
+unfold S1, StateToMove, StateBeing, StateDone.
+simpl app at 1.
+intros; elim (in_move__in_srcdst (x1, x2) t1);
+ (auto; simpl; intros; (split; right; right; (try in_tac))).
+intro; caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+intros Hsplit; unfold S1, StateToMove, StateBeing, StateDone; intro.
+elim (split_move_incl t1 t2 d2 d0 b2 Hsplit); auto.
+intros.
+assert (In (x1, x2) ((s, d) :: (t1 ++ t1))).
+generalize H0; simpl; intros.
+elim H3; [intros H5; left; (try exact H5) | intros H5; right].
+elim (in_app_or t2 d2 (x1, x2)); auto; intro; apply in_or_app; left.
+unfold incl in H1 |-.
+apply H1; auto.
+unfold incl in H2 |-; apply H2; auto.
+split; right.
+elim (in_move__in_srcdst (x1, x2) ((s, d) :: (t1 ++ t1)));
+ (auto; simpl; intros; (try in_tac)).
+elim H4; [intros H6; (try clear H4); (try exact H6) | intros H6; (try clear H4)].
+left; (try assumption).
+right; (try in_tac).
+rewrite getsrc_app in H6; (try in_tac).
+elim (in_move__in_srcdst (x1, x2) ((s, d) :: (t1 ++ t1)));
+ (auto; simpl; intros; (try in_tac)).
+elim H5; [intros H6; (try clear H5); (try exact H6) | intros H6; (try clear H5)].
+left; (try assumption).
+right; rewrite getdst_app in H6; (try in_tac).
+caseEq b1; intro.
+unfold S1, StateToMove, StateBeing, StateDone.
+intro; elim (in_move__in_srcdst (x1, x2) ((s, d) :: t1)); (auto; intros).
+simpl snd in H4 |-; simpl fst in H3 |-; split; right; (try in_tac).
+intros l heq; generalize (app_rewriter _ l m).
+intros [y [r H1]]; rewrite H1.
+destruct y as [y1 y2].
+rewrite last_app; simpl fst.
+case (Loc.eq d0 y1).
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) ((s, d) :: t1)); auto; intros.
+simpl snd in H4 |-; simpl fst in H3 |-; (split; right; (try in_tac)).
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) ((s, d) :: t1)); auto; intros.
+simpl snd in H4 |-; simpl fst in H3 |-; (split; right; (try in_tac)).
+intro; elim (in_app_or (StateBeing (stepf S1)) (StateDone (stepf S1)) (x1, x2));
+ auto.
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0).
+intros e; rewrite <- e; simpl StateBeing.
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) ((s, d) :: ((s0, s) :: b1))); auto;
+ simpl; intros.
+split; right; (try in_tac).
+elim H2; [intros H4; left; (try exact H4) | intros H4; (try clear H2)].
+elim H4; [intros H2; right; (try exact H2) | intros H2; (try clear H4)].
+assert (In x1 (s0 :: nil)); auto; (try in_tac).
+simpl; auto.
+right; (try in_tac).
+elim H3; [intros H4; left; (try exact H4) | intros H4; (try clear H3)].
+elim H4; [intros H3; right; (try exact H3) | intros H3; (try clear H4)].
+rewrite <- e; (try in_tac).
+assert (In x2 (s :: nil)); [simpl; auto | try in_tac].
+right; (try in_tac).
+intro; caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+simpl StateBeing.
+intros.
+generalize (in_split_move t1 t2 d2 d0 b2 H1).
+intros.
+split; right; elim H2; intros.
+rewrite H4 in H3; elim (in_move__in_srcdst (x1, x2) t1); auto; intros.
+simpl snd in H6 |-; simpl fst in H5 |-; (try in_tac).
+unfold S1, StateToMove, StateBeing, StateDone.
+simpl getsrc; (try in_tac).
+elim (in_move__in_srcdst (x1, x2) ((s0, d0) :: b1)); (auto; intros).
+simpl snd in H6 |-; simpl fst in H5 |-; (try in_tac).
+unfold S1, StateToMove, StateBeing, StateDone.
+simpl.
+simpl in H5 |-.
+elim H5; [intros H7; (try clear H5); (try exact H7) | intros H7; (try clear H5)].
+assert (In x1 (s0 :: nil)); simpl; auto.
+right; in_tac.
+right; in_tac.
+inversion H4.
+simpl.
+subst b2.
+rewrite H4 in H3.
+elim (in_move__in_srcdst (x1, x2) t1); (auto; intros).
+simpl snd in H7 |-.
+right; in_tac.
+unfold S1, StateToMove, StateBeing, StateDone.
+elim (in_move__in_srcdst (x1, x2) ((s0, d0) :: b1)); auto; intros.
+simpl snd in H6 |-; (try in_tac).
+apply
+ (in_or_app (getdst ((s, d) :: t1)) (getdst ((s0, d0) :: b1) ++ getdst d1) x2);
+ right; (try in_tac).
+caseEq b1.
+intros h1 h2; inversion h2.
+intros m l heq.
+generalize (app_rewriter _ l m); intros [y [r H2]]; rewrite H2.
+destruct y as [y1 y2].
+rewrite last_app; simpl fst.
+case (Loc.eq d0 y1).
+unfold S1, StateToMove, StateBeing, StateDone.
+generalize (last_replace r y1 y2).
+unfold Move; intros H3 H6.
+rewrite H3.
+intro.
+elim (in_app_or r ((T y1, y2) :: nil) (x1, x2)); auto.
+intro.
+rewrite heq; rewrite H2; (split; right).
+elim (in_move__in_srcdst (x1, x2) r); auto; simpl fst; simpl snd; intros;
+ (try in_tac).
+simpl.
+rewrite getsrc_app; (right; (try in_tac)).
+elim (in_move__in_srcdst (x1, x2) r); auto; simpl fst; simpl snd; intros;
+ (try in_tac).
+simpl.
+rewrite getdst_app; right; (try in_tac).
+intros h; inversion h; inversion H5.
+split; [left; simpl; auto | right].
+unfold T; case (Loc.type y1); auto.
+subst y2.
+rewrite heq; rewrite H2.
+simpl.
+rewrite getdst_app; simpl.
+assert (In x2 (x2 :: nil)); [simpl; auto | right; (try in_tac)].
+unfold S1, StateToMove, StateBeing, StateDone.
+intro; rewrite heq; rewrite H2; (split; right).
+intros; elim (in_move__in_srcdst (x1, x2) (r ++ ((y1, y2) :: nil))); auto;
+ intros.
+simpl snd in H5 |-; simpl fst in H4 |-.
+simpl.
+right; (try in_tac).
+apply in_or_app; right; simpl; right; (try in_tac).
+elim (in_move__in_srcdst (x1, x2) (r ++ ((y1, y2) :: nil))); auto; intros.
+simpl snd in H5 |-.
+simpl.
+right; (try in_tac).
+apply in_or_app; right; simpl; right; (try in_tac).
+simpl stepf.
+destruct m as [s d].
+destruct m0 as [s0 d0].
+case (Loc.eq s d0).
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) d1); auto; intros.
+simpl in H3 |-; simpl in H2 |-.
+split; right; (try in_tac).
+intro; caseEq (split_move t1 d0); intro.
+destruct p as [[t2 b2] d2].
+simpl StateDone.
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) d1); auto; intros.
+simpl in H3 |-; simpl in H4 |-.
+split; right; (try in_tac).
+caseEq b1.
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) ((s0, d0) :: d1)); auto; intros.
+simpl in H5 |-; simpl in H4 |-; split; right; (try in_tac).
+simpl.
+elim H4; [intros H6; right; (try exact H6) | intros H6; (try clear H4)].
+assert (In x1 (x1 :: nil)); [simpl; auto | rewrite H6; (try in_tac)].
+right; (try in_tac).
+elim H5; [intros H6; right; simpl; (try exact H6) | intros H6; (try clear H5)].
+assert (In x2 (x2 :: nil)); [simpl; auto | rewrite H6; (try in_tac)].
+try in_tac.
+intros m l heq.
+generalize (app_rewriter _ l m); intros [y [r H2]]; rewrite H2.
+destruct y as [y1 y2].
+rewrite last_app; simpl fst.
+case (Loc.eq d0 y1).
+unfold S1, StateToMove, StateBeing, StateDone.
+unfold S1, StateToMove, StateBeing, StateDone.
+intros.
+elim H3; intros.
+inversion H4.
+simpl; split; right; auto.
+right; apply in_or_app; right; simpl; auto.
+right; apply in_or_app; right; simpl; auto.
+elim H4; intros.
+inversion H5.
+simpl; split; [right | left].
+rewrite heq; rewrite H2; simpl.
+rewrite <- e; rewrite H7.
+rewrite getsrc_app; simpl.
+right; assert (In x1 (x1 :: nil)); [simpl; auto | try in_tac].
+unfold T; case (Loc.type x1); auto.
+elim (in_move__in_srcdst (x1, x2) d1); (auto; intros).
+simpl snd in H7 |-; simpl fst in H6 |-; split; right; (try in_tac).
+unfold S1, StateToMove, StateBeing, StateDone.
+intros; elim (in_move__in_srcdst (x1, x2) ((s0, d0) :: d1));
+ (auto; simpl; intros).
+split; right.
+elim H4; [intros H6; right; (try exact H6) | intros H6; (try clear H4)].
+apply in_or_app; right; simpl; auto.
+right; (try in_tac).
+elim H5; [intros H6; right; (try exact H6) | intros H6; (try clear H5)].
+apply in_or_app; right; simpl; auto.
+right; (try in_tac).
+Qed.
+
+Lemma getsrc_f: forall s l, In s (getsrc l) -> (exists d , In (s, d) l ).
+Proof.
+induction l; simpl getsrc.
+simpl; (intros h; elim h).
+intros; destruct a as [a1 a2].
+simpl in H |-.
+elim H; [intros H0; (try clear H); (try exact H0) | intros H0; (try clear H)].
+subst a1.
+exists a2; simpl; auto.
+simpl.
+elim IHl; [intros d H; (try clear IHl); (try exact H) | idtac]; auto.
+exists d; [right; (try assumption)].
+Qed.
+
+Lemma incl_src: forall l1 l2, incl l1 l2 -> incl (getsrc l1) (getsrc l2).
+Proof.
+intros.
+unfold incl in H |-.
+unfold incl.
+intros a H0; (try assumption).
+generalize (getsrc_f a).
+intros H1; elim H1 with ( l := l1 );
+ [intros d H2; (try clear H1); (try exact H2) | idtac]; auto.
+assert (In (a, d) l2).
+apply H; auto.
+elim (in_move__in_srcdst (a, d) l2); auto.
+Qed.
+
+Lemma getdst_f: forall d l, In d (getdst l) -> (exists s , In (s, d) l ).
+Proof.
+induction l; simpl getdst.
+simpl; (intros h; elim h).
+intros; destruct a as [a1 a2].
+simpl in H |-.
+elim H; [intros H0; (try clear H); (try exact H0) | intros H0; (try clear H)].
+subst a2.
+exists a1; simpl; auto.
+simpl.
+elim IHl; [intros s H; (try clear IHl); (try exact H) | idtac]; auto.
+exists s; [right; (try assumption)].
+Qed.
+
+Lemma incl_dst: forall l1 l2, incl l1 l2 -> incl (getdst l1) (getdst l2).
+Proof.
+intros.
+unfold incl in H |-.
+unfold incl.
+intros a H0; (try assumption).
+generalize (getdst_f a).
+intros H1; elim H1 with ( l := l1 );
+ [intros d H2; (try clear H1); (try exact H2) | idtac]; auto.
+assert (In (d, a) l2).
+apply H; auto.
+elim (in_move__in_srcdst (d, a) l2); auto.
+Qed.
+
+Lemma src_tmp2_res:
+ forall S1 x1 x2,
+ In
+ (x1, x2)
+ (StateToMove (Pmov S1) ++ (StateBeing (Pmov S1) ++ StateDone (Pmov S1))) ->
+ (In x1 temporaries2 \/
+ In x1 (getsrc (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)))) /\
+ (In x2 temporaries2 \/
+ In x2 (getdst (StateToMove S1 ++ (StateBeing S1 ++ StateDone S1)))).
+Proof.
+intros S1; elim S1 using (well_founded_ind (Wf_nat.well_founded_ltof _ mesure)).
+clear S1; intros S1 Hrec.
+destruct S1 as [[t b] d]; set (S1:=(t, b, d)).
+unfold S1; rewrite Pmov_equation; intros.
+destruct t.
+destruct b.
+apply srcdst_tmp2_stepf; auto.
+elim Hrec with ( y := stepf S1 ) ( x1 := x1 ) ( x2 := x2 );
+ [idtac | apply stepf1_dec; auto | auto].
+intros.
+elim H1; [intros H2; (try clear H1); (try exact H2) | intros H2; (try clear H1)].
+elim H0; [intros H1; (try clear H0); (try exact H1) | intros H1; (try clear H0)].
+split; [left; (try assumption) | idtac].
+left; (try assumption).
+elim (getsrc_f x1) with ( 1 := H1 ); intros x3 H3.
+split; auto.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+elim H0; [intros H1; (try clear H0); (try exact H1) | intros H1; (try clear H0)].
+elim (getdst_f x2) with ( 1 := H2 ); intros x3 H3.
+split; auto.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+elim (getsrc_f x1) with ( 1 := H1 ); intros x3 H3.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+clear H3.
+elim (getdst_f x2) with ( 1 := H2 ); intros x4 H3.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+elim Hrec with ( y := stepf S1 ) ( x1 := x1 ) ( x2 := x2 );
+ [idtac | apply stepf1_dec; auto | auto].
+intros.
+elim H1; [intros H2; (try clear H1); (try exact H2) | intros H2; (try clear H1)].
+elim H0; [intros H1; (try clear H0); (try exact H1) | intros H1; (try clear H0)].
+split; [left; (try assumption) | idtac].
+left; (try assumption).
+elim (getsrc_f x1) with ( 1 := H1 ); intros x3 H3.
+split; auto.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+elim H0; [intros H1; (try clear H0); (try exact H1) | intros H1; (try clear H0)].
+elim (getdst_f x2) with ( 1 := H2 ); intros x3 H3.
+split; auto.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+elim (getsrc_f x1) with ( 1 := H1 ); intros x3 H3.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+clear H3.
+elim (getdst_f x2) with ( 1 := H2 ); intros x4 H3.
+elim srcdst_tmp2_stepf with ( 1 := H3 ); auto.
+Qed.
+
+Lemma wt_add_moves:
+ forall p b,
+ List.map Loc.type (getsrc p) = List.map Loc.type (getdst p) ->
+ locs_read_ok (getsrc p) ->
+ locs_write_ok (getdst p) ->
+ wt_block tf b ->
+ wt_block
+ tf
+ (fold_left
+ (fun (k0 : LTL.block) =>
+ fun (p0 : loc * loc) => add_move (fst p0) (snd p0) k0) p b).
+Proof.
+induction p.
+intros; simpl; auto.
+intros; destruct a as [a1 a2]; simpl.
+apply IHp; auto.
+inversion H; auto.
+simpl in H0 |-.
+unfold locs_read_ok in H0 |-.
+simpl in H0 |-.
+unfold locs_read_ok; auto.
+generalize H1; unfold locs_write_ok; simpl; auto.
+apply wt_add_move; (try assumption).
+simpl in H0 |-.
+unfold locs_read_ok in H0 |-.
+apply H0.
+simpl; left; trivial.
+unfold locs_write_ok in H1 |-; apply H1.
+simpl; left; trivial.
+inversion H; auto.
+Qed.
+
+Lemma map_f_getsrc_getdst:
+ forall (b : Set) (f : Reg -> b) p,
+ map f (getsrc p) = map f (getdst p) ->
+ forall x1 x2, In (x1, x2) p -> f x1 = f x2.
+Proof.
+intros b f0 p; induction p; simpl; auto.
+intros; contradiction.
+destruct a.
+simpl.
+intros heq; injection heq.
+intros h1 h2.
+intros x1 x2 [H3|H3].
+injection H3.
+intros; subst; auto.
+apply IHp; auto.
+Qed.
+
+Lemma wt_parallel_move':
+ forall p b,
+ List.map Loc.type (getsrc p) = List.map Loc.type (getdst p) ->
+ locs_read_ok (getsrc p) ->
+ locs_write_ok (getdst p) -> wt_block tf b -> wt_block tf (p_move p b).
+Proof.
+unfold p_move.
+unfold P_move.
+intros; apply wt_add_moves; auto.
+rewrite getsrc_map; rewrite getdst_map.
+rewrite list_map_compose.
+rewrite list_map_compose.
+apply list_map_exten.
+generalize (move_types_res (p, nil, nil)); auto.
+destruct x as [x1 x2]; simpl; intros; auto.
+symmetry; apply H3.
+simpl.
+rewrite app_nil.
+apply map_f_getsrc_getdst; auto.
+in_tac.
+unfold locs_read_ok.
+intros l H3.
+elim getsrc_f with ( 1 := H3 ); intros x3 H4.
+elim (src_tmp2_res (p, nil, nil) l x3).
+simpl.
+rewrite app_nil.
+intros [[H'|[H'|H']]|H'] _.
+subst l; hnf; auto.
+subst l; hnf; auto.
+contradiction.
+apply H0; auto.
+in_tac.
+intros l H3.
+elim getdst_f with ( 1 := H3 ); intros x3 H4.
+elim (src_tmp2_res (p, nil, nil) x3 l).
+simpl.
+rewrite app_nil.
+intros _ [[H'|[H'|H']]|H'].
+subst l; hnf; auto.
+subst l; hnf; auto.
+contradiction.
+apply H1; auto.
+in_tac.
+Qed.
+
+Theorem wt_parallel_moveX:
+ forall srcs dsts b,
+ List.map Loc.type srcs = List.map Loc.type dsts ->
+ locs_read_ok srcs ->
+ locs_write_ok dsts -> wt_block tf b -> wt_block tf (parallel_move srcs dsts b).
+Proof.
+unfold parallel_move, parallel_move_order, P_move.
+intros.
+generalize (wt_parallel_move' (listsLoc2Moves srcs dsts)); intros H'.
+unfold p_move, P_move in H' |-.
+apply H'; auto.
+elim (getdst_lists2moves srcs dsts); auto.
+unfold Allocation.listsLoc2Moves, listsLoc2Moves.
+intros heq1 heq2; rewrite heq1; rewrite heq2; auto.
+repeat rewrite <- (list_length_map Loc.type).
+rewrite H; auto.
+elim (getdst_lists2moves srcs dsts); auto.
+unfold Allocation.listsLoc2Moves, listsLoc2Moves.
+intros heq1 heq2; rewrite heq1; auto.
+repeat rewrite <- (list_length_map Loc.type).
+rewrite H; auto.
+elim (getdst_lists2moves srcs dsts); auto.
+unfold Allocation.listsLoc2Moves, listsLoc2Moves.
+intros heq1 heq2; rewrite heq2; auto.
+repeat rewrite <- (list_length_map Loc.type).
+rewrite H; auto.
+Qed.
+
+End wt_move_correction.