(** ** Correctness invariant *)
(** The invariant over the state is as follows: - Points with several predecessors are mapped to [L.top] - Points not in the worklist satisfy their inequations (as in Kildall's algorithm). *)
Definition state_invariant (st: state) : Prop :=
(forall n, basic_block_map n = true -> st.(aval)!!n = L.top)
/\
(forall n,
In n st.(worklist) \/
(forall instr s, code!n = Some instr -> In s (successors instr) ->
L.ge st.(aval)!!s (transf n st.(aval)!!n))).

(* Specifications: *)
Lemma propagate_successors_charact1:
forall bb succs l st,
incl st.(worklist)
(propagate_successors bb succs l st).(worklist).
Lemma propagate_successors_charact2:
forall bb succs l st n,
let st' := propagate_successors bb succs l st in
(In n succs -> bb n = false -> In n st'.(worklist) /\ st'.(aval)!!n = l)
/\ (~In n succs \/ bb n = true -> st'.(aval)!!n = st.(aval)!!n).
Lemma propagate_successors_invariant:
forall pc instr res rem,
code!pc = Some instr ->
state_invariant (mkstate res (pc :: rem)) ->
state_invariant
(propagate_successors basic_block_map (successors instr)
(transf pc res!!pc)
(mkstate res rem)).
Lemma propagate_successors_invariant_2:
forall pc res rem,
code!pc = None ->
state_invariant (mkstate res (pc :: rem)) ->
state_invariant (mkstate res rem).
Lemma initial_state_invariant:
state_invariant (mkstate (PMap.init L.top) (basic_block_list basic_block_map)).
Lemma analyze_invariant:
forall res,
fixpoint = Some res ->
state_invariant (mkstate res nil).