(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
(** Solvers for dataflow inequations. *)
(* To avoid useless definitions of inductors in extracted code. *)
Local Unset Elimination Schemes.
Local Unset Case Analysis Schemes.
(** A forward dataflow problem is a set of inequations of the form - [X(s) >= transf n X(n)] if program point [s] is a successor of program point [n] - [X(n) >= a] if [n] is an entry point and [a] its minimal approximation.  The unknowns are the [X(n)], indexed by program points (e.g. nodes in the CFG graph of a RTL function).  They range over a given ordered set that represents static approximations of the program state at each point. The [transf] function is the abstract transfer function: it computes an approximation [transf n X(n)] of the program state after executing instruction at point [n], as a function of the approximation [X(n)] of the program state before executing that instruction.  Symmetrically, a backward dataflow problem is a set of inequations of the form - [X(n) >= transf s X(s)] if program point [s] is a successor of program point [n] - [X(n) >= a] if [n] is an entry point and [a] its minimal approximation.  The only difference with a forward dataflow problem is that the transfer function [transf] now computes the approximation before a program point [s] from the approximation [X(s)] after point [s].  This file defines three solvers for dataflow problems.  The first two solve (optimally) forward and backward problems using Kildall's worklist algorithm.  They assume that the unknowns range over a semi-lattice, that is, an ordered type equipped with a least upper bound operation.  The last solver corresponds to propagation over extended basic blocks: it returns approximate solutions of forward problems where the unknowns range over any ordered type having a greatest element [top].  It simply sets [X(n) = top] for all merge points [n], that is, program points having several predecessors.  This solver is useful when least upper bounds of approximations do not exist or are too expensive to compute. *)
(** * Solving forward dataflow problems using Kildall's algorithm *)
(** A forward dataflow solver has the following generic interface. Unknowns range over the type [L.t], which is equipped with semi-lattice operations (see file [Lattice]).  *)
Module Type DATAFLOW_SOLVER.
Declare Module L: SEMILATTICE.
(** [fixpoint successors transf ep ev] is the solver. It returns either an error or a mapping from program points to values of type [L.t] representing the solution.  [successors] is a finite map returning the list of successors of the given program point. [transf] is the transfer function, [ep] the entry point, and [ev] the minimal abstract value for [ep]. *)
Parameter fixpoint:
forall {A: Type} (code: PTree.t A) (successors: A -> list positive)
(transf: positive -> L.t -> L.t)
(ep: positive) (ev: L.t),
option (PMap.t L.t).
(** The [fixpoint_solution] theorem shows that the returned solution, if any, satisfies the dataflow inequations. *)

Axiom fixpoint_solution:
forall A (code: PTree.t A) successors transf ep ev res n instr s,
fixpoint code successors transf ep ev = Some res ->
code!n = Some instr -> In s (successors instr) ->
(forall n, L.eq (transf n L.bot) L.bot) ->
L.ge res!!s (transf n res!!n).