Module SSAfastliveprecomputeRT


Require Import List. Import ListNotations.
Require Import Wellfounded.

Require Import Coqlib.
Require Import Maps.
Require Import Iteration.
Require Import Utils.

Require Import SSAfastliveutils.

Local Open Scope positive_scope.

The graph is presented as a finite map from nodes (of type positive) to the lists of their successors.

Definition node: Type := positive.

Definition graph: Type := PTree.t (list node).

Local Notation map := PTree.t (only parsing).
Local Notation update := PTree.set (only parsing).
Local Notation remove := PTree.remove (only parsing).
Local Notation filter := PTree.filter (only parsing).
Local Notation itv := (positive * positive)%type (only parsing).
Local Notation set := (PTree.t unit) (only parsing).
Local Notation empty := (PTree.empty _) (only parsing).
Local Notation is_empty := PTree.bempty (only parsing).
Local Notation add := (fun u => PTree.set u tt) (only parsing).
Local Notation merge := ZSortWithIndex.merge (only parsing).
Local Notation union := (PTree.combine_union_strict option_union) (only parsing).
Definition is_directly_included r u v :=
  match r ! u with
  | None => false
  | Some i =>
    match r ! v with
    | None => false
    | Some i' => test_is_included i' i
    end
  end.
Notation is_cross_included := can_reach (only parsing).

The traversal is presented as an iteration that modifies the following state.

Definition pre : Type := positive.
Definition post : Type := set * list (node * Z).
Record state : Type := mkstate {
  gr: graph;
  wrk: list (node * positive * list node * (set * list (node * Z)));
  next: positive;
  r : map itv;
  c : map set;
  t : map (list (node * Z));
  back : list (node * node)
}.

Definition init_state (g: graph) (root: node) :=
  match g!root with
  | Some succs =>
     {| gr := PTree.remove root g;
        wrk := (root, 1%positive, succs, (PTree.empty _, [])) :: nil;
        r := PTree.empty _;
        c := PTree.empty _;
        t := PTree.empty _;
        next := 2%positive;
        back := [] |}
  | None =>
     {| gr := g;
        wrk := nil;
        r := PTree.empty _;
        c := PTree.empty _;
        t := PTree.empty _;
        next := 1%positive;
        back := [] |}
  end.

Definition result : Type := map itv * map set * map (list (node * Z)) * list (node*node).
Definition transition (dom_pre : node -> Z) (s: state) : result + state :=
  match s.(wrk) with
  | [] => inl (s.(r), s.(c), s.(t), s.(back))
  | (u, n, [], (s_c, s_t)) :: wrk' =>
      let r' := update u (n, Pos.pred s.(next)) s.(r) in
      let s_c' := filter (fun v _ => negb (is_directly_included r' u v)) s_c in
      let s_c'' := add u s_c' in
      let c' := update u s_c'' s.(c) in
      let s_t' := List.filter (fun '(v, _) => negb (is_cross_included r' c' u v)) s_t in
      let t' := update u s_t' s.(t) in
      inr {| gr := s.(gr); wrk := wrk'; next := s.(next); r := r'; c := c'; t := t'; back := s.(back) |}
  | (u, n, v :: succs_u, (s_c, s_t)) :: wrk' =>
      match s.(gr) ! v with
      | None =>
          match s.(r) ! v with
          | None =>
            let s_t' := merge [(v, dom_pre v)] s_t in
            let back' := (u, v) :: s.(back) in
            inr {| gr := s.(gr);
                   wrk := (u, n, succs_u, (s_c, s_t')) :: wrk';
                   next := s.(next);
                   r := s.(r); c := s.(c); t := s.(t); back := back' |}
          | Some (m, _) =>
            let s_c' := match s.(c) ! v with | None => s_c | Some s => union s s_c end in
            let s_t' := match s.(t) ! v with | None => s_t | Some s => merge s s_t end in
            inr {| gr := s.(gr);
                   wrk := (u, n, succs_u, (s_c', s_t')) :: wrk';
                   next := s.(next);
                   r := s.(r); c := s.(c); t := s.(t); back := s.(back) |}
           end
      | Some succs_v =>
          inr {| gr := remove v s.(gr);
                 wrk := (v, s.(next), succs_v, (empty, [])) :: s.(wrk);
                 next := Pos.succ s.(next);
                 r := s.(r); c := s.(c); t := s.(t); back := s.(back) |}
      end
  end.

Section POSTORDER.

Termination criterion.

Fixpoint size_worklist (w: list (positive * pre * list positive * post)) : nat :=
  match w with
  | nil => 0%nat
  | (x, _, succs, _) :: w' => (S (List.length succs) + size_worklist w')%nat
  end.

Definition lt_state (s1 s2: state) : Prop :=
  lex_ord lt lt (PTree_Properties.cardinal s1.(gr), size_worklist s1.(wrk))
                (PTree_Properties.cardinal s2.(gr), size_worklist s2.(wrk)).

Lemma lt_state_wf: well_founded lt_state.
Proof.
  set (f := fun s => (PTree_Properties.cardinal s.(gr), size_worklist s.(wrk))).
  change (well_founded (fun s1 s2 => lex_ord lt lt (f s1) (f s2))).
  apply wf_inverse_image.
  apply wf_lex_ord.
  apply lt_wf. apply lt_wf.
Qed.

Lemma transition_decreases :
  forall itvm s s', transition itvm s = inr _ s' -> lt_state s' s.
Proof.
  unfold transition, lt_state; intros.
  destruct (wrk s) as [ | [[[u n] succs] [s_c s_t]] l].
  discriminate.
  destruct succs as [ | y succs ].
  inv H. simpl. apply lex_ord_right. omega.
  destruct ((gr s)!y) as [succs'|] eqn:?.
  inv H. simpl. apply lex_ord_left. eapply PTree_Properties.cardinal_remove; eauto.
  destruct ((r s)!y) as [(m, _)|].
  destruct (m<?n)%positive.
  inv H. simpl. apply lex_ord_right. omega.
  inv H. simpl. apply lex_ord_right. omega.
  inv H. simpl. apply lex_ord_right. omega.
Qed.

End POSTORDER.

Definition precompute_r_t_up (g: graph) (root: node) (dom_pre : node -> Z) : result :=
  WfIter.iterate _ _ (transition dom_pre) lt_state lt_state_wf (transition_decreases dom_pre) (init_state g root).