Skip to content

Commit 4a10677

Browse files
Sparse Conditional Constant Propagation
1 parent d1a68fa commit 4a10677

File tree

8 files changed

+637
-0
lines changed

8 files changed

+637
-0
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public BasicBlock(int bid, BasicBlock... preds) {
9696
}
9797
public void add(Instruction instruction) {
9898
instructions.add(instruction);
99+
instruction.block = this;
99100
}
100101
public void addSuccessor(BasicBlock successor) {
101102
successors.add(successor);
@@ -120,6 +121,7 @@ public void insertPhiFor(Register var) {
120121
inputs.add(var);
121122
Instruction.Phi phi = new Instruction.Phi(var, inputs);
122123
instructions.add(0, phi);
124+
phi.block = this;
123125
}
124126
public List<Instruction.Phi> phis() {
125127
List<Instruction.Phi> list = new ArrayList<>();

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

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ else if (virtualStack.size() > 1)
127127

128128
public void code(Instruction instruction) {
129129
currentBlock.add(instruction);
130+
instruction.block = currentBlock;
130131
}
131132

132133
private void compileStatement(AST.Stmt statement) {

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

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public abstract class Instruction {
2929
public final int opcode;
3030
public Operand.RegisterOperand def;
3131
public Operand[] uses;
32+
public BasicBlock block;
3233

3334
public Instruction(int opcode, Operand... uses) {
3435
this.opcode = opcode;

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

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public class Optimizer {
44

55
public void optimize(CompiledFunction function) {
66
new EnterSSA(function);
7+
new SparseConditionalConstantPropagation().constantPropagation(function);
78
new ExitSSA(function);
89
new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64);
910
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.compilerprogramming.ezlang.compiler;
2+
3+
import com.compilerprogramming.ezlang.exceptions.CompilerException;
4+
5+
import java.util.ArrayList;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
/**
11+
* SSA Edges are connections from the unique point where a variable is
12+
* given a value to a use of that variable. SSA edges are essentially
13+
* def-use chains in the SSA program.
14+
*/
15+
public class SSAEdges {
16+
17+
public static final class SSADef {
18+
public final Register register;
19+
public final Instruction instruction;
20+
public final List<Instruction> useList;
21+
22+
public SSADef(Register register, Instruction instruction) {
23+
this.register = register;
24+
this.instruction = instruction;
25+
this.useList = new ArrayList<>();
26+
}
27+
}
28+
29+
public static Map<Integer, SSADef> buildDefUseChains(CompiledFunction function) {
30+
31+
if (!function.isSSA) throw new CompilerException("Function must be in SSA form");
32+
33+
Map<Integer, SSADef> defUseChains = new HashMap<>();
34+
recordDefs(function, defUseChains);
35+
recordUses(function, defUseChains);
36+
37+
return defUseChains;
38+
}
39+
40+
private static void recordDefs(CompiledFunction function, Map<Integer, SSADef> defUseChains) {
41+
for (BasicBlock block : function.getBlocks()) {
42+
for (Instruction instruction : block.instructions) {
43+
if (instruction instanceof Instruction.Phi phi) {
44+
recordDef(defUseChains, phi.value(), instruction);
45+
}
46+
else if (instruction.definesVar()) {
47+
recordDef(defUseChains, instruction.def(), instruction);
48+
}
49+
}
50+
}
51+
}
52+
53+
private static void recordUses(CompiledFunction function, Map<Integer, SSADef> defUseChains) {
54+
for (BasicBlock block : function.getBlocks()) {
55+
for (Instruction instruction : block.instructions) {
56+
if (instruction instanceof Instruction.Phi phi) {
57+
recordUses(defUseChains, phi.inputs, block, instruction);
58+
}
59+
else {
60+
List<Register> uses = instruction.uses();
61+
if (!uses.isEmpty())
62+
recordUses(defUseChains, uses.toArray(new Register[uses.size()]), block, instruction);
63+
}
64+
}
65+
}
66+
}
67+
68+
private static void recordUses(Map<Integer, SSADef> defUseChains, Register[] inputs, BasicBlock block, Instruction instruction) {
69+
for (Register register : inputs) {
70+
SSADef def = defUseChains.get(register.id);
71+
def.useList.add(instruction);
72+
}
73+
}
74+
75+
private static void recordDef(Map<Integer, SSADef> defUseChains, Register value, Instruction instruction) {
76+
if (defUseChains.containsKey(value.id))
77+
throw new CompilerException("Register already defined, invalid multiple definition in SSA");
78+
defUseChains.put(value.id, new SSADef(value, instruction));
79+
}
80+
}

0 commit comments

Comments
 (0)