(** ** 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. *)

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)).