Skip to content

Commit f7b9f90

Browse files
authored
add some more documentation for analysis (#273)
1 parent e74f4e5 commit f7b9f90

File tree

2 files changed

+101
-4
lines changed

2 files changed

+101
-4
lines changed

docs/analysis.md

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,102 @@
55

66
# Analysis
77

8-
Kirin provides a framework for performing dataflow analysis on the IR. This is done via
8+
Kirin provides a set of analysis tools for common analysis tasks and for building new analysis tools.
99

10-
- IR walking
11-
- Abstract interpretation
10+
## Forward Dataflow Analysis
1211

13-
## Lattice
12+
The forward dataflow analysis is a common analysis technique that computes the dataflow information of a program by propagating the information forward through the control flow graph. The forward dataflow analysis is implemented in the [`kirin.analysis.Forward`][kirin.analysis.Forward] class.
13+
14+
The build a forward dataflow analysis, you need to define a lattice. The lattice represents the set of values that can be computed by the analysis.
15+
16+
### Lattice
1417

1518
A lattice is a set of values that are partially ordered. In Kirin IR, a lattice is a subclass of the [`Lattice`][kirin.lattice.abc.Lattice] ABC class. A lattice can be used to represent the result of a statement that has multiple possible results.
19+
20+
The `kirin.lattice` module provides a set of base and mixin classes that can be used to build some common lattices.
21+
22+
Most of the lattices are bounded lattices, which can be implemented by using the [`BoundedLattice`][kirin.lattice.abc.BoundedLattice] abstract class.
23+
24+
Some lattice elements are singleton, which means the lattice class represents a single instance. A metaclass [`SingletonMeta`][kirin.lattice.abc.SingletonMeta] is provided to create singleton lattice class that guarantees only one instance will be created, e.g the following is a trivial lattice named `EmptyLattice`:
25+
26+
```python
27+
class EmptyLattice(BoundedLattice["EmptyLattice"], metaclass=SingletonMeta):
28+
"""Empty lattice."""
29+
30+
def join(self, other: "EmptyLattice") -> "EmptyLattice":
31+
return self
32+
33+
def meet(self, other: "EmptyLattice") -> "EmptyLattice":
34+
return self
35+
36+
@classmethod
37+
def bottom(cls):
38+
return cls()
39+
40+
@classmethod
41+
def top(cls):
42+
return cls()
43+
44+
def __hash__(self) -> int:
45+
return id(self)
46+
47+
def is_subseteq(self, other: "EmptyLattice") -> bool:
48+
return True
49+
```
50+
51+
where the lattice is a `BoundedLattice` and it is also a singleton class, which means the class will only have one instance.
52+
53+
### Putting things together
54+
55+
To build a forward dataflow analysis, you need to define a lattice and subclass the `Forward` class. The following is the type inference analysis (simplified) that infers the type of each variable in the program:
56+
57+
```python
58+
class TypeInference(Forward[types.TypeAttribute]):
59+
keys = ["typeinfer"]
60+
lattice = types.TypeAttribute
61+
```
62+
63+
where the class `TypeInference` is actually the same as the [interpreter](interp.md) we introduced before, but instead of running on concrete values, it runs on the lattice values and walks through all the control flow branches. The field `keys` is a list of keys that tells the interpreter which method registry to use to run the analysis (similar to the key `"main"` for concrete interpretation).
64+
65+
## Control Flow Graph
66+
67+
The control flow graph (CFG) can be constructed by calling the [`CFG`][kirin.analysis.cfg.CFG] class constructor. The CFG is a directed graph that represents the control flow of the program. Each node in the graph represents a basic block, and each edge represents a control flow transfer between two basic blocks.
68+
69+
An example of using the CFG class to construct a CFG is shown below:
70+
71+
```python
72+
from kirin.analysis import CFG
73+
from kirin.prelude import basic
74+
75+
@basic
76+
def main(x):
77+
if x > 0:
78+
y = 1
79+
else:
80+
y = 2
81+
return y
82+
83+
84+
cfg = CFG(main.callable_region)
85+
cfg.print()
86+
```
87+
88+
prints the following directed acyclic graph:
89+
90+
```
91+
Successors:
92+
^0 -> [^1, ^2]
93+
^2 -> [^3]
94+
^3 -> []
95+
^1 -> [^3]
96+
97+
Predecessors:
98+
^1 <- [^0]
99+
^2 <- [^0]
100+
^3 <- [^2, ^1]
101+
```
102+
103+
## API References
104+
105+
::: kirin.analysis.Forward
106+
::: kirin.analysis.cfg.CFG

src/kirin/lattice/abc.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ def __hash__(self) -> int:
7272

7373

7474
class BoundedLattice(Lattice[BoundedLatticeType]):
75+
"""ABC for bounded lattices as Python class.
76+
77+
`BoundedLattice` is an abstract class that can be inherited from.
78+
It requires the implementation of the `bottom` and `top` methods.
79+
"""
80+
7581
@classmethod
7682
@abstractmethod
7783
def bottom(cls) -> BoundedLatticeType: ...

0 commit comments

Comments
 (0)