Module Analysis_and_optimization.Monotone_framework

The common elements of a monotone framework

val print_mfp : ('a -> Core__.Import.string) -> (int, ('a, 'b) Core__Set.t Monotone_framework_sigs.entry_exit) Core.Map.Poly.t -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> unit

Debugging tool to print out MFP sets *

val free_vars_expr : Middle.Expr.Typed.t -> string Core.Set.Poly.t

Calculate the free (non-bound) variables in an expression

val free_vars_idx : Middle.Expr.Typed.t Middle.Index.t -> string Core.Set.Poly.t

Calculate the free (non-bound) variables in an index

val free_vars_fnapp : Middle.Expr.Typed.t Middle.Fun_kind.t -> Middle.Expr.Typed.t Base__List.t -> string Core.Set.Poly.t
val free_vars_lval : Middle.Expr.Typed.t Middle.Stmt.Fixed.Pattern.lvalue -> string Core.Set.Poly.t
val free_vars_stmt : (Middle.Expr.Typed.t, Middle.Stmt.Located.t) Middle.Stmt.Fixed.Pattern.t -> string Core.Set.Poly.t

Calculate the free (non-bound) variables in a statement

val top_free_vars_stmt : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (Middle.Expr.Typed.t, int) Middle.Stmt.Fixed.Pattern.t -> string Core.Set.Poly.t

A variation on free_vars_stmt, where we do not recursively count free variables in sub statements

val inverse_flowgraph_of_stmt : ?flatten_loops:bool -> ?blocks_after_body:bool -> Middle.Stmt.Located.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) * (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t

Compute the inverse flowgraph of a Stan statement (for reverse analyses)

val reverse : (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l) -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l0)

Reverse flowgraphs to be used for reverse analyses. Observe that this respects the invariants listed for a FLOWGRAPH

val make_circular_flowgraph : (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l) -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l0) -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l1)

Modify the end nodes of a flowgraph to depend on its inits To force the monotone framework to run until the program never changes this function modifies the input Flowgraph so that it's end nodes depend on it's initial nodes. The inits of the reverse flowgraph are used for this since we normally have both the forward and reverse flowgraphs available.

  • parameter l

    Type of the label for each flowgraph, most commonly an int

  • parameter Flowgraph

    The flowgraph to modify

  • parameter RevFlowgraph

    The same flowgraph as Flowgraph but reversed. *

val forward_flowgraph_of_stmt : ?flatten_loops:bool -> ?blocks_after_body:bool -> Middle.Stmt.Located.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) * (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t

Compute the forward flowgraph of a Stan statement (for forward analyses)

val powerset_lattice : (module Monotone_framework_sigs.INITIALTYPE with type vals = 'v) -> (module Monotone_framework_sigs.LATTICE with type properties = 'v0 Core.Set.Poly.t)

The lattice of sets of some values, with the inclusion order, set union and the empty set

val dual_powerset_lattice : (module Monotone_framework_sigs.INITIALTOTALTYPE with type vals = 'v) -> (module Monotone_framework_sigs.LATTICE with type properties = 'v0 Core.Set.Poly.t)

The lattice of subsets of some set, with the inverse inclusion order, set intersection and the total set

val powerset_lattice_expressions : Middle.Expr.Typed.Set.t -> (module Monotone_framework_sigs.LATTICE with type properties = Middle.Expr.Typed.Set.t)
val new_bot : (module Monotone_framework_sigs.LATTICE_NO_BOT with type properties = 'p) -> (module Monotone_framework_sigs.LATTICE with type properties = 'p0 option)

Add a fresh bottom element to a lattice (possibly without bottom)

val dual_partial_function_lattice : (module Monotone_framework_sigs.TOTALTYPE with type vals = 'dv) -> (module Monotone_framework_sigs.TYPE with type vals = 'cv) -> (module Monotone_framework_sigs.LATTICE_NO_BOT with type properties = ('dv0, 'cv0) Core.Map.Poly.t)

The lattice (without bottom) of partial functions, ordered under inverse graph inclusion, with intersection

val dual_partial_function_lattice_with_bot : (module Monotone_framework_sigs.TOTALTYPE with type vals = 'dv) -> (module Monotone_framework_sigs.TYPE with type vals = 'cv) -> (module Monotone_framework_sigs.LATTICE with type properties = ('dv0, 'cv0) Core.Map.Poly.t option)

The lattice of partial functions, where we add a fresh bottom element, to represent an inconsistent combination of functions

val dual_powerset_lattice_empty_initial : (module Monotone_framework_sigs.TOTALTYPE with type vals = 'v) -> (module Monotone_framework_sigs.LATTICE with type properties = 'v0 Core.Set.Poly.t)

A dual powerset lattice, where we set the initial set to be empty

val powerset_lattice_empty_initial : (module Monotone_framework_sigs.TYPE with type vals = 'v) -> (module Monotone_framework_sigs.LATTICE with type properties = 'v0 Core.Set.Poly.t)

A powerset lattice, where we set the initial set to be empty

val reaching_definitions_lattice : (module Monotone_framework_sigs.INITIALTYPE with type vals = 'v) -> (module Monotone_framework_sigs.TYPE with type vals = 'l) -> (module Monotone_framework_sigs.LATTICE with type properties = ('v0 * 'l0 option) Core.Set.Poly.t)

The specific powerset lattice we use for reaching definitions analysis

val minimal_variables_lattice : string Core.Set.Poly.t -> (module Monotone_framework_sigs.LATTICE with type properties = string Core.Set.Poly.t)

Lattice for finding the smallest set that satisfies some criterion

val constant_propagation_transfer : ?preserve_stability:bool -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = (string, Middle.Expr.Typed.t) Core.Map.Poly.t option)
val label_top_decls : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> int -> string Core.Set.Poly.t
val expression_propagation_transfer : ?preserve_stability:bool -> (Middle.Expr.Typed.t -> bool) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = (string, Middle.Expr.Typed.t) Core.Map.Poly.t option)

The transfer function for an expression propagation analysis, AKA forward substitution (see page 396 of Muchnick)

val copy_propagation_transfer : string Core.Set.Poly.t -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = (string, Middle.Expr.Typed.t) Core.Map.Poly.t option)

The transfer function for a copy propagation analysis

val transfer_gen_kill : ('a, 'b) Core.Set.t -> ('c, 'd) Core.Set.t -> ('a, 'b) Core.Set.t -> ('c, 'd) Core.Set.t

A helper function for building transfer functions from gen and kill sets

val assigned_vars_stmt : (Middle.Expr.Typed.t, 'a) Middle.Stmt.Fixed.Pattern.t -> string Core.Set.Poly.t

Calculate the set of variables that a statement can assign to

val declared_vars_stmt : (Middle.Expr.Typed.t, 'a) Middle.Stmt.Fixed.Pattern.t -> string Core.Set.Poly.t

Calculate the set of variables that a statement can declare

val assigned_or_declared_vars_stmt : (Middle.Expr.Typed.t, 'a) Middle.Stmt.Fixed.Pattern.t -> (string, Core__.Comparator.Poly.comparator_witness) Core.Set.t

Calculate the set of variables that a statement can assign to or declare

val reaching_definitions_transfer : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = (string * int option) Core.Set.Poly.t)

The transfer function for a reaching definitions analysis

val initialized_vars_transfer : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = string Core.Set.Poly.t)

The transfer function for an initialized variables analysis

val live_variables_transfer : string Core.Set.Poly.t -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = string Core.Set.Poly.t)

The transfer function for a live variables analysis

Calculate the set of sub-expressions of an expression

Calculate the set of expressions of an expression

Calculate the set of sub-expressions in a statement

Calculate the set of expressions in a statement

Calculate the set of sub-expressions at the top level in a statement

Calculate the set of expressions at the top level in a statement

Calculate the subset (of p) of expressions that will need to be recomputed as a consequence of evaluating the statement s (because of writes to variables performed by s)

val used : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, (Middle.Expr.Typed.Set.Elt.t, Middle.Expr.Typed.Set.Elt.comparator_witness) Core.Set.t) Core.Map.Poly.t

Calculate the set of subexpressions that needs to be computed at each node in the flowgraph

val anticipated_expressions_transfer : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = Middle.Expr.Typed.Set.t)

The transfer function for an anticipated expressions analysis (as a part of lazy code motion)

val transfer_gen_kill_alt : ('a, 'b) Core.Set.t -> ('a, 'b) Core.Set.t -> ('c, 'd) Core.Set.t -> ('c, 'd) Core.Set.t

A helper function for defining transfer functions in terms of gen and kill sets in an alternative way, that is used in some of the subanalyses of lazy code motion

val available_expressions_transfer : (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t Monotone_framework_sigs.entry_exit) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = Middle.Expr.Typed.Set.t)

An available expressions analysis, to be used in lazy code motion

Calculates the set of expressions that can be calculated for the first time at each node in the flow graph

val postponable_expressions_transfer : (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = Middle.Expr.Typed.Set.t)

The transfer function for a postponable expressions analysis (as a part of lazy code motion)

val latest : (int, int Core.Set.Poly.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t Monotone_framework_sigs.entry_exit) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (int, (Middle.Expr.Typed.Set.Elt.t, Middle.Expr.Typed.Set.Elt.comparator_witness) Core.Set.t) Core.Map.Poly.t

Calculates the set of expressions that can be computed at the latest at each node

val used_not_latest_expressions_transfer : (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (int, Middle.Expr.Typed.Set.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = Middle.Expr.Typed.Set.t)

The transfer function for a used-not-latest expressions analysis, as a part of lazy code motion

val minimal_variables_fwd_transfer : ((int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> int -> string Core.Set.Poly.t -> string Core.Set.Poly.t) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = string Core.Set.Poly.t)

The transfer function for the first forward analysis part of determining optimal ad-levels for variables

val monotone_framework : (module Monotone_framework_sigs.FLOWGRAPH with type labels = 'l) -> (module Monotone_framework_sigs.LATTICE with type properties = 'p) -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = 'l0 and type properties = 'p0) -> (module Monotone_framework_sigs.MONOTONE_FRAMEWORK with type labels = 'l1 and type properties = 'p1)

The central definition of a monotone dataflow analysis framework. Given a compatible flowgraph, lattice and transfer function, we can run the mfp (maximal fixed point) algorithm, which computes a maximal fixed point (MFP) for the set of equations/inequalities of properties at the entry and exit of each node in the flow graph, as defined by the triple. Note that this gives a safe approximation to the MOP (meet over all paths) solution that we would really be interested in, but which is often incomputable. In case of a distributive lattice of properties, the MFP and MOP solutions coincide.

val declared_variables_stmt : (Middle.Expr.Typed.t, Middle.Stmt.Located.t) Middle.Stmt.Fixed.Pattern.t -> string Core.Set.Poly.t
val propagation_mfp : Middle.Program.Typed.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> ((int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (module Monotone_framework_sigs.TRANSFER_FUNCTION with type labels = int and type properties = (string, Middle.Expr.Typed.t) Core.Map.Poly.t option)) -> (int, (string, Middle.Expr.Typed.t) Core.Map.Poly.t option Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t
val reaching_definitions_mfp : Middle.Program.Typed.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, (string * int option) Core.Set.Poly.t Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t
val initialized_vars_mfp : string Core.Set.Poly.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, string Core.Set.Poly.t Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t
val globals : Middle.Program.Typed.t -> string Core.Set.Poly.t
val live_variables_mfp : Middle.Program.Typed.t -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, string Core.Set.Poly.t Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t

Monotone framework instance for live_variables analysis. Expects reverse flowgraph.

val lazy_expressions_mfp : (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> (int, (Middle.Expr.Typed.Set.Elt.t, Middle.Expr.Typed.Set.Elt.comparator_witness) Core.Set.t) Core.Map.Poly.t * (int, Middle.Expr.Typed.Set.t Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t

Instantiate all four instances of the monotone framework for lazy code motion, reusing code between them

val minimal_variables_mfp : (module Monotone_framework_sigs.FLOWGRAPH with type labels = int) -> (int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> string Core.Set.Poly.t -> ((int, Middle.Stmt.Located.Non_recursive.t) Core.Map.Poly.t -> int -> string Core.Set.Poly.t -> string Core.Set.Poly.t) -> (int, string Core.Set.Poly.t Analysis_and_optimization__Monotone_framework_sigs.entry_exit) Core.Map.Poly.t

Run the minimal fixed point algorithm to deduce the smallest set of variables that satisfy a set of conditions.

  • parameter Flowgraph

    The set of nodes to analyze

  • parameter flowgraph_to_mir

    Map of nodes to their actual values in the MIR

  • parameter initial_variables

    The set of variables to start in the set

  • parameter gen_variable

    Used in the transfer function to deduce variables that should be in the set *