Lvc.ConstantPropagationAnalysis

Require Import CSet Le.

Require Import Plus Util AllInRel CSet.
Require Import Val Var Env EnvTy IL Annotation Lattice DecSolve Analysis Filter Lattice.

Require Import CMap.

Set Implicit Arguments.

Open Scope map_scope.

Definition Dom := Map [var, withTop val].

Definition join (v : option (withTop val)) : option (withTop val) :=
  match v, with
    | Some (wTA v), Some (wTA ) ⇒ if [v = ] then Some (wTA v) else Some Top
    | Some (Top), _Some Top
    | _, Some TopSome Top
    | Some (wTA v), NoneSome (wTA v)
    | None, Some (wTA v) ⇒ Some (wTA v)
    | None, NoneNone
  end.

Definition joinDom (d :Dom) : Dom := map2 join d .

Definition domain {X} `{OrderedType X} {Y} (d:Map [X, Y])
: set X := of_list (List.map fst (elements d)).


Inductive le : option (withTop val) → option (withTop val) → Prop :=
  | leTop v : le (Some (wTA v)) (Some Top)
  | leBot w : le None (Some w)
  | leRefl v : le v v.

Instance le_dec x y : Computable (le x y).
Defined.

Lemma not_le_irreflexive x y
: ¬le x yx y.

Instance le_find_dec d x : Computable ((fun x0 : varle (find x0 d) (find x0 )) x).

Definition leDom (d : Dom) : Prop :=
 ( x, x domain d domain le (find x d) (find x )).

Lemma leDom_irreflexive x y
: ¬leDom x y¬Equal x y.

Definition set_quant_dec X `{OrderedType X} s P `{Proper _ (_eq ==> iff) P} `{ x, Computable (P x) } : bool :=
  SetInterface.fold (fun x bif [P x] then b else false) s true.


Instance set_quant_computable X `{OrderedType X} s P `{Proper _ (_eq ==> iff) P}
         `{ x, Computable (P x) } :
  Computable ( x, x sP x).


Instance leDom_dec
  : d : Dom, Computable (leDom d ).

Instance Equal_computable (s t:Map [var, withTop val])
: Computable (Equal s t).
Defined.

Lemma not_domain_find {X} `{OrderedType X} {Y} (d:Map [X, Y]) x
: x domain dfind x d = None.
  Lemma findA_get A B (L:list (A × B)) f v
  : findA f L = Some v
    → x n, get L n x snd x = v f (fst x).
  Transparent compare. Qed.

Lemma InA_map X Y (R:XXProp) (:YYProp) `{Reflexive _ } (f:YX) L x
: InA R x (List.map f L)
  → y, InA y L R x (f y).

Lemma domain_find {X} `{OrderedType X} {Y} (d:Map [X, Y]) x
: x domain d v, find x d = Some v.

Lemma lt_join x y
: le y x
  → le
  → le (join y ) (join x ).

Lemma join_bot_right (y:Dom) x0
  : join (find x0 y) ⎣⎦ = find x0 y.

Lemma join_bot_left (y:Dom) x0
  : join ⎣⎦ (find x0 y) = find x0 y.

Lemma leDom_join x y
: leDom y x
  → leDom
  → leDom (joinDom y ) (joinDom x ).

Set Implicit Arguments.

Instance Dom_semilattice_ltDom : PartialOrder Dom := {
  poLe := leDom;
  poLe_dec := leDom_dec;
  poEq := Equal;
  poEq_dec := _
}.

Instance set_var_semilattice : BoundedSemiLattice Dom := {
  bottom := (@empty var _ _ (withTop val));
  join := joinDom
}.
Qed.

  Fixpoint list_update_at {X} (L:list X) (n:nat) (v:X) :=
    match L, n with
      | x::L, 0 ⇒ v::L
      | x::L, S nx::list_update_at L n v
      | _, _nil
    end.

  Lemma list_update_at_length X (l:list X) off v
  : length (list_update_at l off v) = length l.

  Lemma list_update_at_get_1 X (l:list X) off v n
  : get (list_update_at l off ) n v
    → n off
    → get l n v.

  Lemma list_update_at_get_2 X (l:list X) off v n
  : get (list_update_at l off ) n v
    → n = off
    → v = .

  Fixpoint update_with_list X `{OrderedType X} Y XL YL (m:Map [X, Y]) :=
    match XL, YL with
      | x::XL, y::YL(update_with_list XL YL m)[x <- y]
      | _, _m
    end.

Local Notation "f [ w <-- x ]" := (update_with_list w x f) (at level 29, left associativity).

Definition domupd (d:Dom) x (o:option val) : Dom :=
  match o with
    | Some xv ⇒ (d [x <- wTA xv])
    | None ⇒ (d [x <- Top])
  end.

Definition domenv (d:Dom) (x:var) : option val :=
  match find x d with
    | Some (wTA v) ⇒ Some v
    | _None
  end.

Definition constant_propagation_transform st (a:list (Dom × params)×Dom) :=
  match st, a with
    | stmtLet x e s as st, (AL, d)
      let := d in
      let d´´ := domupd x (exp_eval (domenv ) e) in
      (AL, anni1 d´´)
    | stmtIf e s t as st, (AL, d)
      let ai :=
          if [exp_eval (domenv d) e = Some val_true] then
              match e with
                | BinOp 3 (Var x) (Con c) ⇒ anni2opt (Some (d[x <- wTA c])) None
                | _anni2opt (Some d) None
              end
          else if [exp_eval (domenv d) e = Some val_false] then
            match e with
              | Var xanni2opt None (Some (d[x <- wTA 0]))

              | _anni2opt None (Some d)
            end
          else
            anni2opt (Some d) (Some d)
      in
      (AL, ai)
    | stmtApp f Y as st, (AL, d)
      let df := nth (counted f) AL (bottom, nil) in
      let Yc := List.map (fun ematch exp_eval (domenv d) e with
                        | Some vwTA v
                        | NoneTop
                        end ) Y in
      
      let := (d [snd df <-- Yc]) in
      (list_update_at AL (counted f) (joinDom (fst df) , snd df), anni1 )
    | stmtReturn e as st, (AL, d)
      (AL, anni1 d)
    | stmtExtern x f Y s as st, (AL, d)
      
      (AL, anni1 d)
    | stmtFun Z s t as st, (AL, d)
      
      (AL, anni2 d d)
  end.

Instance list_equal_computable X `{@EqDec X eq _}
: (L :list X), Computable (eq L ).

Instance Dom_params_semilattice : PartialOrder (Dom × params) := {
  poLe p := poLe (fst p) (fst ) snd p = snd ;
  poLe_dec := _;
  poEq p := poEq (fst p) (fst ) snd p = snd ;
  poEq_dec := _
}.
Defined.

Definition constant_propagation_analysis :=
  SSA.makeForwardAnalysis _ Dom_params_semilattice constant_propagation_transform (fun Z an(an, Z)) fst.