Skip to content

Commit 88e7dae

Browse files
WIP implement incremental SSA construction using Braun's method
WIP implement incremental SSA construction using Braun's method WIP implement incremental SSA construction using Braun's method WIP implement incremental SSA construction using Braun's method WIP implement incremental SSA construction using Braun's method Small refactor to help with the incremental SSA diff Add option to control ISSA Add missing use replacement in Phis Some other cleanup and comments Bug fix Some prep work on enabling more tests Consider temp registers too as part of SSA because in boolean expressions, a temp is assigned value more than once so although generally temps are SSA already, in this case they are not. phi vars must also be SSA values When temps are used for creating arrays and structs ensure they get processed in the same way as all temps. Delete some unused code bug fixes Have to be seal BBs as soon as possible - will need to review this carefully
1 parent 59a83eb commit 88e7dae

File tree

13 files changed

+624
-60
lines changed

13 files changed

+624
-60
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ public void deleteInstruction(Instruction instruction) {
111111
instructions.remove(instruction);
112112
}
113113
public void addSuccessor(BasicBlock successor) {
114-
assert successors.contains(successor) == false;
115-
successors.add(successor);
116-
assert successor.predecessors.contains(this) == false;
117-
successor.predecessors.add(this);
114+
if (!successors.contains(successor)) {
115+
successors.add(successor);
116+
successor.predecessors.add(this);
117+
}
118118
}
119119
public void removeSuccessor(BasicBlock successor) {
120120
successors.remove(successor);

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

Lines changed: 466 additions & 42 deletions
Large diffs are not rendered by default.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ private void compile(TypeDictionary typeDictionary, EnumSet<Options> options) {
1616
for (Symbol symbol: typeDictionary.getLocalSymbols()) {
1717
if (symbol instanceof Symbol.FunctionTypeSymbol functionSymbol) {
1818
Type.TypeFunction functionType = (Type.TypeFunction) functionSymbol.type;
19-
var function = new CompiledFunction(functionSymbol, typeDictionary);
19+
var function = new CompiledFunction(functionSymbol, typeDictionary, options);
2020
if (options.contains(Options.DUMP_INITIAL_IR))
2121
function.dumpIR(false, "Initial IR");
2222
functionType.code = function;

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,22 @@ public StringBuilder toStr(StringBuilder sb) {
426426
sb.append(")");
427427
return sb;
428428
}
429+
public void addInput(Register register) {
430+
var newUses = new Operand[uses.length + 1];
431+
System.arraycopy(uses, 0, newUses, 0, uses.length);
432+
newUses[newUses.length-1] = new Operand.RegisterOperand(register);
433+
this.uses = newUses;
434+
}
435+
public void replaceInput(Register oldReg, Register newReg) {
436+
for (int i = 0; i < numInputs(); i++) {
437+
if (isRegisterInput(i)) {
438+
Register in = inputAsRegister(i);
439+
if (in.equals(oldReg)) {
440+
replaceInput(i, newReg);
441+
}
442+
}
443+
}
444+
}
429445
}
430446

431447
public static class ArgInstruction extends Instruction {

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.compilerprogramming.ezlang.compiler;
22

3+
import com.compilerprogramming.ezlang.types.Symbol;
34
import com.compilerprogramming.ezlang.types.Type;
45

56
public class Operand {
@@ -48,12 +49,14 @@ public String toString() {
4849
}
4950

5051
public static class LocalRegisterOperand extends RegisterOperand {
51-
public LocalRegisterOperand(Register reg) {
52+
Symbol.VarSymbol variable;
53+
public LocalRegisterOperand(Register reg, Symbol.VarSymbol variable) {
5254
super(reg);
55+
this.variable = variable;
5356
}
5457
@Override
5558
public RegisterOperand copy(Register register) {
56-
return new LocalRegisterOperand(register);
59+
return new LocalRegisterOperand(register, variable);
5760
}
5861
}
5962

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ public class Optimizer {
66

77
public void optimize(CompiledFunction function, EnumSet<Options> options) {
88
if (options.contains(Options.OPTIMIZE)) {
9-
new EnterSSA(function, options);
9+
if (!function.isSSA)
10+
new EnterSSA(function, options);
1011
if (options.contains(Options.SCCP)) {
1112
new SparseConditionalConstantPropagation().constantPropagation(function).apply(options);
1213
if (new ConstantComparisonPropagation(function).apply(options)) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.EnumSet;
44

55
public enum Options {
6+
ISSA, // Incremental SSA
67
OPTIMIZE,
78
SCCP,
89
CCP, // constant comparison propagation
@@ -22,5 +23,6 @@ public enum Options {
2223

2324
public static final EnumSet<Options> NONE = EnumSet.noneOf(Options.class);
2425
public static final EnumSet<Options> OPT = EnumSet.of(Options.OPTIMIZE,Options.SCCP,Options.CCP,Options.REGALLOC);
25-
public static final EnumSet<Options> OPT_VERBOSE = EnumSet.allOf(Options.class);
26+
public static final EnumSet<Options> VERBOSE = EnumSet.range(DUMP_INITIAL_IR, DUMP_POST_CHAITIN_IR);
27+
public static final EnumSet<Options> OPT_VERBOSE = EnumSet.range(OPTIMIZE, DUMP_POST_CHAITIN_IR);
2628
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public String name() {
8383
* During SSA form this is not valid for registers that are instances of SSARegister.
8484
*/
8585
public int nonSSAId() {
86+
assert frameSlot >= 0;
8687
return frameSlot;
8788
}
8889
public void updateSlot(int slot) {
@@ -106,4 +107,6 @@ public int nonSSAId() {
106107
return originalRegNumber;
107108
}
108109
}
110+
111+
109112
}

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,16 @@ private static void recordUses(CompiledFunction function, Map<Register, SSADef>
8383

8484
private static void recordUses(Map<Register, SSADef> defUseChains, Register[] inputs, BasicBlock block, Instruction instruction) {
8585
for (Register register : inputs) {
86-
SSADef def = defUseChains.get(register);
87-
def.useList.add(instruction);
86+
recordUse(defUseChains, instruction, register);
8887
}
8988
}
9089

91-
private static void recordDef(Map<Register, SSADef> defUseChains, Register value, Instruction instruction) {
90+
public static void recordUse(Map<Register, SSADef> defUseChains, Instruction instruction, Register register) {
91+
SSADef def = defUseChains.get(register);
92+
def.useList.add(instruction);
93+
}
94+
95+
public static void recordDef(Map<Register, SSADef> defUseChains, Register value, Instruction instruction) {
9296
if (defUseChains.containsKey(value))
9397
throw new CompilerException("Register already defined, invalid multiple definition in SSA");
9498
defUseChains.put(value, new SSADef(instruction));
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.compilerprogramming.ezlang.compiler;
2+
3+
import org.junit.Test;
4+
5+
import java.util.EnumSet;
6+
7+
public class TestIncrementalSSA {
8+
String compileSrc(String src) {
9+
var compiler = new Compiler();
10+
var typeDict = compiler.compileSrc(src, EnumSet.of(Options.ISSA));
11+
return compiler.dumpIR(typeDict);
12+
}
13+
14+
@Test
15+
public void test1() {
16+
String src = """
17+
func foo(d: Int) {
18+
var a = 42;
19+
var b = a;
20+
var c = a + b;
21+
a = c + 23;
22+
c = a + d;
23+
}
24+
""";
25+
String result = compileSrc(src);
26+
System.out.println(result);
27+
}
28+
29+
@Test
30+
public void test2() {
31+
String src = """
32+
func foo(d: Int)->Int {
33+
var a = 42
34+
if (d)
35+
{
36+
a = a + 1
37+
}
38+
else
39+
{
40+
a = a - 1
41+
}
42+
return a
43+
}
44+
""";
45+
String result = compileSrc(src);
46+
System.out.println(result);
47+
}
48+
49+
@Test
50+
public void test3() {
51+
String src = """
52+
func factorial(num: Int)->Int {
53+
var result = 1
54+
while (num > 1)
55+
{
56+
result = result * num
57+
num = num - 1
58+
}
59+
return result
60+
}
61+
""";
62+
String result = compileSrc(src);
63+
System.out.println(result);
64+
}
65+
66+
67+
@Test
68+
public void test4() {
69+
String src = """
70+
func print(a: Int, b: Int, c:Int, d:Int) {}
71+
func example14_66(p: Int, q: Int, r: Int, s: Int, t: Int) {
72+
var i = 1
73+
var j = 1
74+
var k = 1
75+
var l = 1
76+
while (1) {
77+
if (p) {
78+
j = i
79+
if (q) {
80+
l = 2
81+
}
82+
else {
83+
l = 3
84+
}
85+
k = k + 1
86+
}
87+
else {
88+
k = k + 2
89+
}
90+
print(i,j,k,l)
91+
while (1) {
92+
if (r) {
93+
l = l + 4
94+
}
95+
if (!s)
96+
break
97+
}
98+
i = i + 6
99+
if (!t)
100+
break
101+
}
102+
}
103+
""";
104+
String result = compileSrc(src);
105+
System.out.println(result);
106+
}
107+
}

0 commit comments

Comments
 (0)