Utilities for working with Static-Single-Information LIR form.
Representation of φ and σ
There are no explicit φ/σ
LIRInstruction
s. Instead, they are implemented as
parallel copy that spans across a control-flow edge.
The variables introduced by φ/σ of a specific
block are
attached to the
StandardOp.LabelOp
of the block. The outgoing
values from the predecessor are
input to the
StandardOp.BlockEndOp
of the predecessor.
When it does not matter whether we are talking about a φ or a σ we call the values that
are defined by a label
incoming and the values that are
input to the
StandardOp.BlockEndOp
of the predecessor
outgoing.
Implementation Details
For our purposes we want a
maximal SSI form, which means that all values that are alive
across basic block boundaries are gated with a φ/σ. In other words the outgoing and
incoming values of the
StandardOp.BlockEndOp
and
StandardOp.LabelOp
are equivalent to the live-out and
live-in set of the corresponding block.
As a side effect variables are local to a block. We reuse the name of the predecessor if they
represent the same value (i.e. not a real φ definition).
Examples
Merge (φ)
B0 -> B1
...
v0|i = ...
JUMP ~[v0|i, int[0|0x0]] destination: B0 -> B1
________________________________________________
B2 -> B1
...
v1|i = ...
v2|i = ...
JUMP ~[v1|i, v2|i] destination: B2 -> B1
________________________________________________
B1 <- B0,B2
[v3|i, v4|i] = LABEL
...
Note: the outgoing values of a block can contain constants (see
B0
).
Split (σ)
B0 -> B1,B2
...
v0|i = ...
v1|i = ...
v2|i = ...
TEST (x: v1|i, y: v1|i)
BRANCH ~[v2|i, v0|j] condition: <, true: B1 false: B2
________________________________________________
B1 <- B0
[-, v0|j] = LABEL
...
________________________________________________
B2 <- B0
[v2|i, v0|j] = LABEL
...
Note: If a incoming value is not needed in a branch it is
ignored
(see
B1).