Skip to content

Some fixes, tests and updated README #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 12, 2025
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
9 changes: 6 additions & 3 deletions optvm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ A VM / Interpreter is provided that can run the generated code.
SSA Form using Dominator Trees. The input to this transformation is regular IR, output is SSA IR.
* Incremental SSA - This method generate SSA IR directly from the AST, using [Braun's algorithm](https://dl.acm.org/doi/10.1007/978-3-642-37051-9_6) - this is integrated into the
[compiler](src/main/java/com/compilerprogramming/ezlang/compiler/CompiledFunction.java) itself and can be enabled using an option.
* [ExitSSA](src/main/java/com/compilerprogramming/ezlang/compiler/ExitSSA.java) - Exits SSA form, using algorithm by Preston Briggs.
* [ExitSSA](src/main/java/com/compilerprogramming/ezlang/compiler/ExitSSA.java) - Exits SSA form - i.e. implements SSA destruction. Two methods are implemented:
* [ExitSSABriggs](src/main/java/com/compilerprogramming/ezlang/compiler/ExitSSABriggs.java) - implements method described by [Preston Briggs](https://dl.acm.org/doi/10.5555/295545.295551).
* [ExitSSABoissinotNoCoalesce](src/main/java/com/compilerprogramming/ezlang/compiler/ExitSSABoissinotNoCoalesce.java) - implements method described by [Benoit Boissinot](https://inria.hal.science/inria-00349925v1/document) -
without the coalescing step. Thus, it is the "naive" approach that resembles Sreedhar's method I.

## Optimizations on SSA Form

* [SparseConditionalConstantPropagation](src/main/java/com/compilerprogramming/ezlang/compiler/SparseConditionalConstantPropagation.java) - Conditional Constant Propagation on SSA form (SCCP)
* [SparseConditionalConstantPropagation](src/main/java/com/compilerprogramming/ezlang/compiler/SparseConditionalConstantPropagation.java) - Conditional Constant Propagation on SSA form (SCCP). This is an implementation of the paper [Constant propagation with conditional branches](https://dl.acm.org/doi/10.1145/103135.103136).
* [ConstantComparisonPropagation](src/main/java/com/compilerprogramming/ezlang/compiler/ConstantComparisonPropagation.java) - Detects equals and not equals against constants within conditionals,
and inserts scoped variables with appropriately specialized type within the dominated blocks, so that a second pass of SCCP can further optimize code.
* [SSAEdges](src/main/java/com/compilerprogramming/ezlang/compiler/SSAEdges.java) - SSAEdges are def-use chains used by SCCP algorithm, and also generated during incremental SSA construction using Braun's method.
Expand All @@ -70,7 +73,7 @@ unlimited amount of those.
* [InterferenceGraphBuilder](src/main/java/com/compilerprogramming/ezlang/compiler/InterferenceGraphBuilder.java) - Constructs an InterferenceGraph for a set
of basic bocks, using basic block level liveness information as a starting point for calculating instruction level liveness.
* [ChaitinGraphColoringRegisterAllocator](src/main/java/com/compilerprogramming/ezlang/compiler/ChaitinGraphColoringRegisterAllocator.java) - basic
Chaitin Graph Coloring Register Allocator. Since our target machine here is an abstract machine, we do not really needing spilling support
[Chaitin Graph Coloring Register Allocator](https://web.eecs.umich.edu/~mahlke/courses/583f12/reading/chaitin82.pdf) without spilling. Since our target machine here is an abstract machine, we do not really need spilling support
as we can size each function's stack frame to accommodate the number of registers needed such that each register is really a slot in the stack
frame. But we will eventually simulate an abstract machine with a limited set of registers and a separate stack frame.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class CompiledFunction {
public boolean hasLiveness;
private final IncrementalSSA issa;

private StringBuilder dumpTarget;

/**
* We essentially do a form of abstract interpretation as we generate
* the bytecode instructions. For this purpose we use a virtual operand stack.
Expand Down Expand Up @@ -72,7 +74,9 @@ public CompiledFunction(EZType.EZTypeFunction functionType, TypeDictionary typeD
issa.finish(null);
this.frameSlots = registerPool.numRegisters();
}

public void setDumpTarget(StringBuilder dumpTarget) {
this.dumpTarget = dumpTarget;
}
private void generateArgInstructions(Scope scope) {
if (scope.isFunctionParameterScope) {
for (Symbol symbol: scope.getLocalSymbols()) {
Expand Down Expand Up @@ -814,8 +818,14 @@ public StringBuilder toStr(StringBuilder sb, boolean verbose) {
}

public void dumpIR(boolean verbose, String title) {
System.out.println(title);
System.out.println(toStr(new StringBuilder(), verbose));
if (dumpTarget != null) {
dumpTarget.append(title).append("\n");
toStr(dumpTarget,verbose);
}
else {
System.out.println(title);
System.out.println(toStr(new StringBuilder(), verbose));
}
}

public void livenessAnalysis() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ public ExitSSABoissinotNoCoalesce(CompiledFunction function, EnumSet<Options> op
allBlocks = function.getBlocks();
init();
makeConventionalSSA();
if (options.contains(Options.DUMP_SSA_TO_CSSA)) function.dumpIR(false, "After converting from SSA to CSSA");
removePhis();
if (options.contains(Options.DUMP_CSSA_PHI_REMOVAL)) function.dumpIR(false, "After removing phis from CSSA");
sequenceParallelCopies();
function.isSSA = false;
if (options.contains(Options.DUMP_POST_SSA_IR)) function.dumpIR(false, "After exiting SSA");
if (options.contains(Options.DUMP_POST_SSA_IR)) function.dumpIR(false, "After exiting SSA (Boissinot method)");
}

private void init() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public boolean interfere(Integer from, Integer to) {
public void rename(Integer source, Integer target) {
// Move all interferences
var fromSet = edges.remove(source);
if (fromSet == null) {
// FIXME figure out why
// Test case testSSA21 / when run using Boissinot SSA Destruction without coalescing
// This is eq() function in mergesort test case
return;
}
var toSet = edges.get(target);
if (toSet == null) {
//throw new RuntimeException("Cannot find edge " + target + " from " + source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ public enum Options {
DUMP_CCP_POSTAPPLY,
DUMP_SSA_LIVENESS,
DUMP_SSA_DOMTREE,
DUMP_SSA_TO_CSSA,
DUMP_CSSA_PHI_REMOVAL,
DUMP_POST_SSA_IR,
DUMP_INTERFERENCE_GRAPH,
DUMP_CHAITIN_COALESCE,
DUMP_POST_CHAITIN_IR;

public static final EnumSet<Options> NONE = EnumSet.noneOf(Options.class);
public static final EnumSet<Options> OPT = EnumSet.of(Options.OPTIMIZE,Options.SCCP,Options.CCP,Options.REGALLOC);
public static final EnumSet<Options> OPT_B = EnumSet.of(Options.OPTIMIZE,Options.SCCP,Options.CCP,Options.REGALLOC,Options.SSA_DESTRUCTION_BOISSINOT_NOCOALESCE);
public static final EnumSet<Options> OPT_ISSA = EnumSet.of(Options.OPTIMIZE,Options.ISSA,Options.SCCP,Options.CCP,Options.REGALLOC);
public static final EnumSet<Options> OPT_ISSA_B = EnumSet.of(Options.OPTIMIZE,Options.ISSA,Options.SCCP,Options.CCP,Options.REGALLOC,Options.SSA_DESTRUCTION_BOISSINOT_NOCOALESCE);
public static final EnumSet<Options> VERBOSE = EnumSet.range(DUMP_INITIAL_IR, DUMP_POST_CHAITIN_IR);
public static final EnumSet<Options> OPT_VERBOSE = EnumSet.range(OPTIMIZE, DUMP_POST_CHAITIN_IR);
}
Loading