(** ** 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 steps_state_good:
forall st1 st2, steps st1 st2 -> good_state st1 -> good_state st2.