Skip to content

Commit bad22b5

Browse files
Merge pull request #25 from CompilerProgramming/sccp
SCCP: some more test cases
2 parents 8e4fb47 + 4ead605 commit bad22b5

File tree

12 files changed

+350
-32
lines changed

12 files changed

+350
-32
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
*/
1818
public class ChaitinGraphColoringRegisterAllocator {
1919

20-
public Map<Integer, Integer> assignRegisters(CompiledFunction function, int numRegisters) {
20+
public Map<Integer, Integer> assignRegisters(CompiledFunction function, int numRegisters, EnumSet<Options> options) {
2121
if (function.isSSA) throw new IllegalStateException("Register allocation should be done after exiting SSA");
2222
// Remove useless copy operations
23-
InterferenceGraph g = coalesce(function);
23+
InterferenceGraph g = coalesce(function, options);
2424
// Get used registers
2525
Set<Integer> registers = registersInIR(function);
2626
// Create color set
@@ -36,6 +36,8 @@ public Map<Integer, Integer> assignRegisters(CompiledFunction function, int numR
3636
updateInstructions(function, assignments);
3737
// Compute and set the new framesize
3838
function.setFrameSize(computeFrameSize(assignments));
39+
if (options.contains(Options.DUMP_POST_CHAITIN_IR))
40+
function.dumpIR(false, "Post Chaitin Register Allocation");
3941
return assignments;
4042
}
4143

@@ -83,13 +85,17 @@ private void updateInstructions(CompiledFunction function, Map<Integer, Integer>
8385
/**
8486
* Chaitin: coalesce_nodes - coalesce away copy operations
8587
*/
86-
public InterferenceGraph coalesce(CompiledFunction function) {
88+
public InterferenceGraph coalesce(CompiledFunction function, EnumSet<Options> options) {
8789
boolean changed = true;
8890
InterferenceGraph igraph = null;
8991
while (changed) {
9092
igraph = new InterferenceGraphBuilder().build(function);
9193
changed = coalesceCopyOperations(function, igraph);
9294
}
95+
if (options.contains(Options.DUMP_CHAITIN_COALESCE)) {
96+
System.out.println("Post Chaitin Coalesce Registers");
97+
System.out.println(function.toStr(new StringBuilder(), false));
98+
}
9399
return igraph;
94100
}
95101

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,11 @@ public StringBuilder toStr(StringBuilder sb, boolean verbose) {
566566
return sb;
567567
}
568568

569+
public void dumpIR(boolean verbose, String title) {
570+
System.out.println(title);
571+
System.out.println(toStr(new StringBuilder(), verbose));
572+
}
573+
569574
public void livenessAnalysis() {
570575
new Liveness(this);
571576
this.hasLiveness = true;

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,34 @@
88
import com.compilerprogramming.ezlang.types.Type;
99
import com.compilerprogramming.ezlang.types.TypeDictionary;
1010

11+
import java.util.EnumSet;
12+
1113
public class Compiler {
1214

13-
private void compile(TypeDictionary typeDictionary, boolean opt) {
15+
private void compile(TypeDictionary typeDictionary, EnumSet<Options> options) {
1416
for (Symbol symbol: typeDictionary.getLocalSymbols()) {
1517
if (symbol instanceof Symbol.FunctionTypeSymbol functionSymbol) {
1618
Type.TypeFunction functionType = (Type.TypeFunction) functionSymbol.type;
1719
var function = new CompiledFunction(functionSymbol);
20+
if (options.contains(Options.DUMP_INITIAL_IR))
21+
function.dumpIR(false, "Initial IR");
1822
functionType.code = function;
19-
if (opt) {
20-
new Optimizer().optimize(function);
21-
}
23+
new Optimizer().optimize(function, options);
2224
}
2325
}
2426
}
2527
public TypeDictionary compileSrc(String src) {
26-
return compileSrc(src, false);
28+
return compileSrc(src, EnumSet.noneOf(Options.class));
2729
}
28-
public TypeDictionary compileSrc(String src, boolean opt) {
30+
public TypeDictionary compileSrc(String src, EnumSet<Options> options) {
2931
Parser parser = new Parser();
3032
var program = parser.parse(new Lexer(src));
3133
var typeDict = new TypeDictionary();
3234
var sema = new SemaDefineTypes(typeDict);
3335
sema.analyze(program);
3436
var sema2 = new SemaAssignTypes(typeDict);
3537
sema2.analyze(program);
36-
compile(typeDict, opt);
38+
compile(typeDict, options);
3739
return typeDict;
3840
}
3941
public static String dumpIR(TypeDictionary typeDictionary) {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,21 @@ public class EnterSSA {
3333
int[] counters;
3434
VersionStack[] stacks;
3535

36-
public EnterSSA(CompiledFunction bytecodeFunction) {
36+
public EnterSSA(CompiledFunction bytecodeFunction, EnumSet<Options> options) {
3737
this.function = bytecodeFunction;
3838
setupGlobals();
3939
computeDomTreeAndDominanceFrontiers();
40+
if (options.contains(Options.DUMP_PRE_SSA_DOMTREE)) {
41+
System.out.println("Pre SSA Dominator Tree");
42+
System.out.println(domTree.generateDotOutput());
43+
}
4044
this.blocks = domTree.blocks; // the blocks are ordered reverse post order
4145
findNonLocalNames();
4246
insertPhis();
4347
renameVars();
4448
bytecodeFunction.isSSA = true;
4549
bytecodeFunction.hasLiveness = false;
50+
if (options.contains(Options.DUMP_SSA_IR)) bytecodeFunction.dumpIR(false, "Post SSA IR");
4651
}
4752

4853
private void computeDomTreeAndDominanceFrontiers() {

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,21 @@ public class ExitSSA {
1717
NameStack[] stacks;
1818
DominatorTree tree;
1919

20-
public ExitSSA(CompiledFunction function) {
20+
public ExitSSA(CompiledFunction function, EnumSet<Options> options) {
2121
this.function = function;
2222
if (!function.isSSA) throw new IllegalStateException();
2323
function.livenessAnalysis();
24-
System.out.println(function.toStr(new StringBuilder(), true));
24+
if (options.contains(Options.DUMP_SSA_LIVENESS)) function.dumpIR(true, "SSA Liveness Analysis");
2525
tree = new DominatorTree(function.entry);
26+
if (options.contains(Options.DUMP_SSA_DOMTREE)) {
27+
System.out.println("Pre SSA Dominator Tree");
28+
System.out.println(tree.generateDotOutput());
29+
}
2630
initStack();
2731
insertCopies(function.entry);
2832
removePhis();
2933
function.isSSA = false;
34+
if (options.contains(Options.DUMP_POST_SSA_IR)) function.dumpIR(false, "After exiting SSA");
3035
}
3136

3237
private void removePhis() {
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package com.compilerprogramming.ezlang.compiler;
22

3+
import java.util.EnumSet;
4+
35
public class Optimizer {
46

5-
public void optimize(CompiledFunction function) {
6-
new EnterSSA(function);
7-
new SparseConditionalConstantPropagation().constantPropagation(function).apply();
8-
new ExitSSA(function);
9-
new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64);
7+
public void optimize(CompiledFunction function, EnumSet<Options> options) {
8+
if (options.contains(Options.OPTIMIZE)) {
9+
new EnterSSA(function, options);
10+
if (options.contains(Options.SCCP))
11+
new SparseConditionalConstantPropagation().constantPropagation(function).apply(options);
12+
new ExitSSA(function, options);
13+
}
14+
if (options.contains(Options.REGALLOC))
15+
new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64, options);
1016
}
1117
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.compilerprogramming.ezlang.compiler;
2+
3+
import java.util.EnumSet;
4+
5+
public enum Options {
6+
OPTIMIZE,
7+
SCCP,
8+
REGALLOC,
9+
DUMP_INITIAL_IR,
10+
DUMP_PRE_SSA_DOMTREE,
11+
DUMP_SSA_IR,
12+
DUMP_SCCP_PREAPPLY,
13+
DUMP_SCCP_POSTAPPLY,
14+
DUMP_SSA_LIVENESS,
15+
DUMP_SSA_DOMTREE,
16+
DUMP_POST_SSA_IR,
17+
DUMP_INTERFERENCE_GRAPH,
18+
DUMP_CHAITIN_COALESCE,
19+
DUMP_POST_CHAITIN_IR;
20+
21+
public static final EnumSet<Options> NONE = EnumSet.noneOf(Options.class);
22+
public static final EnumSet<Options> OPT = EnumSet.of(Options.OPTIMIZE,Options.SCCP,Options.REGALLOC);
23+
public static final EnumSet<Options> OPT_VERBOSE = EnumSet.allOf(Options.class);
24+
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private void init(CompiledFunction function) {
120120
visited = new BitSet();
121121
}
122122

123-
public SparseConditionalConstantPropagation apply() {
123+
public SparseConditionalConstantPropagation apply(EnumSet<Options> options) {
124124
/*
125125
The constant propagation algorithm does not change the flow graph - it computes
126126
information about the flow graph. The compiler now uses this information to improve
@@ -137,10 +137,15 @@ public SparseConditionalConstantPropagation apply() {
137137
138138
Bob Morgan. Building an Optimizing Compiler
139139
*/
140+
if (options.contains(Options.DUMP_SCCP_PREAPPLY)) {
141+
System.out.println("SCCP analysis\n");
142+
System.out.println(toString());
143+
}
140144
markExecutableBlocks();
141145
removeBranchesThatAreNotExecutable();
142146
replaceVarsWithConstants();
143147
// Unreachable blocks are eliminated as there are no paths to them
148+
if (options.contains(Options.DUMP_SCCP_POSTAPPLY)) function.dumpIR(false, "Post SCCP\n");
144149
return this;
145150
}
146151

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void test4() {
1515
Assert.assertEquals(2, edges.size());
1616
Assert.assertTrue(edges.contains(new InterferenceGraph.Edge(0, 1)));
1717
Assert.assertTrue(edges.contains(new InterferenceGraph.Edge(0, 2)));
18-
var regAssignments = new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64);
18+
var regAssignments = new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64, Options.OPT);
1919
String result = function.toStr(new StringBuilder(), false).toString();
2020
Assert.assertEquals("""
2121
L0:

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@
55
import org.junit.Test;
66

77
import java.util.BitSet;
8+
import java.util.EnumSet;
89

910
public class TestSCCP {
1011

1112
String compileSrc(String src) {
1213
var compiler = new Compiler();
1314
var typeDict = compiler.compileSrc(src);
1415
StringBuilder sb = new StringBuilder();
16+
var options = Options.NONE;
1517
for (Symbol s : typeDict.bindings.values()) {
1618
if (s instanceof Symbol.FunctionTypeSymbol f) {
1719
var functionBuilder = (CompiledFunction) f.code();
18-
new EnterSSA(functionBuilder);
20+
new EnterSSA(functionBuilder, options);
1921
BasicBlock.toStr(sb, functionBuilder.entry, new BitSet(), false);
2022
//functionBuilder.toDot(sb, false);
2123
var sccp = new SparseConditionalConstantPropagation().constantPropagation(functionBuilder);
2224
sb.append(sccp.toString());
23-
sccp.apply();
25+
sccp.apply(options);
2426
sb.append("After SCCP changes:\n");
2527
functionBuilder.toStr(sb, false);
2628
}

0 commit comments

Comments
 (0)