Lvc.Spilling.SpillUtil

Require Import List Map CSet Env AllInRel Exp AppExpFree.
Require Import IL Annotation AutoIndTac Liveness.Liveness LabelsDefined.

Notation "'spilling'"
  := (ann (var × var × list (var × var))).

Notation "'getSp' sl" := (fst (fst (getAnn sl))) (at level 40).
Notation "'getL' sl" := (snd (fst (getAnn sl))) (at level 40).

Notation "'getRm' sl" := (snd (getAnn sl)) (at level 40, only parsing).

SpillUtil


Lemma setTopAnn_setTopAnn
      (X : Type)
      (x x' : X)
      (a : ann X)
  :
    setTopAnn (setTopAnn a x') x = setTopAnn a x.
Proof.
  induction a; simpl; eauto.
Qed.

Lemma tl_list_incl
      (X : Type) `{OrderedType X}
      (L : list X)
  :
    of_list (tl L) of_list L
.
Proof.
  general induction L; simpl; eauto with cset.
Qed.

Lemma tl_set_incl
      (X : Type) `{OrderedType X}
      (s : set X)
  :
    of_list (tl (elements s)) s
.
Proof.
  rewrite tl_list_incl.
  hnf. intros. eapply elements_iff. cset_tac.
Qed.

Definition sub_spill
           (sl' sl : spilling)
  :=
    sl' = setTopAnn sl (getAnn sl')
     fst (fst (getAnn sl')) fst (fst (getAnn sl))
     snd (fst (getAnn sl')) snd (fst (getAnn sl))
     snd (getAnn sl') = snd (getAnn sl)
.

Function count
         (sl : spilling)
  := cardinal (fst (fst (getAnn sl))) + cardinal (snd (fst (getAnn sl))).

Lemma count_reduce_L
      (sl : spilling)
      (n m : nat)
  :
    count sl = S n
     cardinal (snd (fst (getAnn sl))) = S m
     count (setTopAnn sl (fst (fst (getAnn sl)),
                           of_list (tl (elements (snd (fst (getAnn sl))))),
                           snd (getAnn sl)))
      = n
.
Proof.
  intros count_sl card_L.
  unfold count in ×.
  rewrite getAnn_setTopAnn.
  simpl.
  rewrite cardinal_set_tl with (n:=m).
  - omega.
  - rewrite of_list_elements. assumption.
Qed.


Lemma count_reduce_Sp
      (sl : spilling)
      (n m : nat)
  :
    count sl = S n
     cardinal (fst (fst (getAnn sl))) = S m
     count (setTopAnn sl (of_list (tl (elements (fst (fst (getAnn sl))))),
                           snd (fst (getAnn sl)),
                           snd (getAnn sl)))
      = n
.
Proof.
  intros count_sl card_Sp.
  unfold count in ×.
  rewrite getAnn_setTopAnn.
  simpl.
  rewrite cardinal_set_tl with (n:=m).
  - omega.
  - rewrite of_list_elements. assumption.
Qed.

Lemma get_get_eq
      (X : Type)
      (L : list X)
      (n : nat)
      (x x' : X)
  :
    get L n x get L n x' x = x'
.
Proof.
  intros get_x get_x'.
  induction get_x; inversion get_x'.
  - reflexivity.
  - apply IHget_x. assumption.
Qed.

Lemma sub_spill_refl sl
  :
    sub_spill sl sl
.
Proof.
  unfold sub_spill.
  repeat split.
    simpl; eauto.
  - unfold setTopAnn.
    destruct sl; destruct a; destruct p;
      simpl; reflexivity.
  - reflexivity.
  - reflexivity.
Qed.


Lemma of_list_tl_hd
      (L : list var)
  :
    L nil
     of_list L [=] of_list (tl L) singleton (hd default_var L)
.
Proof.
  intro N.
  induction L; simpl; eauto.
  - isabsurd.
  - cset_tac.
Qed.

Lemma tl_hd_set_incl
      (s t : var)
  :
    s \ of_list (tl (elements t)) s \ t singleton (hd default_var (elements t))
.
Proof.
  hnf.
  intros a H.
  apply diff_iff in H.
  destruct H as [in_s not_in_tl_t].
  apply union_iff.
  decide (a t).
  - right.
    rewrite <- of_list_elements in i.
    rewrite of_list_tl_hd in i.
    + apply union_iff in i.
      destruct i.
      × contradiction.
      × eauto.
    + intro N.
      apply elements_nil_eset in N.
      rewrite of_list_elements in i.
      rewrite N in i.
      isabsurd.
  - left.
    cset_tac.
Qed.

Lemma nth_zip
      (X Y Z : Type)
      (L : list X)
      (L': list Y)
      (x : X)
      (x' : Y)
      (d : Z)
      (f : X Y Z)
      n
  :
    get L n x
     get L' n x'
     nth n (f L L') d = f x x'
.
Proof.
  intros get_x get_x'.
  general induction n;
    simpl; eauto; isabsurd;
      inv get_x;
      inv get_x'.
  - simpl. apply IHn; eauto.
Qed.

Lemma injective_ann
      (X : Type)
      (a b : ann X)
  :
    a = b
     match a,b with
      | ann0 an, ann0 bnan = bn
      | ann1 an a', ann1 bn b'an = bn a' = b'
      | ann2 an a1 a2, ann2 bn b1 b2an = bn a1 = b1 a2 = b2
      | annF an aF a', annF bn bF b'an = bn aF = bF a' = b'
      | _,_True
      end
.
Proof.
  revert b;
    induction a;
    intros b eq_ab;
    induction b;
    eauto;
    try split;
    inversion eq_ab;
    eauto.
Qed.

Lemma count_zero_Empty_Sp
      (sl : spilling)
  :
    count sl = 0
     Empty (getSp sl)
.
Proof.
  intro count_zero.
  apply cardinal_Empty.
  unfold count in count_zero.
  omega.
Qed.

Lemma count_zero_cardinal_Sp
      (sl : spilling)
  :
    count sl = 0
     cardinal (getSp sl) = 0
.
Proof.
  intro count_zero.
  unfold count in count_zero.
  omega.
Qed.

Lemma count_zero_cardinal_L
      (sl : spilling)
  :
    count sl = 0
     cardinal (getL sl) = 0
.
Proof.
  intro count_zero.
  unfold count in count_zero.
  omega.
Qed.

Lemma count_zero_Empty_L
      (sl : spilling)
  :
    count sl = 0
     Empty (getL sl)
.
Proof.
  intro count_zero.
  apply cardinal_Empty.
  unfold count in count_zero.
  omega.
Qed.

Lemma Empty_Sp_L_count_zero
      (sl : spilling)
  :
    Empty (getSp sl)
     Empty (getL sl)
     count sl = 0
.
Proof.
  intros Empty_Sp Empty_L.
  apply cardinal_Empty in Empty_Sp.
  apply cardinal_Empty in Empty_L.
  unfold count.
  omega.
Qed.

Definition clear_L
           (sl : spilling)
  :=
    setTopAnn sl (getSp sl, , getRm sl)
.

Lemma count_clearL
      (sl : spilling)
  :
    count (clear_L sl) = cardinal (getSp sl)
.
Proof.
  unfold count.
  unfold clear_L.
  rewrite getAnn_setTopAnn.
  simpl.
  rewrite empty_cardinal.
  omega.
Qed.

Definition merge (RM : set var × set var) :=
  fst RM snd RM.

Lemma getAnn_als_EQ_merge_rms
      (Lv : var)
      (als : ann var)
      (Λ : var × var)
      (pir2 : PIR2 Equal (merge Λ) Lv)
      (rms : var × var)
      (H23 : PIR2 Equal (merge rms) (getAnn als))
  :
    PIR2 Equal (merge (rms ++ Λ)) (getAnn als ++ Lv)
.
Proof.
  rewrite List.map_app. apply PIR2_app; eauto.
Qed.

Definition clear_SpL
           (sl : spilling)
  :=
    setTopAnn sl (,,snd (getAnn sl))
.

Definition reduce_Sp
           (sl : spilling)
  :=
    setTopAnn sl (of_list (tl (elements (getSp sl))), getL sl, snd (getAnn sl))
.

Definition reduce_L
           (sl : spilling)
  :=
    setTopAnn sl (getSp sl, of_list (tl (elements (getL sl))), snd (getAnn sl))
.

Lemma count_clear_zero
      (sl : spilling)
  :
    count (clear_SpL sl) = 0
.
Proof.
  unfold count.
  unfold clear_SpL.
  rewrite getAnn_setTopAnn.
  simpl.
  apply empty_cardinal.
Qed.

Definition clear_Sp
           (sl : spilling)
  :=
    setTopAnn sl (,getL sl,getRm sl)
.

Lemma count_clearSp
      (sl : spilling)
  :
    count (clear_Sp sl) = cardinal (getL sl)
.
Proof.
  unfold count.
  unfold clear_Sp.
  rewrite getAnn_setTopAnn.
  simpl.
  rewrite empty_cardinal.
  reflexivity.
Qed.

Lemma getSp_clearSp
      (sl : spilling)
  :
    getSp clear_Sp sl =
.
Proof.
  unfold clear_Sp.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma getL_clearSp
      (sl : spilling)
  :
    getL clear_Sp sl = getL sl
.
Proof.
  unfold clear_Sp.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma getSp_clear
      (sl : spilling)
  :
    getSp clear_SpL sl =
.
Proof.
  unfold clear_SpL.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma getL_clear
      (sl : spilling)
  :
    getL clear_SpL sl =
.
Proof.
  unfold clear_SpL.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma getRm_clear
      (sl : spilling)
  :
    getRm clear_SpL sl = getRm sl
.
Proof.
  unfold clear_SpL.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma getRm_clearSp
      (sl : spilling)
  :
    getRm clear_Sp sl = getRm sl
.
Proof.
  unfold clear_Sp.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Definition setSp
           (sl : spilling)
           (Sp : var)
  : spilling
  :=
    setTopAnn sl (Sp,getL sl,getRm sl)
.

Lemma clear_clearSp
      (sl : spilling)
  :
    clear_SpL (clear_Sp sl) = clear_SpL sl
.
Proof.
  unfold clear_SpL.
  unfold clear_Sp.
  rewrite setTopAnn_setTopAnn.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma clearSp_clearSp
      (sl : spilling)
  :
    clear_Sp (clear_Sp sl) = clear_Sp sl
.
Proof.
  unfold clear_Sp.
  rewrite getAnn_setTopAnn.
  rewrite setTopAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.

Lemma setSp_getSp
      (sl : spilling)
  :
    setSp sl (getSp sl) = sl
.
Proof.
  unfold setSp.
  unfold setTopAnn.
  destruct sl;
    destruct a;
    destruct p;
    simpl;
    reflexivity.
Qed.

Lemma getSp_setSp
      (sl : spilling)
      (Sp : var)
  :
    getSp (setSp sl Sp) = Sp
.
Proof.
  unfold setSp.
  rewrite getAnn_setTopAnn.
  simpl.
  reflexivity.
Qed.