Skip to content

Commit 18db2b7

Browse files
Implement second method of building DOM Frontiers based on Appel's Modern Compiler Implementation in C.
Set the IDOM of root node to null rather than itself, post Dom Tree calculation. Add option to dump out the DOM Tree Pre-SSA
1 parent c6e2937 commit 18db2b7

File tree

6 files changed

+92
-11
lines changed

6 files changed

+92
-11
lines changed

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/BasicBlock.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ public StringBuilder toDot(StringBuilder sb, boolean verbose) {
213213
sb.append("</TABLE>");
214214
return sb;
215215
}
216+
public StringBuilder listDomFrontiers(StringBuilder sb) {
217+
sb.append("L").append(this.bid).append(":");
218+
for (BasicBlock bb: dominationFrontier) {
219+
sb.append(" L").append(bb.bid);
220+
}
221+
sb.append("\n");
222+
return sb;
223+
}
216224
@Override
217225
public boolean equals(Object o) {
218226
if (this == o) return true;

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/DominatorTree.java

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package com.compilerprogramming.ezlang.compiler;
22

3-
import java.util.ArrayList;
43
import java.util.Comparator;
54
import java.util.HashSet;
65
import java.util.List;
7-
import java.util.function.Consumer;
86

97
/**
108
* The dominator tree construction algorithm is based on figure 9.24,
@@ -34,14 +32,15 @@ public DominatorTree(BasicBlock entry) {
3432
populateTree();
3533
setDepth();
3634
calculateDominanceFrontiers();
35+
//calculateDominanceFrontiersMethod2();
3736
}
3837

3938
private void calculateDominatorTree() {
4039
resetDomInfo();
4140
annotateBlocksWithRPO();
4241
sortBlocksByRPO();
4342

44-
// Set IDom entry for root to itself
43+
// Set IDom entry for root to itself (see note below)
4544
entry.idom = entry;
4645
boolean changed = true;
4746
while (changed) {
@@ -68,6 +67,11 @@ private void calculateDominatorTree() {
6867
}
6968
}
7069
}
70+
// There is a contradiction between what is described in the book
71+
// and the algo - as the book says the IDOM for root is undefined
72+
// But we set this to itself when calculating. So after calculations
73+
// are done, set this to null. This is technically more correct IMO.
74+
entry.idom = null;
7175
}
7276

7377
private void resetDomInfo() {
@@ -146,7 +150,7 @@ private BasicBlock findFirstPredecessorWithIdom(BasicBlock n) {
146150
private void populateTree() {
147151
for (BasicBlock block : blocks) {
148152
BasicBlock idom = block.idom;
149-
if (idom == block) // root
153+
if (idom == null) // root
150154
continue;
151155
// add edge from idom to n
152156
idom.dominatedChildren.add(block);
@@ -166,12 +170,13 @@ private void setDepth() {
166170
*/
167171
private void setDepth_(BasicBlock block) {
168172
BasicBlock idom = block.idom;
169-
if (idom != block) {
173+
if (idom != null) {
170174
assert idom.domDepth > 0;
171175
block.domDepth = idom.domDepth + 1;
172-
} else {
173-
assert idom.domDepth == 1;
174-
assert idom.domDepth == block.domDepth;
176+
}
177+
else {
178+
// root (entry) block's idom is null
179+
assert block.domDepth == 1;
175180
}
176181
for (BasicBlock child : block.dominatedChildren)
177182
setDepth_(child);
@@ -189,6 +194,8 @@ private void calculateDominanceFrontiers() {
189194
// while runner != doms[b]
190195
// add b to runner’s dominance frontier set
191196
// runner = doms[runner]
197+
for (BasicBlock b: blocks)
198+
b.dominationFrontier.clear(); // empty set
192199
for (BasicBlock b : blocks) {
193200
if (b.predecessors.size() >= 2) {
194201
for (BasicBlock p : b.predecessors) {
@@ -204,6 +211,37 @@ private void calculateDominanceFrontiers() {
204211
}
205212
}
206213

214+
// We have an alternative approach to calculating DOM Frontiers to
215+
// allow us to validate above
216+
private void calculateDominanceFrontiersMethod2()
217+
{
218+
for (BasicBlock b: blocks)
219+
b.dominationFrontier.clear(); // empty set
220+
computeDF(entry);
221+
}
222+
223+
// Implementation based on description in pg 440 of
224+
// Modern Compiler implementation in C
225+
// Appel
226+
private void computeDF(BasicBlock n) {
227+
var S = new HashSet<BasicBlock>();
228+
for (BasicBlock y: n.successors) {
229+
if (y.idom != n)
230+
S.add(y);
231+
}
232+
for (BasicBlock c: n.dominatedChildren) {
233+
computeDF(c);
234+
for (BasicBlock w: c.dominationFrontier) {
235+
// Note that the printed book has an error below
236+
// and errata gives the correct version
237+
if (!n.dominates(w) || n==w) {
238+
S.add(w);
239+
}
240+
}
241+
}
242+
n.dominationFrontier.addAll(S);
243+
}
244+
207245
public String generateDotOutput() {
208246
StringBuilder sb = new StringBuilder();
209247
sb.append("digraph DomTree {\n");
@@ -212,10 +250,18 @@ public String generateDotOutput() {
212250
}
213251
for (BasicBlock n : blocks) {
214252
BasicBlock idom = n.idom;
215-
if (idom == n) continue;
253+
if (idom == null) continue;
216254
sb.append(idom.uniqueName()).append("->").append(n.uniqueName()).append(";\n");
217255
}
218256
sb.append("}\n");
219257
return sb.toString();
220258
}
259+
260+
public String listDomFrontiers() {
261+
StringBuilder sb = new StringBuilder();
262+
for (BasicBlock n : blocks) {
263+
n.listDomFrontiers(sb);
264+
}
265+
return sb.toString();
266+
}
221267
}

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/EnterSSA.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ public EnterSSA(CompiledFunction bytecodeFunction, EnumSet<Options> options) {
4141
System.out.println("Pre SSA Dominator Tree");
4242
System.out.println(domTree.generateDotOutput());
4343
}
44+
if (options.contains(Options.DUMP_PRE_SSA_DOMFRONTIERS)) {
45+
System.out.println("Pre SSA Dominance Frontiers");
46+
System.out.println(domTree.listDomFrontiers());
47+
}
4448
this.blocks = domTree.blocks; // the blocks are ordered reverse post order
4549
findNonLocalNames();
4650
new Liveness(bytecodeFunction); // EWe require liveness info to construct pruned ssa

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/Options.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public enum Options {
1010
REGALLOC,
1111
DUMP_INITIAL_IR,
1212
DUMP_PRE_SSA_DOMTREE,
13+
DUMP_PRE_SSA_DOMFRONTIERS,
1314
DUMP_SSA_IR,
1415
DUMP_SCCP_PREAPPLY,
1516
DUMP_SCCP_POSTAPPLY,

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestDominators.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ BasicBlock add(List<BasicBlock> nodes, BasicBlock node) {
1212
return node;
1313
}
1414

15+
// This CFG example is taken from page 473 of
16+
// Engineering a Compiler 3rd ed
1517
BasicBlock makeGraph(List<BasicBlock> nodes) {
1618
BasicBlock r0 = add(nodes, new BasicBlock(1));
1719
BasicBlock r1 = add(nodes, new BasicBlock(2, r0));
@@ -28,15 +30,34 @@ BasicBlock makeGraph(List<BasicBlock> nodes) {
2830
return r0;
2931
}
3032

33+
// This DOM Tree example is taken from page 473 of
34+
// Engineering a Compiler 3rd ed
3135
@Test
3236
public void testDominatorTree() {
3337
List<BasicBlock> nodes = new ArrayList<>();
3438
BasicBlock root = makeGraph(nodes);
3539
DominatorTree tree = new DominatorTree(root);
3640
System.out.println(tree.generateDotOutput());
37-
long[] expectedIdoms = {0,1,1,2,2,4,2,6,6,6};
41+
// expected {_,_,0,1,1,3,1,5,5,5}
42+
// Note first entry is not used
43+
// Note we set idom of root to itself so the second entry
44+
// does not match example
45+
long[] expectedIdoms = {-1,0,1,2,2,4,2,6,6,6};
3846
for (BasicBlock n: nodes) {
39-
Assert.assertEquals(expectedIdoms[(int)n.bid], n.idom.bid);
47+
if (expectedIdoms[(int)n.bid] == 0)
48+
Assert.assertNull(n.idom);
49+
else
50+
Assert.assertEquals(expectedIdoms[(int)n.bid], n.idom.bid);
51+
}
52+
// -1 means empty set
53+
long[] expectedDF = {0,-1,2,4,2,-1,4,8,4,8};
54+
for (BasicBlock n: nodes) {
55+
if (expectedDF[(int)n.bid] == -1) {
56+
Assert.assertTrue(n.dominationFrontier.isEmpty());
57+
}
58+
else {
59+
Assert.assertEquals(1,n.dominationFrontier.size());
60+
}
4061
}
4162
}
4263

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestSSATransform.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ String compileSrc(String src) {
2626
BasicBlock.toStr(sb, functionBuilder.entry, new BitSet(), false);
2727
//functionBuilder.toDot(sb,false);
2828
new EnterSSA(functionBuilder, Options.NONE);
29+
//new EnterSSA(functionBuilder, EnumSet.of(DUMP_PRE_SSA_DOMFRONTIERS));
2930
sb.append("After SSA\n");
3031
sb.append("=========\n");
3132
BasicBlock.toStr(sb, functionBuilder.entry, new BitSet(), false);

0 commit comments

Comments
 (0)