(** * Review *)
(** Consider the following CFG:
[[
1 --> 2
2 --> 3, 11
3 --> 4, 8
4 --> 5
5 --> 6
6 --> 5, 7
7 --> 2
8 --> 9
9 --> 6, 10
10 --> 8
]]
Please draw its dominance tree.
*)
(** Suppose [S = [1; 3; 4; 7]], compute the iterated dominance frontier of
[S]. *)
(* ################################################################# *)
(** * Desctructing SSA form *)
(** When freshly constructed, an SSA code is _conventional_ (we will explain
that later) and its destruction is straightforward: one simply has to
rename all PHI-related variables (source and destination operands of the
same Phi-function) into a unique representative variable. Then, each
PHI-function should have syntactically identical names for all its operands,
and thus can be removed to coalesce the related live-ranges.
Here, we say that [x] and [y] are PHI-related to one another if they are
referenced by the same PHI-command, i.e., if [x] and [y] are either
parameters or defined by the PHI-command. We refer to a set of PHI-related
variables as a PHI-web, i.e. a PHI-web is an equivalence class of the
reflexive transitive closure of the PHI-related relation. The PHI-webs
discovery algorithm is straightforward and efficient based on the
union-find pattern:
- (1) For each variable [v]
- (1.1) Let [phiweb(v)] be the singleton set containing [v]
- (2) For each PHI-command [a0 = PHI(a1, a2, ..., an)]
- (2.1) For [i] in [1, 2, 3, ..., n]
- (2.1.1) Union [phiweb(a0)] and [phiweb(ai)]
We call an SSA code conventional, if all variables of a PHI-web have
non-overlapping live-ranges. *)
(* ################################################################# *)
(** * Making nonconventional SSA form conventional *)
(** Consider the following program.
[[
CFG:
1 --> 2, 3
2 --> 4
3 --> 4
Original Instructions:
1:
a <-- ...
tmp <-- a
2:
a <- a
3:
a <- a + 1
4:
... <- a
... <- tmp
Conventional SSA:
1:
a1 <-- ...
tmp <-- a1
2:
a2 <- a1
3:
a3 <- a1 + 1
4:
a4 <- PHI (a2, a3)
... <- a4
... <- tmp
Transformed SSA:
1:
a1 <-- ...
2:
3:
a3 <- a1 + 1
4:
a4 <- PHI (a1, a3)
... <- a4
... <- a1
]]
It shows that an SSA form may be non-conventional after some transformation.
In order to destruct such kind of SSA, we need to add new variables so that
any two variables in a PHI-web will not interfere with each other. This is not
hard for the sample program above.
[[
After adding new variables:
1:
a1 <-- ...
2:
a1' <- a1
3:
a3 <- a1 + 1
a3' <- a3
4:
a4 <- PHI (a1', a3')
... <- a4
... <- a1
]]
*)
(* ################################################################# *)
(** * Partial redundancy elimination *)
(** The following examples shows typical situations of partial redundancy
elimination.
[[
CFG:
1 --> 2, 3
2 --> 4
3 --> 4
Instructions (before optimization):
2: ... <-- a + b
4: ... <-- a + b
Instructions (after optimization):
2: ... <-- a + b
3: ... <-- a + b
]]
[[
CFG:
1 --> 2
2 --> 2, 3
Instructions (before optimization):
2: ... <-- a + b
Instructions (after optimization):
1: ... <-- a + b
]]
This can be done by insertion-and-deletion.
[[
Example 1:
Annotating the expression:
2: ... <-- a + b [h]
4: h <-- PHI (h, h)
... <-- a + b [h]
Inserting expressions:
2: ... <-- a + b [h]
3: ... <-- a + b [h]
4: h <-- PHI (h, h)
... <-- a + b [h]
deleting expressions:
2: ... <-- a + b [h]
3: ... <-- a + b [h]
4: h <-- PHI (h, h)
]]
[[
Example 2:
Annotating the expression:
2: h <-- PHI (h, h)
... <-- a + b [h]
Inserting expressions:
1: ... <-- a + b [h]
2: h <-- PHI (h, h)
... <-- a + b [h]
deleting expressions:
1: ... <-- a + b [h]
2: h <-- PHI (h, h)
]]
*)
(* 2021-06-09 07:55 *)