Monotone Dataflow Engine ======================== Overview ======== The **monotone dataflow engine** in ``lib/Dataflow/Mono`` implements a classic **bit-vector style** framework for intraprocedural and interprocedural analyses over LLVM IR. * **Location**: ``lib/Dataflow/Mono`` * **Main classes**: ``DataFlowEngine``, ``DataFlowResult`` * **Direction**: forward or backward (configurable per analysis) Core Idea ========= Facts are represented as sets of LLVM values (``std::set``). For each instruction ``n`` an analysis defines: * ``GEN[n]`` — facts generated at ``n``, * ``KILL[n]`` — facts killed at ``n``, * ``IN[n]`` — facts before executing ``n``, * ``OUT[n]`` — facts after executing ``n``. The engine repeatedly applies client-provided callbacks (``computeGEN``, ``computeKILL``, ``computeIN``, ``computeOUT``) until all ``IN``/``OUT`` sets reach a monotone fixed point. Example Analyses ================ Live Variables (SSA) -------------------- ``runLiveVariablesAnalysis`` implements a **backward liveness analysis** for SSA registers: * **Direction**: backward. * **Facts**: SSA values that are live at a program point. * **Equations**: * ``GEN[n]`` = operands of ``n`` that are instructions or arguments, * ``KILL[n]`` = ``{n}`` if ``n`` defines a non-void value, * ``OUT[n]`` = ⋃ ``IN[s]`` for all CFG successors ``s``, * ``IN[n]`` = ``(OUT[n] - KILL[n]) ∪ GEN[n]``. Reachable Instructions ---------------------- ``runReachableAnalysis`` is another client that computes which instructions are **reachable in the future**: * **Direction**: backward. * **Facts**: instructions that can be executed after ``n``. * **Equations**: * ``GEN[n]`` = ``{n}`` if a user-supplied predicate ``filter(n)`` holds, * ``KILL[n]`` = ∅, * ``OUT[n]`` = ⋃ ``IN[s]`` for all successors ``s``, * ``IN[n]`` = ``GEN[n] ∪ OUT[n]``. Both examples show how to express standard gen–kill problems while delegating the fixed-point iteration to ``DataFlowEngine``.