Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public BasicBlock(int bid, BasicBlock... preds) {
}
public void add(Instruction instruction) {
instructions.add(instruction);
instruction.block = this;
}
public void addSuccessor(BasicBlock successor) {
successors.add(successor);
Expand All @@ -120,6 +121,7 @@ public void insertPhiFor(Register var) {
inputs.add(var);
Instruction.Phi phi = new Instruction.Phi(var, inputs);
instructions.add(0, phi);
phi.block = this;
}
public List<Instruction.Phi> phis() {
List<Instruction.Phi> list = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ else if (virtualStack.size() > 1)

public void code(Instruction instruction) {
currentBlock.add(instruction);
instruction.block = currentBlock;
}

private void compileStatement(AST.Stmt statement) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public abstract class Instruction {
public final int opcode;
public Operand.RegisterOperand def;
public Operand[] uses;
public BasicBlock block;

public Instruction(int opcode, Operand... uses) {
this.opcode = opcode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class Optimizer {

public void optimize(CompiledFunction function) {
new EnterSSA(function);
new SparseConditionalConstantPropagation().constantPropagation(function);
new ExitSSA(function);
new ChaitinGraphColoringRegisterAllocator().assignRegisters(function, 64);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.compilerprogramming.ezlang.compiler;

import com.compilerprogramming.ezlang.exceptions.CompilerException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* SSA Edges are connections from the unique point where a variable is
* given a value to a use of that variable. SSA edges are essentially
* def-use chains in the SSA program.
*/
public class SSAEdges {

public static final class SSADef {
public final Register register;
public final Instruction instruction;
public final List<Instruction> useList;

public SSADef(Register register, Instruction instruction) {
this.register = register;
this.instruction = instruction;
this.useList = new ArrayList<>();
}
}

public static Map<Integer, SSADef> buildDefUseChains(CompiledFunction function) {

if (!function.isSSA) throw new CompilerException("Function must be in SSA form");

Map<Integer, SSADef> defUseChains = new HashMap<>();
recordDefs(function, defUseChains);
recordUses(function, defUseChains);

return defUseChains;
}

private static void recordDefs(CompiledFunction function, Map<Integer, SSADef> defUseChains) {
for (BasicBlock block : function.getBlocks()) {
for (Instruction instruction : block.instructions) {
if (instruction instanceof Instruction.Phi phi) {
recordDef(defUseChains, phi.value(), instruction);
}
else if (instruction.definesVar()) {
recordDef(defUseChains, instruction.def(), instruction);
}
}
}
}

private static void recordUses(CompiledFunction function, Map<Integer, SSADef> defUseChains) {
for (BasicBlock block : function.getBlocks()) {
for (Instruction instruction : block.instructions) {
if (instruction instanceof Instruction.Phi phi) {
recordUses(defUseChains, phi.inputs, block, instruction);
}
else {
List<Register> uses = instruction.uses();
if (!uses.isEmpty())
recordUses(defUseChains, uses.toArray(new Register[uses.size()]), block, instruction);
}
}
}
}

private static void recordUses(Map<Integer, SSADef> defUseChains, Register[] inputs, BasicBlock block, Instruction instruction) {
for (Register register : inputs) {
SSADef def = defUseChains.get(register.id);
def.useList.add(instruction);
}
}

private static void recordDef(Map<Integer, SSADef> defUseChains, Register value, Instruction instruction) {
if (defUseChains.containsKey(value.id))
throw new CompilerException("Register already defined, invalid multiple definition in SSA");
defUseChains.put(value.id, new SSADef(value, instruction));
}
}
Loading
Loading