Description
So I have a nit to pick with this part of the MIR dataflow guide. In particular:
- I don't think it's quite right, and
- It might suffer from slight ambiguity.
Lemme explain. This is the text:
Convergence
Your analysis must converge to "fixpoint", otherwise it will run forever. Converging to fixpoint is just another way of saying "reaching equilibrium". In order to reach equilibrium, your analysis must obey some laws. One of the laws it must obey is that the bottom value1 joined with some other value equals the second value. Or, as an equation:
bottom join x = x
Another law is that your analysis must have a "top value" such that
top join x = top
Having a top value ensures that your semilattice has a finite height, and the law state above ensures that once the dataflow state reaches top, it will no longer change (the fixpoint will be top).
Here are my issues:
Ambiguity
Your analysis must converge to "fixpoint", otherwise it will run forever.
Isn't this ambiguous? As I understand it, there are many ways to look for an optimum valid point in the lattice, and not all of those require fixpoint.
I also feel weird about the phrase "your analysis must converge to 'fixpoint'". Isn't the framework the one who finds a fixpoint? But to me it feels like we're asking the implementer to find it.
Stuff that seems wrong to me
Bottom's reason
One of the laws it must obey is that the bottom value[^bottom-purpose] joined with some other value equals the second value. Or, as an equation:
> *bottom* join *x* = *x*
As I understand it, the bottom value is important to give the process an initial state, but it's otherwise not really necessary for convergence.
Top's reason
Another law is that your analysis must have a "top value" such that
> *top* join *x* = *top*
Having a top value ensures that your semilattice has a finite height, and the law state above ensures that once the dataflow state reaches top, it will no longer change (the fixpoint will be top).
This on the other hand, I'm certain is not true. The top value ensures that the semilattice has a "common upper bound" for any pair of elements, but it does not force convergence.
I'm going to try to illustrate this with the following example, please let me know if something's not clear:
The interval lattice
Let's define the Interval Lattice as follows:
- Set: let
I
be all pairs of integers[a, b]
wherea <= b
. A pair like that represents the set of integers where for allx
in the set,a <= x
andx <= b
. This is not enough to have a lattice, so let's expandI
with the following intervals:- For every integer
a
, we will add the element[-infinity, a]
and the element[a, infinity]
toI
, so that unbounded ranges can be expressed. In set terms, this means that the elements contained in[a, infinity]
are all integers greater than or equal toa
. - We will add the element
[-infinity, infinity]
toI
so that an unrestricted range can be expressed. This range represents the entirety of the Integer set. - We will add the element
[]
so that an empty range can be expressed. This range represents the Empty set.
- For every integer
- Order: we will use the partial order
A <= B
to mean exactly "A is fully contained in B". This is a partial order, so we're ready to see our lattice. - Join: we will use the operation
A join B
to mean "A intersected with B".
It can be proven that all of this constitutes a valid lattice.
Here is an illustration of it. It uses bottom
as top
, but orientation is a convention in lattices so these are equivalent to how we're using top
and bottom
in our framework.
In our Interval Lattice, we use [-infinity, infinity]
to mean bottom
and []
to mean top
. However, unlike many of the lattices that are likely in use in the compiler today, this lattice has infinite height. Even though it has a top and bottom values.
Here are more details into this lattice and how to work with it to actually get convergence. It's part of Static Program Analysis, one of the resources quoted in the docs :3
So what's the reason for top, then
Top is needed to have a complete lattice. This just helps prove certain properties. But it does not help convergence. We need something stronger than that, otherwise there will be lattices like the one above which will not converge even though our requisites are being satisified.
Convergence, then
The main property that's used for proving convergence for fixpoint algorithms over common Lattices is the Ascending Chain Condition (or Descending CC, depending on the convention. In our convention, we start at the bottom
element, so we use the ACC). It basically states that any strictly ascending chain of elements in the lattice must be finite, or in other words, that any ascending chain of elements in the lattice must reach an n-th element, from which it doesn't go up anymore.
This is definitely strong enough for our fixpoint context, since the fixpoint algorithms will reach convergence, at most at the end of the ACC that they are climbing.
This also rejects the lattice I described above, and for good reason: it cannot be directly searched with fixpoint algorithms; it has the capability of never converging to a value. But for lattices like those, approximations can be done that let fixpoint algorithms converge, and maybe that can be pointed out in the docs if / when the framework is capable of working with such approximations.
Footnotes
-
The bottom value's primary purpose is as the initial dataflow
state. Each basic block's entry state is initialized to bottom before the
analysis starts. ↩