Module ISF := FSetFacts.Facts(IS).Module ISP := FSetProperties.Properties(IS).Definition ref_fundef (fd: fundef) (id: ident) : Prop :=
  match fd with Internal f => ref_function f id | External ef => False end.Definition ref_init (il: list init_data) (id: ident) : Prop :=
  exists ofs, In (Init_addrof id ofs) il.Definition ref_def (gd: globdef fundef unit) (id: ident) : Prop :=
  match gd with
  | Gfun fd => ref_fundef fd id
  | Gvar gv => ref_init gv.(gvar_init) id
  end.Definition match_prog (p tp: program) : Prop :=
  exists u: IS.t, valid_used_set p u /\ match_prog_1 u p tp.(** * Properties of the static analysis *)

(** Monotonic evolution of the workset. *)

Inductive workset_incl (w1 w2: workset) : Prop :=
  workset_incl_intro:
    forall (SEEN: IS.Subset w1.(w_seen) w2.(w_seen))
           (TODO: List.incl w1.(w_todo) w2.(w_todo))
           (TRACK: forall id, IS.In id w2.(w_seen) ->
                      IS.In id w1.(w_seen) \/ List.In id w2.(w_todo)),
    workset_incl w1 w2.(** * Properties of the static analysis *)

(** Monotonic evolution of the workset. *)

Inductive workset_incl (w1 w2: workset) : Prop :=
  workset_incl_intro:
    forall (SEEN: IS.Subset w1.(w_seen) w2.(w_seen))
           (TODO: List.incl w1.(w_todo) w2.(w_todo))
           (TRACK: forall id, IS.In id w2.(w_seen) ->
                      IS.In id w1.(w_seen) \/ List.In id w2.(w_todo)),
    workset_incl w1 w2.

(* Specifications: *)
Lemma seen_workset_incl: forall w1 w2 id, workset_incl w1 w2 -> IS.In id w1 -> IS.In id w2.
Lemma workset_incl_refl: forall w, workset_incl w w.
Lemma workset_incl_trans: forall w1 w2 w3, workset_incl w1 w2 -> workset_incl w2 w3 -> workset_incl w1 w3.
Lemma add_workset_incl: forall id w, workset_incl w (add_workset id w).
Lemma addlist_workset_incl: forall l w, workset_incl w (addlist_workset l w).
Lemma add_ref_function_incl: forall f w, workset_incl w (add_ref_function f w).
Lemma add_ref_globvar_incl: forall gv w, workset_incl w (add_ref_globvar gv w).
Lemma add_ref_definition_incl: forall pm id w, workset_incl w (add_ref_definition pm id w).
Lemma initial_workset_incl: forall p, workset_incl {| w_seen := IS.empty; w_todo := nil |} (initial_workset p).
Lemma seen_add_workset: forall id (w: workset), IS.In id (add_workset id w).
Lemma seen_addlist_workset: forall id l (w: workset), In id l -> IS.In id (addlist_workset l w).
Lemma seen_add_ref_function: forall id f w, ref_function f id -> IS.In id (add_ref_function f w).
Lemma seen_main_initial_workset: forall p, IS.In p.(prog_main) (initial_workset p).
Lemma seen_public_initial_workset: forall p id, In id p.(prog_public) -> IS.In id (initial_workset p).
Lemma iter_step_invariant: forall w, workset_invariant w -> match iter_step pm w with | inl u => used_set_closed u | inr w' => workset_invariant w' end.
Theorem used_globals_sound: forall u, used_globals p pm = Some u -> used_set_closed u.
Theorem used_globals_incl: forall u, used_globals p pm = Some u -> IS.Subset (initial_workset p) u.