diff --git a/src/dk/camelot64/kickc/Compiler.java b/src/dk/camelot64/kickc/Compiler.java index 31dca207c..da7242566 100644 --- a/src/dk/camelot64/kickc/Compiler.java +++ b/src/dk/camelot64/kickc/Compiler.java @@ -101,22 +101,29 @@ public class Compiler { Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program, log); pass3BlockSequencePlanner.plan(); - //Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log); - //pass3PhiLifting.perform(); - //pass3BlockSequencePlanner.plan(); - - //log.append("CONTROL FLOW GRAPH - PHI LIFTED"); - //log.append(program.getGraph().toString(program.getScope())); - //pass2AssertSSA(program, log); + Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log); + pass3PhiLifting.perform(); + pass3BlockSequencePlanner.plan(); + log.append("CONTROL FLOW GRAPH - PHI LIFTED"); + log.append(program.getGraph().toString(program.getScope())); + pass2AssertSSA(program, log); Pass3IdentifyAliveRanges pass3IdentifyAliveRanges = new Pass3IdentifyAliveRanges(program, log); pass3IdentifyAliveRanges.findLiveRanges(); - - log.append("CONTROL FLOW GRAPH - LIVE RANGES"); log.append(program.getGraph().toString(program.getScope())); pass2AssertSSA(program, log); + Pass3PhiMemCoalesce pass3PhiMemCoalesce = new Pass3PhiMemCoalesce(program, log); + pass3PhiMemCoalesce.optimize(); + Pass2CullEmptyBlocks cullEmptyBlocks = new Pass2CullEmptyBlocks(program, log); + cullEmptyBlocks.optimize(); + pass3BlockSequencePlanner.plan(); + pass3IdentifyAliveRanges.findLiveRanges(); + log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED"); + log.append(program.getGraph().toString(program.getScope())); + pass2AssertSSA(program, log); + } public void pass2OptimizeSSA(Program program, CompileLog log) { diff --git a/src/dk/camelot64/kickc/icl/LiveRange.java b/src/dk/camelot64/kickc/icl/LiveRange.java index 1b5f48bc7..4702d1f31 100644 --- a/src/dk/camelot64/kickc/icl/LiveRange.java +++ b/src/dk/camelot64/kickc/icl/LiveRange.java @@ -109,6 +109,37 @@ public class LiveRange { return true; } + /** + * Determines if this live range overlaps another live range + * @param other The other live range + * @return true if there is an overlap + */ + public boolean overlaps(LiveRange other) { + if(this.getMaxIndex()==-1 || other.getMaxIndex()==-1) { + return false; + } + int maxIdx = getMaxIndex(); + for(int i=0;i<=maxIdx; i++) { + if(contains(i) && other.contains(i)) { + return true; + } + } + return false; + } + + /** + * Adds another live range to this one - extending this live range to include the other one. + * @param other The live range to add + */ + public void add(LiveRange other) { + int otherMaxIndex = other.getMaxIndex(); + for(int i=0;i<=otherMaxIndex; i++) { + if(other.contains(i)) { + add(i); + } + } + } + /** * Determines if the live range contains a statement * @param statement The statement to examine @@ -136,5 +167,16 @@ public class LiveRange { return false; } + /** + * Get the maximal index contained in the live range + * @return The max index. -1 if the range is empty. + */ + int getMaxIndex() { + if(intervals.isEmpty()) { + return -1; + } + return intervals.get(intervals.size()-1).lastStatementIdx; + } + } diff --git a/src/dk/camelot64/kickc/icl/VariableLiveRanges.java b/src/dk/camelot64/kickc/icl/VariableLiveRanges.java index ecce3ab84..788394844 100644 --- a/src/dk/camelot64/kickc/icl/VariableLiveRanges.java +++ b/src/dk/camelot64/kickc/icl/VariableLiveRanges.java @@ -44,4 +44,13 @@ public class VariableLiveRanges { return aliveVars; } + /** + * Get the alive range of a variable + * @param variable The variable reference + * @return The alive range for the variable + */ + public LiveRange getLiveRange(VariableRef variable) { + return liveRanges.get(variable); + } + } diff --git a/src/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java b/src/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java new file mode 100644 index 000000000..86e42df91 --- /dev/null +++ b/src/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java @@ -0,0 +1,239 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.icl.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Eliminate virtual variables introduced by PhiLifting if they do not have overlapping live ranges with other phi equivalent variables. + * (This pass requires variable alive ranges). + *

+ * See http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf + */ +public class Pass3PhiMemCoalesce extends Pass2SsaOptimization { + + public Pass3PhiMemCoalesce(Program program, CompileLog log) { + super(program, log); + } + + @Override + public boolean optimize() { + PhiEquivalenceClassInitializer phiEquivalenceClassInitializer = new PhiEquivalenceClassInitializer(); + phiEquivalenceClassInitializer.visitGraph(getGraph()); + ProgramPhiEquivalenceClasses phiEquivalenceClasses = phiEquivalenceClassInitializer.getPhiEquivalenceClasses(); + log.append("Created " +phiEquivalenceClasses.size()+ " initial phi equivalence classes"); + PhiMemCoalescer phiMemCoalescer = new PhiMemCoalescer(phiEquivalenceClasses); + phiMemCoalescer.visitGraph(getGraph()); + removeAssignments(phiMemCoalescer.getRemove()); + replaceVariables(phiMemCoalescer.getReplace()); + deleteVariables(phiMemCoalescer.getRemove()); + log.append("Coalesced down to " +phiEquivalenceClasses.size()+ " phi equivalence classes"); + return false; + } + + /** Coalesces phi equivalence classes when they do not overlap based on assignments to variables in phi statements. */ + private class PhiMemCoalescer extends ControlFlowGraphBaseVisitor { + + private ProgramPhiEquivalenceClasses phiEquivalenceClasses; + private List remove; + private Map replace; + + public PhiMemCoalescer(ProgramPhiEquivalenceClasses phiEquivalenceClasses) { + this.phiEquivalenceClasses = phiEquivalenceClasses; + this.remove = new ArrayList<>(); + this.replace = new HashMap<>(); + } + + public List getRemove() { + return remove; + } + + public Map getReplace() { + return replace; + } + + @Override + public Void visitAssignment(StatementAssignment assignment) { + if (assignment.getlValue() instanceof VariableRef) { + PhiEquivalenceClass lValEquivalenceClass = + phiEquivalenceClasses.getPhiEquivalenceClass((VariableRef) assignment.getlValue()); + if (lValEquivalenceClass != null && assignment.getOperator() == null && assignment.getrValue1() == null && assignment.getrValue2() instanceof VariableRef) { + // Found copy assignment to a variable in an equivalence class - attempt to coalesce + VariableRef assignVar = (VariableRef) assignment.getrValue2(); + PhiEquivalenceClass assignVarEquivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(assignVar); + if(lValEquivalenceClass.equals(assignVarEquivalenceClass)) { + remove.add((VariableRef) assignment.getlValue()); + replace.put((VariableRef) assignment.getlValue(), assignVar); + log.append("Coalesced (already) "+assignment); + } else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) { + lValEquivalenceClass.addAll(assignVarEquivalenceClass); + phiEquivalenceClasses.remove(assignVarEquivalenceClass); + remove.add((VariableRef) assignment.getlValue()); + replace.put((VariableRef) assignment.getlValue(), assignVar); + log.append("Coalesced "+assignment); + } else { + log.append("Not coalescing "+assignment); + } + } + } + return null; + } + + } + + + /** Creates initial phi equivalence classes from program phi statements.*/ + private class PhiEquivalenceClassInitializer extends ControlFlowGraphBaseVisitor { + + private ProgramPhiEquivalenceClasses phiEquivalenceClasses; + + public PhiEquivalenceClassInitializer() { + this.phiEquivalenceClasses = new ProgramPhiEquivalenceClasses(); + } + + @Override + public Void visitPhiBlock(StatementPhiBlock phi) { + for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { + VariableRef variable = phiVariable.getVariable(); + PhiEquivalenceClass equivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(variable); + for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + if(!(phiRValue.getrValue() instanceof Constant)) { + VariableRef phiRVar = (VariableRef) phiRValue.getrValue(); + equivalenceClass.addVariable(phiRVar); + } + } + } + return null; + } + + public ProgramPhiEquivalenceClasses getPhiEquivalenceClasses() { + return phiEquivalenceClasses; + } + } + + /** The entire set of phi equivalence classes in the pgogram. */ + public class ProgramPhiEquivalenceClasses { + + List equivalenceClasses; + + public ProgramPhiEquivalenceClasses() { + this.equivalenceClasses = new ArrayList<>(); + } + + /** + * Get the phi equivalence class for a specific variable. + * If the equivalence class does not exist it is created. + * + * @param variable The variable + * @return The existing or new phi equivalence class + */ + public PhiEquivalenceClass getOrCreateEquivalenceClass(VariableRef variable) { + PhiEquivalenceClass equivalenceClass1 = getPhiEquivalenceClass(variable); + if (equivalenceClass1 != null) return equivalenceClass1; + // Not found - create it + PhiEquivalenceClass equivalenceClass = new PhiEquivalenceClass(); + equivalenceClasses.add(equivalenceClass); + equivalenceClass.addVariable(variable); + return equivalenceClass; + } + + /** + * Get the phi equivalence class for a specific variable. + * + * @param variable The variable + * @return The existing phi equivalence class. null if no equivalence class contains the variable. + */ + private PhiEquivalenceClass getPhiEquivalenceClass(VariableRef variable) { + for (PhiEquivalenceClass equivalenceClass : equivalenceClasses) { + if(equivalenceClass.contains(variable)) { + return equivalenceClass; + } + } + return null; + } + + + public int size() { + return equivalenceClasses.size(); + } + + public void remove(PhiEquivalenceClass equivalenceClass) { + equivalenceClasses.remove(equivalenceClass); + } + } + + /** + * A phi equivalence class contains all varialbes connected in by phi statements. + * In the phi statement va = phi(vb, vc) all 3 variables are in the same equivalence class. + * The equivalence class is the closure over all phi statements in the program. + * The set of equivalence classes is a disjoint partition of all variables uses in phi statements + * (ie. those variables crossing non-trivial block transitions). + *

+ * See http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf + **/ + public class PhiEquivalenceClass { + + /** The variables of the equivalence class. */ + List variables; + + /** The combined live range of the variables. */ + LiveRange classLiveRange; + + public PhiEquivalenceClass() { + this.variables = new ArrayList<>(); + this.classLiveRange = new LiveRange(); + } + + /** + * Add a variable to the equivalence class + * @param variable The variable to add + */ + public void addVariable(VariableRef variable) { + VariableLiveRanges liveRanges = getSymbols().getLiveRanges(); + LiveRange varLiveRange = liveRanges.getLiveRange(variable); + if(classLiveRange.overlaps(varLiveRange)) { + throw new RuntimeException("Compilation error! Variable live range overlaps phi equivalence class live range. "+variable); + } + classLiveRange.add(varLiveRange); + variables.add(variable); + } + + /** + * Determines if the phi equivalence class contains a variable + * @param variable The variable to look for + * @return true if the equivalence class contains the variable + */ + public boolean contains(VariableRef variable) { + return variables.contains(variable); + } + + public LiveRange getLiveRange() { + return classLiveRange; + } + + public void addAll(PhiEquivalenceClass other) { + variables.addAll(other.variables); + classLiveRange.add(other.classLiveRange); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PhiEquivalenceClass that = (PhiEquivalenceClass) o; + + return variables.equals(that.variables); + } + + @Override + public int hashCode() { + return variables.hashCode(); + } + } + +} diff --git a/src/dk/camelot64/kickc/test/ref/bresenham.log b/src/dk/camelot64/kickc/test/ref/bresenham.log index bec4dc83b..a3e2fa7b8 100644 --- a/src/dk/camelot64/kickc/test/ref/bresenham.log +++ b/src/dk/camelot64/kickc/test/ref/bresenham.log @@ -844,6 +844,52 @@ Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 Multiple usages for variable. Not optimizing sub-constant (byte) y#2 Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 Block Sequence Planned @BEGIN @1 @3 @END @2 +Added new block during phi lifting @7(between @3 and @1) +Added new block during phi lifting @8(between @1 and @3) +Block Sequence Planned @BEGIN @1 @8 @3 @END @7 @2 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @7 @BEGIN + (byte) y#2 ← phi( @7/(byte~) y#5 @BEGIN/(byte) 0 ) + (byte) e#3 ← phi( @7/(byte~) e#6 @BEGIN/(byte) 12 ) + (byte) x#2 ← phi( @7/(byte~) x#5 @BEGIN/(byte) 0 ) + (byte*) cursor#3 ← phi( @7/(byte*~) cursor#6 @BEGIN/(word) 1024 ) + *((byte*) cursor#3) ← (byte) 81 + (byte) x#1 ← (byte) x#2 + (byte) 1 + (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 + (byte) e#1 ← (byte) e#3 + (byte) 24 + if((byte) 39<(byte) e#1) goto @2 + to:@8 +@8: from @1 + (byte*~) cursor#7 ← (byte*) cursor#1 + (byte~) e#7 ← (byte) e#1 + (byte~) y#6 ← (byte) y#2 + to:@3 +@3: from @2 @8 + (byte) y#4 ← phi( @8/(byte~) y#6 @2/(byte~) y#7 ) + (byte) e#5 ← phi( @8/(byte~) e#7 @2/(byte~) e#8 ) + (byte*) cursor#5 ← phi( @8/(byte*~) cursor#7 @2/(byte*~) cursor#8 ) + if((byte) x#1<(byte) 40) goto @7 + to:@END +@END: from @3 +@7: from @3 + (byte*~) cursor#6 ← (byte*) cursor#5 + (byte~) x#5 ← (byte) x#1 + (byte~) e#6 ← (byte) e#5 + (byte~) y#5 ← (byte) y#4 + to:@1 +@2: from @1 + (byte) y#1 ← (byte) y#2 + (byte) 1 + (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 + (byte) e#2 ← (byte) e#1 - (byte) 39 + (byte*~) cursor#8 ← (byte*) cursor#2 + (byte~) e#8 ← (byte) e#2 + (byte~) y#7 ← (byte) y#1 + to:@3 + +Propagating live ranges... +Propagating live ranges... Propagating live ranges... Propagating live ranges... Propagating live ranges... @@ -851,6 +897,68 @@ Propagating live ranges... Propagating live ranges... Propagating live ranges... CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @7 @BEGIN + [0] (byte) y#2 ← phi( @7/(byte~) y#5 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) e#3 ← phi( @7/(byte~) e#6 @BEGIN/(byte) 12 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) x#2 ← phi( @7/(byte~) x#5 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte*) cursor#3 ← phi( @7/(byte*~) cursor#6 @BEGIN/(word) 1024 ) [ cursor#3 x#2 e#3 y#2 ] + [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] + [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ cursor#3 e#3 y#2 x#1 ] + [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ e#3 cursor#1 y#2 x#1 ] + [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ e#1 cursor#1 y#2 x#1 ] + [5] if((byte) 39<(byte) e#1) goto @2 [ e#1 cursor#1 y#2 x#1 ] + to:@8 +@8: from @1 + [6] (byte*~) cursor#7 ← (byte*) cursor#1 [ e#1 y#2 cursor#7 x#1 ] + [7] (byte~) e#7 ← (byte) e#1 [ y#2 cursor#7 e#7 x#1 ] + [8] (byte~) y#6 ← (byte) y#2 [ cursor#7 e#7 y#6 x#1 ] + to:@3 +@3: from @2 @8 + [9] (byte) y#4 ← phi( @8/(byte~) y#6 @2/(byte~) y#7 ) [ x#1 cursor#5 e#5 y#4 ] + [9] (byte) e#5 ← phi( @8/(byte~) e#7 @2/(byte~) e#8 ) [ x#1 cursor#5 e#5 y#4 ] + [9] (byte*) cursor#5 ← phi( @8/(byte*~) cursor#7 @2/(byte*~) cursor#8 ) [ x#1 cursor#5 e#5 y#4 ] + [10] if((byte) x#1<(byte) 40) goto @7 [ x#1 cursor#5 e#5 y#4 ] + to:@END +@END: from @3 +@7: from @3 + [11] (byte*~) cursor#6 ← (byte*) cursor#5 [ cursor#6 x#1 e#5 y#4 ] + [12] (byte~) x#5 ← (byte) x#1 [ cursor#6 x#5 e#5 y#4 ] + [13] (byte~) e#6 ← (byte) e#5 [ cursor#6 x#5 e#6 y#4 ] + [14] (byte~) y#5 ← (byte) y#4 [ cursor#6 x#5 e#6 y#5 ] + to:@1 +@2: from @1 + [15] (byte) y#1 ← (byte) y#2 + (byte) 1 [ e#1 cursor#1 x#1 y#1 ] + [16] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ e#1 x#1 cursor#2 y#1 ] + [17] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] + [18] (byte*~) cursor#8 ← (byte*) cursor#2 [ cursor#8 x#1 e#2 y#1 ] + [19] (byte~) e#8 ← (byte) e#2 [ cursor#8 e#8 x#1 y#1 ] + [20] (byte~) y#7 ← (byte) y#1 [ cursor#8 e#8 y#7 x#1 ] + to:@3 + +Created 7 initial phi equivalence classes +Coalesced [6] cursor#7 ← cursor#1 +Coalesced [7] e#7 ← e#1 +Coalesced [8] y#6 ← y#2 +Coalesced [11] cursor#6 ← cursor#5 +Coalesced [12] x#5 ← x#1 +Coalesced [13] e#6 ← e#5 +Coalesced (already) [14] y#5 ← y#4 +Coalesced [18] cursor#8 ← cursor#2 +Coalesced [19] e#8 ← e#2 +Coalesced [20] y#7 ← y#1 +Coalesced down to 4 phi equivalence classes +Culled Empty Block (label) @8 +Culled Empty Block (label) @7 +Block Sequence Planned @BEGIN @1 @3 @END @2 +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED @BEGIN: from to:@1 @1: from @3 @BEGIN diff --git a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log index 7479f40db..d2e115943 100644 --- a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log +++ b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log @@ -3310,6 +3310,149 @@ Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 Multiple usages for variable. Not optimizing sub-constant (byte) plot::i#2 Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return plot plot::@1 plot::@2 plot::@3 plot::@return flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return prepare prepare::@1 prepare::@return +Added new block during phi lifting main::@12(between main::@6 and main::@3) +Added new block during phi lifting plot::@5(between plot::@3 and plot::@1) +Added new block during phi lifting plot::@6(between plot::@2 and plot::@2) +Added new block during phi lifting flip::@7(between flip::@4 and flip::@1) +Added new block during phi lifting flip::@8(between flip::@2 and flip::@2) +Added new block during phi lifting flip::@9(between flip::@3 and flip::@3) +Added new block during phi lifting prepare::@3(between prepare::@1 and prepare::@1) +Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return main::@12 plot plot::@1 plot::@2 plot::@3 plot::@return plot::@5 plot::@6 flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return flip::@9 flip::@7 flip::@8 prepare prepare::@1 prepare::@return prepare::@3 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + call main param-assignment + to:@END +@END: from @BEGIN +main: from @BEGIN + call prepare param-assignment + to:main::@3 +main::@3: from main main::@11 main::@12 main::@3 + (byte) main::c#2 ← phi( main/(byte) 25 main::@12/(byte~) main::c#6 main::@11/(byte) 25 ) + (byte~) main::$1 ← * (word) 53266 + if((byte~) main::$1!=(byte) 254) goto main::@3 + to:main::@4 +main::@4: from main::@3 main::@4 + (byte~) main::$3 ← * (word) 53266 + if((byte~) main::$3!=(byte) 255) goto main::@4 + to:main::@6 +main::@6: from main::@4 + (byte) main::c#1 ← -- (byte) main::c#2 + if((byte) main::c#1!=(byte) 0) goto main::@12 + to:main::@7 +main::@7: from main::@6 + call flip param-assignment + to:main::@10 +main::@10: from main::@7 + call plot param-assignment + to:main::@11 +main::@11: from main::@10 + if(true) goto main::@3 + to:main::@return +main::@return: from main::@11 + return + to:@RETURN +main::@12: from main::@6 + (byte~) main::c#6 ← (byte) main::c#1 + to:main::@3 +plot: from main::@10 + to:plot::@1 +plot::@1: from plot plot::@5 + (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@5/(byte~) plot::y#5 ) + (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@5/(byte*~) plot::line#5 ) + (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@5/(byte~) plot::i#5 ) + (byte~) plot::i#6 ← (byte) plot::i#3 + to:plot::@2 +plot::@2: from plot::@1 plot::@6 + (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@6/(byte~) plot::x#3 ) + (byte) plot::i#2 ← phi( plot::@1/(byte~) plot::i#6 plot::@6/(byte~) plot::i#7 ) + (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 + *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 + (byte) plot::i#1 ← ++ (byte) plot::i#2 + (byte) plot::x#1 ← ++ (byte) plot::x#2 + if((byte) plot::x#1<(byte) 16) goto plot::@6 + to:plot::@3 +plot::@3: from plot::@2 + (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 + (byte) plot::y#1 ← -- (byte) plot::y#2 + if((byte) plot::y#1!=(byte) 0) goto plot::@5 + to:plot::@return +plot::@return: from plot::@3 + return + to:@RETURN +plot::@5: from plot::@3 + (byte~) plot::i#5 ← (byte) plot::i#1 + (byte*~) plot::line#5 ← (byte*) plot::line#1 + (byte~) plot::y#5 ← (byte) plot::y#1 + to:plot::@1 +plot::@6: from plot::@2 + (byte~) plot::i#7 ← (byte) plot::i#1 + (byte~) plot::x#3 ← (byte) plot::x#1 + to:plot::@2 +flip: from main::@7 + to:flip::@1 +flip::@1: from flip flip::@7 + (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@7/(byte~) flip::r#5 ) + (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@7/(byte~) flip::dstIdx#6 ) + (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@7/(byte~) flip::srcIdx#5 ) + (byte~) flip::srcIdx#6 ← (byte) flip::srcIdx#3 + (byte~) flip::dstIdx#7 ← (byte) flip::dstIdx#5 + to:flip::@2 +flip::@2: from flip::@1 flip::@8 + (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@8/(byte~) flip::c#3 ) + (byte) flip::dstIdx#3 ← phi( flip::@1/(byte~) flip::dstIdx#7 flip::@8/(byte~) flip::dstIdx#8 ) + (byte) flip::srcIdx#2 ← phi( flip::@1/(byte~) flip::srcIdx#6 flip::@8/(byte~) flip::srcIdx#7 ) + (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 + *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 + (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 + (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 + (byte) flip::c#1 ← -- (byte) flip::c#2 + if((byte) flip::c#1!=(byte) 0) goto flip::@8 + to:flip::@4 +flip::@4: from flip::@2 + (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 + (byte) flip::r#1 ← -- (byte) flip::r#2 + if((byte) flip::r#1!=(byte) 0) goto flip::@7 + to:flip::@3 +flip::@3: from flip::@4 flip::@9 + (byte) flip::i#2 ← phi( flip::@9/(byte~) flip::i#3 flip::@4/(byte) 0 ) + (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 + *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 + (byte) flip::i#1 ← ++ (byte) flip::i#2 + if((byte) flip::i#1!=(byte) 0) goto flip::@9 + to:flip::@return +flip::@return: from flip::@3 + return + to:@RETURN +flip::@9: from flip::@3 + (byte~) flip::i#3 ← (byte) flip::i#1 + to:flip::@3 +flip::@7: from flip::@4 + (byte~) flip::srcIdx#5 ← (byte) flip::srcIdx#1 + (byte~) flip::dstIdx#6 ← (byte) flip::dstIdx#2 + (byte~) flip::r#5 ← (byte) flip::r#1 + to:flip::@1 +flip::@8: from flip::@2 + (byte~) flip::srcIdx#7 ← (byte) flip::srcIdx#1 + (byte~) flip::dstIdx#8 ← (byte) flip::dstIdx#1 + (byte~) flip::c#3 ← (byte) flip::c#1 + to:flip::@2 +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@3 + (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@3/(byte~) prepare::i#3 ) + *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 + (byte) prepare::i#1 ← ++ (byte) prepare::i#2 + if((byte) prepare::i#1!=(byte) 0) goto prepare::@3 + to:prepare::@return +prepare::@return: from prepare::@1 + return + to:@RETURN +prepare::@3: from prepare::@1 + (byte~) prepare::i#3 ← (byte) prepare::i#1 + to:prepare::@1 + +Propagating live ranges... +Propagating live ranges... Propagating live ranges... Propagating live ranges... Propagating live ranges... @@ -3324,6 +3467,175 @@ CONTROL FLOW GRAPH - LIVE RANGES [0] call main param-assignment [ ] to:@END @END: from @BEGIN +main: from @BEGIN + [1] call prepare param-assignment [ ] + to:main::@3 +main::@3: from main main::@11 main::@12 main::@3 + [2] (byte) main::c#2 ← phi( main/(byte) 25 main::@12/(byte~) main::c#6 main::@11/(byte) 25 ) [ main::c#2 ] + [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] + [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] + to:main::@4 +main::@4: from main::@3 main::@4 + [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] + [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] + to:main::@6 +main::@6: from main::@4 + [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] + [8] if((byte) main::c#1!=(byte) 0) goto main::@12 [ main::c#1 ] + to:main::@7 +main::@7: from main::@6 + [9] call flip param-assignment [ ] + to:main::@10 +main::@10: from main::@7 + [10] call plot param-assignment [ ] + to:main::@11 +main::@11: from main::@10 + [11] if(true) goto main::@3 [ ] + to:main::@return +main::@return: from main::@11 + [12] return [ ] + to:@RETURN +main::@12: from main::@6 + [13] (byte~) main::c#6 ← (byte) main::c#1 [ main::c#6 ] + to:main::@3 +plot: from main::@10 + to:plot::@1 +plot::@1: from plot plot::@5 + [14] (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@5/(byte~) plot::y#5 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [14] (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@5/(byte*~) plot::line#5 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [14] (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@5/(byte~) plot::i#5 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [15] (byte~) plot::i#6 ← (byte) plot::i#3 [ plot::i#6 plot::line#2 plot::y#2 ] + to:plot::@2 +plot::@2: from plot::@1 plot::@6 + [16] (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@6/(byte~) plot::x#3 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [16] (byte) plot::i#2 ← phi( plot::@1/(byte~) plot::i#6 plot::@6/(byte~) plot::i#7 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [17] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] + [18] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [19] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::line#2 plot::x#2 plot::y#2 plot::i#1 ] + [20] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::line#2 plot::x#1 plot::y#2 plot::i#1 ] + [21] if((byte) plot::x#1<(byte) 16) goto plot::@6 [ plot::line#2 plot::x#1 plot::y#2 plot::i#1 ] + to:plot::@3 +plot::@3: from plot::@2 + [22] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::y#2 plot::i#1 plot::line#1 ] + [23] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::y#1 plot::i#1 plot::line#1 ] + [24] if((byte) plot::y#1!=(byte) 0) goto plot::@5 [ plot::y#1 plot::i#1 plot::line#1 ] + to:plot::@return +plot::@return: from plot::@3 + [25] return [ ] + to:@RETURN +plot::@5: from plot::@3 + [26] (byte~) plot::i#5 ← (byte) plot::i#1 [ plot::i#5 plot::y#1 plot::line#1 ] + [27] (byte*~) plot::line#5 ← (byte*) plot::line#1 [ plot::i#5 plot::line#5 plot::y#1 ] + [28] (byte~) plot::y#5 ← (byte) plot::y#1 [ plot::i#5 plot::line#5 plot::y#5 ] + to:plot::@1 +plot::@6: from plot::@2 + [29] (byte~) plot::i#7 ← (byte) plot::i#1 [ plot::i#7 plot::line#2 plot::x#1 plot::y#2 ] + [30] (byte~) plot::x#3 ← (byte) plot::x#1 [ plot::i#7 plot::x#3 plot::line#2 plot::y#2 ] + to:plot::@2 +flip: from main::@7 + to:flip::@1 +flip::@1: from flip flip::@7 + [31] (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@7/(byte~) flip::r#5 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [31] (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@7/(byte~) flip::dstIdx#6 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [31] (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@7/(byte~) flip::srcIdx#5 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [32] (byte~) flip::srcIdx#6 ← (byte) flip::srcIdx#3 [ flip::dstIdx#5 flip::srcIdx#6 flip::r#2 ] + [33] (byte~) flip::dstIdx#7 ← (byte) flip::dstIdx#5 [ flip::srcIdx#6 flip::dstIdx#7 flip::r#2 ] + to:flip::@2 +flip::@2: from flip::@1 flip::@8 + [34] (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@8/(byte~) flip::c#3 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [34] (byte) flip::dstIdx#3 ← phi( flip::@1/(byte~) flip::dstIdx#7 flip::@8/(byte~) flip::dstIdx#8 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [34] (byte) flip::srcIdx#2 ← phi( flip::@1/(byte~) flip::srcIdx#6 flip::@8/(byte~) flip::srcIdx#7 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [35] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] + [36] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [37] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::dstIdx#3 flip::c#2 flip::r#2 flip::srcIdx#1 ] + [38] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::c#2 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ] + [39] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::c#1 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ] + [40] if((byte) flip::c#1!=(byte) 0) goto flip::@8 [ flip::c#1 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ] + to:flip::@4 +flip::@4: from flip::@2 + [41] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::r#2 flip::srcIdx#1 flip::dstIdx#2 ] + [42] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::r#1 flip::srcIdx#1 flip::dstIdx#2 ] + [43] if((byte) flip::r#1!=(byte) 0) goto flip::@7 [ flip::r#1 flip::srcIdx#1 flip::dstIdx#2 ] + to:flip::@3 +flip::@3: from flip::@4 flip::@9 + [44] (byte) flip::i#2 ← phi( flip::@9/(byte~) flip::i#3 flip::@4/(byte) 0 ) [ flip::i#2 ] + [45] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] + [46] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] + [47] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] + [48] if((byte) flip::i#1!=(byte) 0) goto flip::@9 [ flip::i#1 ] + to:flip::@return +flip::@return: from flip::@3 + [49] return [ ] + to:@RETURN +flip::@9: from flip::@3 + [50] (byte~) flip::i#3 ← (byte) flip::i#1 [ flip::i#3 ] + to:flip::@3 +flip::@7: from flip::@4 + [51] (byte~) flip::srcIdx#5 ← (byte) flip::srcIdx#1 [ flip::srcIdx#5 flip::r#1 flip::dstIdx#2 ] + [52] (byte~) flip::dstIdx#6 ← (byte) flip::dstIdx#2 [ flip::srcIdx#5 flip::dstIdx#6 flip::r#1 ] + [53] (byte~) flip::r#5 ← (byte) flip::r#1 [ flip::srcIdx#5 flip::dstIdx#6 flip::r#5 ] + to:flip::@1 +flip::@8: from flip::@2 + [54] (byte~) flip::srcIdx#7 ← (byte) flip::srcIdx#1 [ flip::srcIdx#7 flip::c#1 flip::dstIdx#1 flip::r#2 ] + [55] (byte~) flip::dstIdx#8 ← (byte) flip::dstIdx#1 [ flip::srcIdx#7 flip::dstIdx#8 flip::c#1 flip::r#2 ] + [56] (byte~) flip::c#3 ← (byte) flip::c#1 [ flip::srcIdx#7 flip::dstIdx#8 flip::c#3 flip::r#2 ] + to:flip::@2 +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@3 + [57] (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@3/(byte~) prepare::i#3 ) [ prepare::i#2 ] + [58] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] + [59] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] + [60] if((byte) prepare::i#1!=(byte) 0) goto prepare::@3 [ prepare::i#1 ] + to:prepare::@return +prepare::@return: from prepare::@1 + [61] return [ ] + to:@RETURN +prepare::@3: from prepare::@1 + [62] (byte~) prepare::i#3 ← (byte) prepare::i#1 [ prepare::i#3 ] + to:prepare::@1 + +Created 14 initial phi equivalence classes +Coalesced [13] main::c#6 ← main::c#1 +Coalesced [15] plot::i#6 ← plot::i#3 +Coalesced [26] plot::i#5 ← plot::i#1 +Coalesced [27] plot::line#5 ← plot::line#1 +Coalesced [28] plot::y#5 ← plot::y#1 +Coalesced (already) [29] plot::i#7 ← plot::i#1 +Coalesced [30] plot::x#3 ← plot::x#1 +Coalesced [32] flip::srcIdx#6 ← flip::srcIdx#3 +Coalesced [33] flip::dstIdx#7 ← flip::dstIdx#5 +Coalesced [50] flip::i#3 ← flip::i#1 +Coalesced [51] flip::srcIdx#5 ← flip::srcIdx#1 +Coalesced [52] flip::dstIdx#6 ← flip::dstIdx#2 +Coalesced [53] flip::r#5 ← flip::r#1 +Coalesced (already) [54] flip::srcIdx#7 ← flip::srcIdx#1 +Coalesced [55] flip::dstIdx#8 ← flip::dstIdx#1 +Coalesced [56] flip::c#3 ← flip::c#1 +Coalesced [62] prepare::i#3 ← prepare::i#1 +Coalesced down to 11 phi equivalence classes +Culled Empty Block (label) main::@12 +Culled Empty Block (label) plot::@5 +Culled Empty Block (label) plot::@6 +Culled Empty Block (label) flip::@9 +Culled Empty Block (label) flip::@7 +Culled Empty Block (label) flip::@8 +Culled Empty Block (label) prepare::@3 +Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return plot plot::@1 plot::@2 plot::@3 plot::@return flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return prepare prepare::@1 prepare::@return +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED +@BEGIN: from + [0] call main param-assignment [ ] + to:@END +@END: from @BEGIN main: from @BEGIN [1] call prepare param-assignment [ ] to:main::@3 diff --git a/src/dk/camelot64/kickc/test/ref/loopmin.log b/src/dk/camelot64/kickc/test/ref/loopmin.log index 79b0c21dc..58eb5af3e 100644 --- a/src/dk/camelot64/kickc/test/ref/loopmin.log +++ b/src/dk/camelot64/kickc/test/ref/loopmin.log @@ -252,10 +252,78 @@ CONTROL FLOW GRAPH @END: from @3 Block Sequence Planned @BEGIN @1 @3 @END @2 +Added new block during phi lifting @7(between @3 and @1) +Added new block during phi lifting @8(between @1 and @3) +Block Sequence Planned @BEGIN @1 @8 @3 @END @7 @2 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @7 @BEGIN + (byte) s#2 ← phi( @7/(byte~) s#5 @BEGIN/(byte) 0 ) + (byte) i#2 ← phi( @7/(byte~) i#5 @BEGIN/(byte) 10 ) + if((byte) i#2>(byte) 5) goto @2 + to:@8 +@8: from @1 + (byte~) s#6 ← (byte) s#2 + to:@3 +@3: from @2 @8 + (byte) s#4 ← phi( @8/(byte~) s#6 @2/(byte~) s#7 ) + (byte) i#1 ← -- (byte) i#2 + if((byte) i#1>(byte) 0) goto @7 + to:@END +@END: from @3 +@7: from @3 + (byte~) i#5 ← (byte) i#1 + (byte~) s#5 ← (byte) s#4 + to:@1 +@2: from @1 + (byte) s#1 ← (byte) s#2 + (byte) i#2 + (byte~) s#7 ← (byte) s#1 + to:@3 + +Propagating live ranges... Propagating live ranges... Propagating live ranges... Propagating live ranges... CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @7 @BEGIN + [0] (byte) s#2 ← phi( @7/(byte~) s#5 @BEGIN/(byte) 0 ) [ i#2 s#2 ] + [0] (byte) i#2 ← phi( @7/(byte~) i#5 @BEGIN/(byte) 10 ) [ i#2 s#2 ] + [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] + to:@8 +@8: from @1 + [2] (byte~) s#6 ← (byte) s#2 [ i#2 s#6 ] + to:@3 +@3: from @2 @8 + [3] (byte) s#4 ← phi( @8/(byte~) s#6 @2/(byte~) s#7 ) [ i#2 s#4 ] + [4] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] + [5] if((byte) i#1>(byte) 0) goto @7 [ i#1 s#4 ] + to:@END +@END: from @3 +@7: from @3 + [6] (byte~) i#5 ← (byte) i#1 [ i#5 s#4 ] + [7] (byte~) s#5 ← (byte) s#4 [ i#5 s#5 ] + to:@1 +@2: from @1 + [8] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] + [9] (byte~) s#7 ← (byte) s#1 [ i#2 s#7 ] + to:@3 + +Created 3 initial phi equivalence classes +Coalesced [2] s#6 ← s#2 +Coalesced [6] i#5 ← i#1 +Coalesced (already) [7] s#5 ← s#4 +Coalesced [9] s#7 ← s#1 +Coalesced down to 2 phi equivalence classes +Culled Empty Block (label) @8 +Culled Empty Block (label) @7 +Block Sequence Planned @BEGIN @1 @3 @END @2 +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED @BEGIN: from to:@1 @1: from @3 @BEGIN diff --git a/src/dk/camelot64/kickc/test/ref/minus.log b/src/dk/camelot64/kickc/test/ref/minus.log index c5fb88bdb..37445250e 100644 --- a/src/dk/camelot64/kickc/test/ref/minus.log +++ b/src/dk/camelot64/kickc/test/ref/minus.log @@ -207,9 +207,50 @@ Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Block Sequence Planned @BEGIN @1 @END +Added new block during phi lifting @3(between @1 and @1) +Block Sequence Planned @BEGIN @1 @END @3 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 ) + (byte~) $0 ← (byte) 2 + (byte) i#2 + (byte~) $1 ← (byte~) $0 + (byte) 2 + *((word) 4352 + (byte) i#2) ← (byte~) $1 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 10) goto @3 + to:@END +@END: from @1 +@3: from @1 + (byte~) i#3 ← (byte) i#1 + to:@1 + Propagating live ranges... Propagating live ranges... CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + [0] (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 ) [ i#2 ] + [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] + [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] + [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [5] if((byte) i#1<(byte) 10) goto @3 [ i#1 ] + to:@END +@END: from @1 +@3: from @1 + [6] (byte~) i#3 ← (byte) i#1 [ i#3 ] + to:@1 + +Created 1 initial phi equivalence classes +Coalesced [6] i#3 ← i#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) @3 +Block Sequence Planned @BEGIN @1 @END +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED @BEGIN: from to:@1 @1: from @1 @BEGIN diff --git a/src/dk/camelot64/kickc/test/ref/summin.log b/src/dk/camelot64/kickc/test/ref/summin.log index a4f6e6f8d..783b0f132 100644 --- a/src/dk/camelot64/kickc/test/ref/summin.log +++ b/src/dk/camelot64/kickc/test/ref/summin.log @@ -241,6 +241,24 @@ sum::@return: from sum @END: from @2 Block Sequence Planned @BEGIN @2 @END sum sum::@return +Block Sequence Planned @BEGIN @2 @END sum sum::@return +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + call sum param-assignment + to:@2 +@2: from @BEGIN + call sum param-assignment + to:@END +@END: from @2 +sum: from @2 @BEGIN + (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) + (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) + (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 + to:sum::@return +sum::@return: from sum + return (byte) s1#0 + to:@RETURN + Propagating live ranges... CONTROL FLOW GRAPH - LIVE RANGES @BEGIN: from @@ -259,6 +277,27 @@ sum::@return: from sum [4] return (byte) s1#0 [ ] to:@RETURN +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes +Block Sequence Planned @BEGIN @2 @END sum sum::@return +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED +@BEGIN: from + [0] call sum param-assignment [ ] + to:@2 +@2: from @BEGIN + [1] call sum param-assignment [ ] + to:@END +@END: from @2 +sum: from @2 @BEGIN + [2] (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) [ sum::a#2 sum::b#2 ] + [2] (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) [ sum::a#2 sum::b#2 ] + [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] + to:sum::@return +sum::@return: from sum + [4] return (byte) s1#0 [ ] + to:@RETURN + INITIAL ASM BBEGIN: sum_from_BBEGIN: