(** ** Correctness invariant *)
(** The following invariant is preserved at each iteration of Kildall's algorithm: for all visited program point [n], either [n] is in the worklist, or the inequations associated with [n] ([aval[s] >= transf n aval[n]] for all successors [s] of [n]) hold.  In other terms, the worklist contains all nodes that were visited but do not yet satisfy their inequations.  The second part of the invariant shows that nodes that already have an abstract value associated with them have been visited. *)
Record good_state (st: state) : Prop := {
gs_stable: forall n,
st.(visited) n ->
NS.In n st.(worklist) \/
(forall i s,
code!n = Some i -> In s (successors i) ->
optge st.(aval)!s (Some (transf n (abstr_value n st))));
gs_defined: forall n v,
st.(aval)!n = Some v -> st.(visited) n
}.
(** We show that the [step] function preserves this invariant. *)

(* Specifications: *)
Lemma step_state_good:
forall st pc rem instr,
NS.pick st.(worklist) = Some (pc, rem) ->
code!pc = Some instr ->
good_state st ->
good_state (propagate_succ_list (mkstate st.(aval) rem st.(visited))
(transf pc (abstr_value pc st))
(successors instr)).
Lemma step_state_good_2:
forall st pc rem,
good_state st ->
NS.pick (worklist st) = Some (pc, rem) ->
code!pc = None ->
good_state (mkstate st.(aval) rem st.(visited)).
Lemma steps_state_good:
forall st1 st2, steps st1 st2 -> good_state st1 -> good_state st2.