diff --git a/src/dk/camelot64/kickc/Compiler.java b/src/dk/camelot64/kickc/Compiler.java index 1d72dc477..a1ddc8e8d 100644 --- a/src/dk/camelot64/kickc/Compiler.java +++ b/src/dk/camelot64/kickc/Compiler.java @@ -16,13 +16,13 @@ public class Compiler { public static class CompilationResult { private AsmProgram asmProgram; private ControlFlowGraph graph; - private ProgramScope symbols; + private ProgramScope scope; private CompileLog log; - public CompilationResult(AsmProgram asmProgram, ControlFlowGraph graph, ProgramScope symbols, CompileLog log) { + public CompilationResult(AsmProgram asmProgram, ControlFlowGraph graph, ProgramScope scope, CompileLog log) { this.asmProgram = asmProgram; this.graph = graph; - this.symbols = symbols; + this.scope = scope; this.log = log; } @@ -34,8 +34,8 @@ public class Compiler { return graph; } - public ProgramScope getSymbols() { - return symbols; + public ProgramScope getScope() { + return scope; } public CompileLog getLog() { @@ -49,7 +49,7 @@ public class Compiler { KickCParser.FileContext file = pass0ParseInput(input, log); Program program = pass1GenerateSSA(file, log); pass2OptimizeSSA(program, log); - pass3IntervalAnalysis(program, log); + pass3LiveRangeAnalysis(program, log); AsmProgram asmProgram = pass4GenerateAsm(program, log); pass5OptimizeAsm(asmProgram, log); @@ -98,7 +98,7 @@ public class Compiler { } - private void pass3IntervalAnalysis(Program program, CompileLog log) { + private void pass3LiveRangeAnalysis(Program program, CompileLog log) { Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program, log); pass3BlockSequencePlanner.plan(); @@ -110,8 +110,8 @@ public class Compiler { log.append(program.getGraph().toString(program.getScope())); pass2AssertSSA(program, log); - Pass3IdentifyAliveRanges pass3IdentifyAliveRanges = new Pass3IdentifyAliveRanges(program, log); - pass3IdentifyAliveRanges.findLiveRanges(); + Pass3IdentifyLiveRanges pass3IdentifyLiveRanges = new Pass3IdentifyLiveRanges(program, log); + pass3IdentifyLiveRanges.findLiveRanges(); log.append("CONTROL FLOW GRAPH - LIVE RANGES"); log.append(program.getGraph().toString(program.getScope())); pass2AssertSSA(program, log); @@ -121,11 +121,14 @@ public class Compiler { Pass2CullEmptyBlocks cullEmptyBlocks = new Pass2CullEmptyBlocks(program, log); cullEmptyBlocks.optimize(); pass3BlockSequencePlanner.plan(); - pass3IdentifyAliveRanges.findLiveRanges(); + pass3IdentifyLiveRanges.findLiveRanges(); log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED"); log.append(program.getGraph().toString(program.getScope())); pass2AssertSSA(program, log); + Pass3LoopAnalysis pass3LoopAnalysis = new Pass3LoopAnalysis(program, log); + pass3LoopAnalysis.detectLoops(); + } public void pass2OptimizeSSA(Program program, CompileLog log) { diff --git a/src/dk/camelot64/kickc/TODO.txt b/src/dk/camelot64/kickc/TODO.txt index 1e5857bf2..4a5601a10 100644 --- a/src/dk/camelot64/kickc/TODO.txt +++ b/src/dk/camelot64/kickc/TODO.txt @@ -17,13 +17,10 @@ Features + Add ++/-- incrementing/decrementing operators. Register Allocation -- Matrix Phi operation (instead of separate statements) - Safe-Copy based SSA deconstruction - Optimize phi transitions by ensuring that identical phi-transitions with regards to register allocation are collected into a single transition. - Optimize by finding optimal sequence for multiple phi assignments in entry-segments. -- Phi Lifting - Interval Analysis (variable liveness intervals) -- PhiLifting & PhiMemCoalesce (http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf) - ComputeLoopNestDepth(b) - Assign loop nesting levels to blocks. - ComputeRegisterPreference(v), ComputeWeight(v) - CalculateClobbering(i) @@ -32,13 +29,16 @@ Register Allocation - Maybe register preference should also incorporate the types of operations that can be effectively performed with the register? (Maybe based on fragment cost?) - Implement a register allocation (coloring) algorithm using by liveness intervals, preferences, weights & clobbering information. - Optimize register allocation by combining with knowledge of ASM program cost (bytes/cycles) and different ASM fragments with different clobbering. ++ Matrix Phi operation (instead of separate statements) ++ Phi Lifting ++ PhiLifting & PhiMemCoalesce (http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf) Process/Code Structure Improvement -- Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks) - Refactor Expression Operator Implementation & Evaluation into one class per operator - Improve error messages to give better context - Offer to compile resulting ASM with KickAssembler + Implemenent Assertions for the output of different phases (ensuring that the result of the phase is consistent) ++ Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks) Testing - Test that the parse tree for specific KC syntax is as expected. Use a print function for the parse tree to generate output for comparison. diff --git a/src/dk/camelot64/kickc/icl/LiveRange.java b/src/dk/camelot64/kickc/icl/LiveRange.java index 4702d1f31..41e506780 100644 --- a/src/dk/camelot64/kickc/icl/LiveRange.java +++ b/src/dk/camelot64/kickc/icl/LiveRange.java @@ -66,7 +66,7 @@ public class LiveRange { private Integer getIndex(Statement statement) { Integer index = statement.getIndex(); if (index == null) { - throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3IdentifyAliveRanges.generateStatementIndexes)."); + throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3IdentifyLiveRanges.generateStatementIndexes)."); } return index; } diff --git a/src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java b/src/dk/camelot64/kickc/passes/Pass3IdentifyLiveRanges.java similarity index 99% rename from src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java rename to src/dk/camelot64/kickc/passes/Pass3IdentifyLiveRanges.java index 789f37688..b873bada2 100644 --- a/src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java +++ b/src/dk/camelot64/kickc/passes/Pass3IdentifyLiveRanges.java @@ -11,12 +11,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class Pass3IdentifyAliveRanges { +public class Pass3IdentifyLiveRanges { private final Program program; private final CompileLog log; - public Pass3IdentifyAliveRanges(Program program, CompileLog log) { + public Pass3IdentifyLiveRanges(Program program, CompileLog log) { this.program = program; this.log = log; } diff --git a/src/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java b/src/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java new file mode 100644 index 000000000..8feb5346f --- /dev/null +++ b/src/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java @@ -0,0 +1,222 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.icl.ControlFlowBlock; +import dk.camelot64.kickc.icl.LabelRef; +import dk.camelot64.kickc.icl.Program; + +import java.util.*; + +/** + * Finds loops and nested loops in the control flow graph + */ +public class Pass3LoopAnalysis { + + private Program program; + private CompileLog log; + + public Pass3LoopAnalysis(Program program, CompileLog log) { + this.program = program; + this.log = log; + } + + public Program getProgram() { + return program; + } + + public CompileLog getLog() { + return log; + } + + public void detectLoops() { + + GraphDominators graphDominators = analyseDominators(); + + + } + + /** + * Analyse the control flow graph to find dominators for all blocks. + *
+ * Definition: d dom i if all paths from entry to node i include d + *
+ * See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
+ *
+ * @return The graph dominators
+ */
+ private GraphDominators analyseDominators() {
+ GraphDominators graphDominators = new GraphDominators();
+
+ // Initialize dominators: Dom[first]={first}, Dom[block]={all}
+ LabelRef firstBlock = program.getGraph().getFirstBlock().getLabel();
+ BlockDominators firstDominators = graphDominators.addDominators(firstBlock);
+ firstDominators.add(firstBlock);
+ List