Section Exit_points.
(** Assuming that the nodes of the CFG [code] are numbered in reverse postorder (cf. pass [Renumber]), an edge from [n] to [s] is a normal edge if [s < n] and a back-edge otherwise. [sequential_node] returns [true] if the given node has at least one normal outgoing edge.  It returns [false] if the given node is an exit node (no outgoing edges) or the final node of a loop body (all outgoing edges are back-edges).  As we prove later, the set of all non-sequential node is an appropriate set of entry points for exploring the reverse CFG. *)
Definition sequential_node (pc: positive) (instr: A): bool :=
existsb (fun s => match code!s with None => false | Some _ => plt s pc end)
(successors instr).
Definition exit_points : NS.t :=
PTree.fold
(fun ep pc instr =>
if sequential_node pc instr
then ep
else NS.add pc ep)
code NS.empty.
(** The crucial property of exit points is that any nonempty node in the CFG is reverse-reachable from an exit point. *)

Lemma reachable_exit_points_predecessor:
forall pc i,
code!pc = Some i ->
exists x, NS.In x exit_points /\ reachable (make_predecessors code successors) (fun l => l) x pc.