From 00266760807a94fb60495bea8bfbe379d29dad6f Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Tue, 7 Nov 2017 09:32:16 +0100 Subject: [PATCH] Implemented call-path based effective alive analysis with call-path specific aliases. --- .../java/dk/camelot64/kickc/Compiler.java | 8 +- .../fragment/asm/zpby1_ge_zpby1_then_la1.asm | 1 + .../model/LiveRangeVariablesEffective.java | 204 +- .../dk/camelot64/kickc/model/Procedure.java | 2 + .../camelot64/kickc/model/StatementBase.java | 4 +- .../kickc/passes/Pass2AliasElimination.java | 28 +- .../Pass3LiveRangesEffectiveAnalysis.java | 108 +- .../Pass4RegisterUpliftCombinations.java | 13 +- .../dk/camelot64/kickc/test/TestErrors.java | 3 - .../dk/camelot64/kickc/test/TestPrograms.java | 4 + .../kickc/test/ref/overlap-allocation.asm | 31 + .../kickc/test/ref/overlap-allocation.cfg | 46 + .../kickc/test/ref/overlap-allocation.log | 2039 +++++++++++++++++ .../kickc/test/ref/overlap-allocation.sym | 34 + 14 files changed, 2456 insertions(+), 69 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/fragment/asm/zpby1_ge_zpby1_then_la1.asm create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.asm create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.cfg create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.log create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.sym diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d9a683074..3b7cc50ef 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -209,6 +209,8 @@ public class Compiler { new Pass3StatementIndices(program).generateStatementIndices(); new Pass3CallGraphAnalysis(program).findCallGraph(); new Pass3LiveRangesAnalysis(program).findLiveRanges(); + program.getLog().append("CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES"); + program.getLog().append(program.getGraph().toString(program)); new Pass3LiveRangesEffectiveAnalysis(program).findLiveRangesEffective(); program.getLog().append("CONTROL FLOW GRAPH - PHI MEM COALESCED"); program.getLog().append(program.getGraph().toString(program)); @@ -262,9 +264,9 @@ public class Compiler { //program.getLog().setVerboseUplift(true); new Pass4RegisterUpliftCombinations(program).performUplift(10_000); - program.getLog().setVerboseUplift(true); - new Pass4RegisterUpliftStatic(program).performUplift(); - program.getLog().setVerboseUplift(false); + //program.getLog().setVerboseUplift(true); + //new Pass4RegisterUpliftStatic(program).performUplift(); + //program.getLog().setVerboseUplift(false); // Attempt uplifting registers one at a time to catch remaining potential not realized by combination search new Pass4RegisterUpliftRemains(program).performUplift(10_000); diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpby1_ge_zpby1_then_la1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpby1_ge_zpby1_then_la1.asm new file mode 100644 index 000000000..3a49f26fb --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpby1_ge_zpby1_then_la1.asm @@ -0,0 +1 @@ +jmp {la1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java index 271a892f5..a58c4d37c 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java @@ -1,31 +1,139 @@ package dk.camelot64.kickc.model; +import dk.camelot64.kickc.passes.Pass2AliasElimination; + import java.util.*; -/** Effective variable live ranges for all statements. (Including variables alive in calling methods) - * Created by {@link dk.camelot64.kickc.passes.Pass3CallGraphAnalysis} +/** + * Effective variable live ranges for all statements. + * (Including variables alive in calling methods). + * Created by {@link dk.camelot64.kickc.passes.Pass3LiveRangesEffectiveAnalysis} */ public class LiveRangeVariablesEffective { - /** Effectively alive variables by statement index. */ - Map effectiveLiveCombinations; + /** + * The program. + */ + private Program program; - public LiveRangeVariablesEffective(Map effectiveLiveCombinations) { - this.effectiveLiveCombinations = effectiveLiveCombinations; + /** + * Call-paths for all procedures. + */ + private Map procedureCallPaths; + + /** + * Normal variable live ranges. + */ + private LiveRangeVariables liveRangeVariables; + + /** + * Information about which procedures reference which variables. + */ + private VariableReferenceInfo referenceInfo; + + public LiveRangeVariablesEffective(Program program, Map procedureCallPaths, LiveRangeVariables liveRangeVariables, VariableReferenceInfo referenceInfo) { + this.program = program; + this.procedureCallPaths = procedureCallPaths; + this.liveRangeVariables = liveRangeVariables; + this.referenceInfo = referenceInfo; } + /** + * All call-paths leading into a specific procedure. + */ + public static class CallPaths { + /** + * The procedure + */ + private ProcedureRef procedure; + /** + * All call-paths leading into the procedure from the main() procedure. + */ + private Collection callPaths; + + public CallPaths(ProcedureRef procedure) { + this.procedure = procedure; + this.callPaths = new ArrayList<>(); + } + + public ProcedureRef getProcedure() { + return procedure; + } + + public Collection getCallPaths() { + return callPaths; + } + + public void add(CallPath callPath) { + this.callPaths.add(callPath); + } + } + + /** + * All variables alive in a specific procedure at a specific call-path. + * The call-path is th path from the main()-procedure to the procedure in question. + */ + public static class CallPath { + + /** + * The path from main() to the procedure. First element is the call to main(), last element is the call to the procedure. + */ + private List path; + /** + * Alive variables on the call-path. Based on alive vars at each call in the path. + */ + private Collection alive; + /** + * Alias variables on the call-path. All global aliases plus any variables alias-assigned in a phi-block on the path. + */ + private Pass2AliasElimination.Aliases aliases; + + public CallPath(List path, Collection alive, Pass2AliasElimination.Aliases aliases) { + this.path = path; + this.alive = alive; + this.aliases = aliases; + } + + /** + * The path from main() to the procedure. First element is the call to main(), last element is the call to the procedure. + * @return Tha call path + */ + public List getPath() { + return path; + } + + /** + * Alive variables on the call-path. Based on alive vars at each call in the path. + * @return The alive variables + */ + public Collection getAlive() { + return alive; + } + + /** + * Alias variables on the call-path. All global aliases plus any variables alias-assigned in a phi-block on the path. + * @return The aliases + */ + public Pass2AliasElimination.Aliases getAliases() { + return aliases; + } + } + + /** * Get all variables potentially alive at a statement. * If the statement is inside a method this also includes all variables alive at the exit of any call. *

+ * * @param statement The statement to examine * @return All variables potentially alive at the statement */ public Collection getAliveEffective(Statement statement) { Set effectiveAliveTotal = new LinkedHashSet<>(); - AliveCombinations aliveCombinations = effectiveLiveCombinations.get(statement.getIndex()); - for (AliveCombination aliveCombination : aliveCombinations.getCombinations()) { - effectiveAliveTotal.addAll(aliveCombination.getAlive()); + AliveCombinations aliveCombinations = getAliveCombinations(statement); + for (CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) { + Collection alive = aliveCombinations.getEffectiveAliveAtStmt(callPath); + effectiveAliveTotal.addAll(alive); } return effectiveAliveTotal; } @@ -36,46 +144,80 @@ public class LiveRangeVariablesEffective { * (recursively up til the main()-method. * Each combination includes all variables alive at the exit of any surrounding call. *

+ * * @param statement The statement to examine * @return All combinations of variables alive at the statement */ public AliveCombinations getAliveCombinations(Statement statement) { - return effectiveLiveCombinations.get(statement.getIndex()); + List aliveAtStmt = liveRangeVariables.getAlive(statement); + CallPaths callPaths; + Collection referencedInProcedure; + ControlFlowBlock block = program.getGraph().getBlockFromStatementIdx(statement.getIndex()); + ScopeRef scopeRef = block.getScope(); + Scope scope = program.getScope().getScope(scopeRef); + if (scope instanceof Procedure) { + Procedure procedure = (Procedure) scope; + callPaths = procedureCallPaths.get(procedure.getRef()); + referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef()); + } else { + callPaths = new CallPaths(Procedure.ROOT); + referencedInProcedure = new ArrayList<>(); + } + return new AliveCombinations(callPaths, referencedInProcedure, aliveAtStmt); } - /** Combinations of variables effectively alive at a specific statement. + /** + * Combinations of variables effectively alive at a specific statement. * If the statement is inside a method the combinations are the live variables inside the method combined with each calling statements alive vars. * As each caller might also be inside a methos there may be a large amount of combinations. */ public static class AliveCombinations { - private Collection combinations; + /** + * All call-paths to the procedure containing the statement. + */ + private CallPaths callPaths; + /** + * All variables referenced in the procedure containing the statement. + */ + private Collection referencedInProcedure; + /** + * Variables alive at the statement inside the procedure. + */ + private Collection aliveAtStmt; - public AliveCombinations(Collection> aliveCombinations) { - ArrayList combinations = new ArrayList<>(); - for (Collection aliveCombination : aliveCombinations) { - combinations.add(new AliveCombination(aliveCombination)); - } - this.combinations = combinations; + public AliveCombinations(CallPaths callPaths, Collection referencedInProcedure, Collection aliveAtStmt) { + this.callPaths = callPaths; + this.referencedInProcedure = referencedInProcedure; + this.aliveAtStmt = aliveAtStmt; } - public Collection getCombinations() { - return combinations; + public CallPaths getCallPaths() { + return callPaths; } - } - - /** One single combinations of variables effectively alive at a specific statement. */ - public static class AliveCombination { - - private Collection alive; - - public AliveCombination(Collection alive) { - this.alive = alive; + public Collection getReferencedInProcedure() { + return referencedInProcedure; } - public Collection getAlive() { - return alive; + public Collection getAliveAtStmt() { + return aliveAtStmt; + } + + /** + * Get all variables effective alive at the statement for a specific call path. + * @param callPath The call path (returned from getCallPaths) + * @return All variables effectively alive at the statement on the call-path + */ + public Collection getEffectiveAliveAtStmt(CallPath callPath) { + LinkedHashSet effectiveAlive = new LinkedHashSet<>(); + // Add alive at call + effectiveAlive.addAll(callPath.getAlive()); + // Clear out any variables referenced in the method + effectiveAlive.removeAll(referencedInProcedure); + // Add alive at statement + effectiveAlive.addAll(aliveAtStmt); + return effectiveAlive; } } diff --git a/src/main/java/dk/camelot64/kickc/model/Procedure.java b/src/main/java/dk/camelot64/kickc/model/Procedure.java index cf670b454..033669eb8 100644 --- a/src/main/java/dk/camelot64/kickc/model/Procedure.java +++ b/src/main/java/dk/camelot64/kickc/model/Procedure.java @@ -14,6 +14,8 @@ public class Procedure extends Scope { private final SymbolType returnType; private List parameterNames; + public static final ProcedureRef ROOT = new ProcedureRef(""); + public Procedure(String name, SymbolType returnType, Scope parentScope) { super(name, parentScope); this.returnType = returnType; diff --git a/src/main/java/dk/camelot64/kickc/model/StatementBase.java b/src/main/java/dk/camelot64/kickc/model/StatementBase.java index a3f64480e..e0c84130e 100644 --- a/src/main/java/dk/camelot64/kickc/model/StatementBase.java +++ b/src/main/java/dk/camelot64/kickc/model/StatementBase.java @@ -55,8 +55,8 @@ public abstract class StatementBase implements Statement { if(liveRangeVariablesEffective!=null) { LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this); alive.append(" ( "); - for (LiveRangeVariablesEffective.AliveCombination aliveCombination : aliveCombinations.getCombinations()) { - alive.append(getAliveString(aliveCombination.getAlive())); + for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) { + alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath))); alive.append(" "); } alive.append(")"); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java index a7fbb4314..065d7d62f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -19,7 +19,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { */ @Override public boolean optimize() { - final Aliases aliases = findAliases(); + final Aliases aliases = findAliases(getProgram(), false); removeAliasAssignments(aliases); replaceVariables(aliases.getReplacements()); for (AliasSet aliasSet : aliases.getAliasSets()) { @@ -88,6 +88,14 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { this.aliases = new ArrayList<>(); } + public Aliases(Aliases aliases) { + this.aliases = new ArrayList<>(); + for (AliasSet aliasSet : aliases.getAliasSets()) { + AliasSet copySet = new AliasSet(aliasSet); + this.aliases.add(copySet); + } + } + public List getSymbolsToRemove() { ArrayList eliminates = new ArrayList<>(); for (AliasSet alias : aliases) { @@ -159,6 +167,10 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { this.vars = new ArrayList<>(); } + public AliasSet(AliasSet aliasSet) { + this.vars = new ArrayList<>(aliasSet.getVars()); + } + public void add(VariableRef variable) { vars.add(variable); } @@ -226,16 +238,16 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { } - private Aliases findAliases() { - Aliases candidates = findAliasesCandidates(false, getProgram()); - cleanupCandidates(candidates); + public static Aliases findAliases(Program program, boolean allowCrossScope) { + Aliases candidates = findAliasesCandidates(allowCrossScope, program); + cleanupCandidates(candidates, program); return candidates; } // Remove all candidates that are used after assignment in phi blocks - private void cleanupCandidates(Aliases candidates) { + private static void cleanupCandidates(Aliases candidates, Program program) { for (final AliasSet aliasSet : candidates.aliases) { - for (ControlFlowBlock block : getGraph().getAllBlocks()) { + for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { if(block.hasPhiBlock()) { StatementPhiBlock phi = block.getPhiBlock(); boolean lMatch = false; @@ -244,7 +256,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { RValue rValue = phiRValue.getrValue(); if (aliasSet.contains(rValue)) { - getLog().append("Alias candidate removed " + rValue.toString(getProgram())); + program.getLog().append("Alias candidate removed " + rValue.toString(program)); aliasSet.remove(rValue); break; } @@ -265,7 +277,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { * * @return Map from Variable to the Constant value */ - public static Aliases findAliasesCandidates(final boolean allowCrossScope, final Program program) { + private static Aliases findAliasesCandidates(final boolean allowCrossScope, final Program program) { final Aliases aliases = new Aliases(); final ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java index 7cf178d88..0036292bb 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java @@ -9,29 +9,36 @@ import java.util.*; */ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { + /** + * Call-paths for all procedures. + */ + private Map procedureCallPaths; + + /** + * Normal variable live ranges. + */ + private LiveRangeVariables liveRangeVariables; + + /** + * Information about which procedures reference which variables. + */ + private VariableReferenceInfo referenceInfo; + + public Pass3LiveRangesEffectiveAnalysis(Program program) { super(program); } public void findLiveRangesEffective() { - LiveRangeVariablesEffective aliveEffective = findAliveEffective(getProgram()); + this.liveRangeVariables = getProgram().getLiveRangeVariables(); + this.referenceInfo = new VariableReferenceInfo(getProgram()); + this.procedureCallPaths = new LinkedHashMap<>(); + populateProcedureCallPaths(); + LiveRangeVariablesEffective aliveEffective = new LiveRangeVariablesEffective(getProgram(), procedureCallPaths, liveRangeVariables, referenceInfo); getProgram().setLiveRangeVariablesEffective(aliveEffective); //getLog().append("Calculated effective variable live ranges"); } - private LiveRangeVariablesEffective findAliveEffective(Program program) { - LiveRangeVariables liveRangeVariables = program.getLiveRangeVariables(); - Map effectiveLiveVariablesCombinations = new HashMap<>(); - for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { - for (Statement statement : block.getStatements()) { - Collection> statementAliveCombinations = findAliveEffective(liveRangeVariables, statement); - LiveRangeVariablesEffective.AliveCombinations aliveCombinations = new LiveRangeVariablesEffective.AliveCombinations(statementAliveCombinations); - effectiveLiveVariablesCombinations.put(statement.getIndex(), aliveCombinations); - } - } - return new LiveRangeVariablesEffective(effectiveLiveVariablesCombinations); - } - /** * Get all variables alive at a statement. * If the statement is inside a method this also includes all variables alive at the exit of the calls. @@ -54,7 +61,6 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { Procedure procedure = (Procedure) scope; Collection callers = getProgram().getCallGraph().getCallers(procedure.getLabel().getRef()); - VariableReferenceInfo referenceInfo = new VariableReferenceInfo(getProgram()); Collection referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef()); for (CallGraph.CallBlock.Call caller : callers) { // Each caller creates its own combinations @@ -81,4 +87,76 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { return combinations; } + private void populateProcedureCallPaths() { + this.procedureCallPaths = new LinkedHashMap<>(); + Collection procedures = getProgram().getScope().getAllProcedures(true); + for (Procedure procedure : procedures) { + populateProcedureCallPaths(procedure); + } + } + + private void populateProcedureCallPaths(Procedure procedure) { + ProcedureRef procedureRef = procedure.getRef(); + LiveRangeVariablesEffective.CallPaths callPaths = procedureCallPaths.get(procedureRef); + if (callPaths == null) { + callPaths = new LiveRangeVariablesEffective.CallPaths(procedureRef); + Collection callers = + getProgram().getCallGraph().getCallers(procedure.getLabel().getRef()); + ControlFlowBlock procedureBlock = getProgram().getGraph().getBlock(procedure.getLabel().getRef()); + StatementPhiBlock procedurePhiBlock = null; + if(procedureBlock.hasPhiBlock()) { + procedurePhiBlock = procedureBlock.getPhiBlock(); + } + for (CallGraph.CallBlock.Call caller : callers) { + // Each caller creates its own call-paths + StatementCall callStatement = + (StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx()); + ControlFlowBlock callBlock = getProgram().getGraph().getBlockFromStatementIdx(callStatement.getIndex()); + ScopeRef callScopeRef = callBlock.getScope(); + Scope callScope = getProgram().getScope().getScope(callScopeRef); + if (callScope instanceof Procedure) { + // Found calling procedure! + Procedure callerProcedure = (Procedure) callScope; + // Make sure we have populated the call-paths of the calling procedure + populateProcedureCallPaths(callerProcedure); + // Find variables referenced in caller procedure + Collection referencedInCaller = referenceInfo.getReferenced(callerProcedure.getRef().getLabelRef()); + // For each caller path - create a new call-path + LiveRangeVariablesEffective.CallPaths callerPaths = procedureCallPaths.get(callerProcedure.getRef()); + for (LiveRangeVariablesEffective.CallPath callerPath : callerPaths.getCallPaths()) { + ArrayList path = new ArrayList<>(callerPath.getPath()); + path.add(caller); + Collection alive = new LinkedHashSet<>(); + alive.addAll(callerPath.getAlive()); + alive.removeAll(referencedInCaller); + alive.addAll(liveRangeVariables.getAlive(callStatement)); + Pass2AliasElimination.Aliases aliases = new Pass2AliasElimination.Aliases(callerPath.getAliases()); + if(procedurePhiBlock!=null) { + for (StatementPhiBlock.PhiVariable phiVariable : procedurePhiBlock.getPhiVariables()) { + RValue phiRvalue = phiVariable.getrValue(callBlock.getLabel()); + if (phiRvalue instanceof VariableRef) { + aliases.add(phiVariable.getVariable(), (VariableRef) phiRvalue); + } + } + } + LiveRangeVariablesEffective.CallPath callPath = new LiveRangeVariablesEffective.CallPath(path, alive, aliases); + callPaths.add(callPath); + } + } else { + // main() call outside procedure scope - create initial call-path. + ArrayList rootPath = new ArrayList<>(); + rootPath.add(caller); + ArrayList rootAlive = new ArrayList<>(); + // Initialize with global cross-scope aliases + Pass2AliasElimination.Aliases rootAliases = Pass2AliasElimination.findAliases(getProgram(), true); + LiveRangeVariablesEffective.CallPath rootCallPath = new LiveRangeVariablesEffective.CallPath(rootPath, rootAlive, rootAliases); + callPaths.add(rootCallPath); + } + } + procedureCallPaths.put(procedureRef, callPaths); + } + } + + + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java index fc6d75543..cc6933ca7 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java @@ -198,10 +198,9 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base { * @return true if the register allocation contains an overlapping allocation. false otherwise. */ public static boolean isAllocationOverlapping(Program program) { - Pass2AliasElimination.Aliases aliases = Pass2AliasElimination.findAliasesCandidates(true, program); for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { for (Statement statement : block.getStatements()) { - if (isStatementAllocationOverlapping(program, statement, aliases)) { + if (isStatementAllocationOverlapping(program, statement)) { return true; } } @@ -214,15 +213,15 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base { * * @param program The program * @param statement The statement to check - * @param usedRegisters The used registers. Will be extended with all registers used in the statement. * @return true if there is an overlapping register allocation */ - private static boolean isStatementAllocationOverlapping(Program program, Statement statement, Pass2AliasElimination.Aliases aliases) { + private static boolean isStatementAllocationOverlapping(Program program, Statement statement) { ProgramScope programScope = program.getScope(); LiveRangeVariablesEffective.AliveCombinations aliveCombinations = program.getLiveRangeVariablesEffective().getAliveCombinations(statement); - for (LiveRangeVariablesEffective.AliveCombination aliveCombination : aliveCombinations.getCombinations()) { + for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) { LinkedHashMap usedRegisters = new LinkedHashMap<>(); - Collection alive = aliveCombination.getAlive(); + Collection alive = aliveCombinations.getEffectiveAliveAtStmt(callPath); + Pass2AliasElimination.Aliases callPathAliases = callPath.getAliases(); for (VariableRef varRef : alive) { Variable var = programScope.getVariable(varRef); Registers.Register allocation = var.getAllocation(); @@ -230,7 +229,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base { if (allocationClass != null && !allocationClass.contains(varRef)) { // Examine if the var is an alias of a var in the allocation class boolean overlap = true; - Pass2AliasElimination.AliasSet aliasSet = aliases.findAliasSet(varRef); + Pass2AliasElimination.AliasSet aliasSet = callPathAliases.findAliasSet(varRef); if(aliasSet!=null) { for (VariableRef aliasVar : aliasSet.getVars()) { if(allocationClass.contains(aliasVar)) { diff --git a/src/main/java/dk/camelot64/kickc/test/TestErrors.java b/src/main/java/dk/camelot64/kickc/test/TestErrors.java index 1001fc4f1..b8f2a641d 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestErrors.java +++ b/src/main/java/dk/camelot64/kickc/test/TestErrors.java @@ -28,9 +28,6 @@ public class TestErrors extends TestCase { compileAndCompare("inline-asm-param"); } - public void testOverlapAllocation() throws IOException, URISyntaxException { - compileAndCompare("overlap-allocation"); - } public void testIncD020() throws IOException, URISyntaxException { compileAndCompare("incd020"); diff --git a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java index 12ee69671..fee4ae35f 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java @@ -24,6 +24,10 @@ public class TestPrograms extends TestCase { helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); } + public void testOverlapAllocation() throws IOException, URISyntaxException { + compileAndCompare("overlap-allocation"); + } + public void testBitmapBresenham() throws IOException, URISyntaxException { compileAndCompare("bitmap-bresenham"); } diff --git a/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.asm b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.asm new file mode 100644 index 000000000..7a820c7f7 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.asm @@ -0,0 +1,31 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SCREEN = $400 + jsr main +main: { + ldx #0 + b1: + jsr plot + inx + cpx #$b + bne b1 + ldx #0 + b2: + jsr plot + inx + cpx #$b + bne b2 + ldx #0 + b3: + jsr plot + inx + cpx #$b + bne b3 + rts +} +plot: { + lda #'*' + sta SCREEN,x + rts +} diff --git a/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.cfg b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.cfg new file mode 100644 index 000000000..50f64030e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.cfg @@ -0,0 +1,46 @@ +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + [1] phi() [ ] ( [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@7 + [2] (byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte) main::i#1 ) [ main::i#2 ] ( [ main::i#2 ] ) + [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + to:main::@7 +main::@7: scope:[main] from main::@1 + [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) + [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) + to:main::@2 +main::@2: scope:[main] from main::@7 main::@8 + [7] (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@8/(byte) main::j#1 ) [ main::j#2 ] ( [ main::j#2 ] ) + [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + to:main::@8 +main::@8: scope:[main] from main::@2 + [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) + [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) + to:main::@3 +main::@3: scope:[main] from main::@8 main::@9 + [12] (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@9/(byte) main::k#1 ) [ main::k#2 ] ( [ main::k#2 ] ) + [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + to:main::@9 +main::@9: scope:[main] from main::@3 + [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) + [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@9 + [17] return [ ] ( [ ] ) + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + [18] (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) [ plot::x#3 ] ( [ main::i#2 plot::x#3 ] [ main::j#2 plot::x#3 ] [ main::k#2 plot::x#3 ] ) + [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + to:plot::@return +plot::@return: scope:[plot] from plot + [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + to:@return diff --git a/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.log b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.log new file mode 100644 index 000000000..51aa50261 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.log @@ -0,0 +1,2039 @@ +// Allocates ZP to j/k-variables even though all of i, j, k could be allocates to x and be more efficient. +// Reason: Pass4RegisterUpliftCombinations.isAllocationOverlapping() believes i/j/k variables overlaps insode plot() +byte* SCREEN = $0400; + +void main() { + for(byte i : 0..10) { + plot(i); + } + for(byte j : 0..10) { + plot(j); + } + for(byte k : 0..10) { + plot(k); + } +} + +void plot(byte x) { + SCREEN[x] = '*'; +} + +PROGRAM + (byte*) SCREEN ← (word) 1024 +proc (void()) main() + (byte) main::i ← (byte) 0 +main::@1: + (void~) main::$0 ← call plot (byte) main::i + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$1 ← (byte) main::i != (byte) 11 + if((boolean~) main::$1) goto main::@1 + (byte) main::j ← (byte) 0 +main::@2: + (void~) main::$2 ← call plot (byte) main::j + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$3 ← (byte) main::j != (byte) 11 + if((boolean~) main::$3) goto main::@2 + (byte) main::k ← (byte) 0 +main::@3: + (void~) main::$4 ← call plot (byte) main::k + (byte) main::k ← ++ (byte) main::k + (boolean~) main::$5 ← (byte) main::k != (byte) 11 + if((boolean~) main::$5) goto main::@3 +main::@return: + return +endproc // main() +proc (void()) plot((byte) plot::x) + *((byte*) SCREEN + (byte) plot::x) ← (byte) '*' +plot::@return: + return +endproc // plot() + call main + +SYMBOLS +(byte*) SCREEN +(void()) main() +(void~) main::$0 +(boolean~) main::$1 +(void~) main::$2 +(boolean~) main::$3 +(void~) main::$4 +(boolean~) main::$5 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte) main::i +(byte) main::j +(byte) main::k +(void()) plot((byte) plot::x) +(label) plot::@return +(byte) plot::x + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN ← (word) 1024 + to:@1 +main: scope:[main] from + (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (void~) main::$0 ← call plot (byte) main::i + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$1 ← (byte) main::i != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@1 + (byte) main::j ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@2 main::@4 + (void~) main::$2 ← call plot (byte) main::j + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$3 ← (byte) main::j != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@2 + (byte) main::k ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@3 main::@5 + (void~) main::$4 ← call plot (byte) main::k + (byte) main::k ← ++ (byte) main::k + (boolean~) main::$5 ← (byte) main::k != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@6 +main::@6: scope:[main] from main::@3 + to:main::@return +main::@return: scope:[main] from main::@6 + return + to:@return +@1: scope:[] from @begin + to:@2 +plot: scope:[plot] from + *((byte*) SCREEN + (byte) plot::x) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @1 + call main + to:@end +@end: scope:[] from @2 + +Removing empty block main::@6 +Removing empty block @1 +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN ← (word) 1024 + to:@2 +main: scope:[main] from + (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (void~) main::$0 ← call plot (byte) main::i + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$1 ← (byte) main::i != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@1 + (byte) main::j ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@2 main::@4 + (void~) main::$2 ← call plot (byte) main::j + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$3 ← (byte) main::j != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@2 + (byte) main::k ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@3 main::@5 + (void~) main::$4 ← call plot (byte) main::k + (byte) main::k ← ++ (byte) main::k + (boolean~) main::$5 ← (byte) main::k != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +plot: scope:[plot] from + *((byte*) SCREEN + (byte) plot::x) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main + to:@end +@end: scope:[] from @2 + +PROCEDURE MODIFY VARIABLE ANALYSIS + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL +@begin: scope:[] from + (byte*) SCREEN ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) plot::x ← (byte) main::i + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$1 ← (byte) main::i != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte) plot::x ← (byte) main::j + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$3 ← (byte) main::j != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte) plot::x ← (byte) main::k + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k ← ++ (byte) main::k + (boolean~) main::$5 ← (byte) main::k != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + *((byte*) SCREEN + (byte) plot::x) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte*) SCREEN#5 ← phi( @2/(byte*) SCREEN#11 ) + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#5 main::@7/(byte*) SCREEN#6 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte*) SCREEN#6 ← phi( main::@1/(byte*) SCREEN#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte) main::i#1 ← ++ (byte) main::i#3 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte*) SCREEN#7 ← phi( main::@7/(byte*) SCREEN#6 ) + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte*) SCREEN#3 ← phi( main::@4/(byte*) SCREEN#7 main::@8/(byte*) SCREEN#8 ) + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte*) SCREEN#8 ← phi( main::@2/(byte*) SCREEN#3 ) + (byte) main::j#3 ← phi( main::@2/(byte) main::j#2 ) + (byte) main::j#1 ← ++ (byte) main::j#3 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte*) SCREEN#9 ← phi( main::@8/(byte*) SCREEN#8 ) + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte*) SCREEN#4 ← phi( main::@5/(byte*) SCREEN#9 main::@9/(byte*) SCREEN#10 ) + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte*) SCREEN#10 ← phi( main::@3/(byte*) SCREEN#4 ) + (byte) main::k#3 ← phi( main::@3/(byte) main::k#2 ) + (byte) main::k#1 ← ++ (byte) main::k#3 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + (byte*) SCREEN#11 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte*) SCREEN#5 ← phi( @2/(byte*) SCREEN#11 ) + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#5 main::@7/(byte*) SCREEN#6 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte*) SCREEN#6 ← phi( main::@1/(byte*) SCREEN#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte) main::i#1 ← ++ (byte) main::i#3 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte*) SCREEN#7 ← phi( main::@7/(byte*) SCREEN#6 ) + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte*) SCREEN#3 ← phi( main::@4/(byte*) SCREEN#7 main::@8/(byte*) SCREEN#8 ) + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte*) SCREEN#8 ← phi( main::@2/(byte*) SCREEN#3 ) + (byte) main::j#3 ← phi( main::@2/(byte) main::j#2 ) + (byte) main::j#1 ← ++ (byte) main::j#3 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte*) SCREEN#9 ← phi( main::@8/(byte*) SCREEN#8 ) + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte*) SCREEN#4 ← phi( main::@5/(byte*) SCREEN#9 main::@9/(byte*) SCREEN#10 ) + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte*) SCREEN#10 ← phi( main::@3/(byte*) SCREEN#4 ) + (byte) main::k#3 ← phi( main::@3/(byte) main::k#2 ) + (byte) main::k#1 ← ++ (byte) main::k#3 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + (byte*) SCREEN#11 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +INITIAL SSA SYMBOL TABLE +(label) @2 +(label) @3 +(label) @begin +(label) @end +(byte*) SCREEN +(byte*) SCREEN#0 +(byte*) SCREEN#1 +(byte*) SCREEN#10 +(byte*) SCREEN#11 +(byte*) SCREEN#2 +(byte*) SCREEN#3 +(byte*) SCREEN#4 +(byte*) SCREEN#5 +(byte*) SCREEN#6 +(byte*) SCREEN#7 +(byte*) SCREEN#8 +(byte*) SCREEN#9 +(void()) main() +(boolean~) main::$1 +(boolean~) main::$3 +(boolean~) main::$5 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::i#3 +(byte) main::j +(byte) main::j#0 +(byte) main::j#1 +(byte) main::j#2 +(byte) main::j#3 +(byte) main::k +(byte) main::k#0 +(byte) main::k#1 +(byte) main::k#2 +(byte) main::k#3 +(void()) plot((byte) plot::x) +(label) plot::@return +(byte) plot::x +(byte) plot::x#0 +(byte) plot::x#1 +(byte) plot::x#2 +(byte) plot::x#3 + +Culled Empty Block (label) @3 +Succesful SSA optimization Pass2CullEmptyBlocks +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte*) SCREEN#5 ← phi( @2/(byte*) SCREEN#11 ) + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#5 main::@7/(byte*) SCREEN#6 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte*) SCREEN#6 ← phi( main::@1/(byte*) SCREEN#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte) main::i#1 ← ++ (byte) main::i#3 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte*) SCREEN#7 ← phi( main::@7/(byte*) SCREEN#6 ) + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte*) SCREEN#3 ← phi( main::@4/(byte*) SCREEN#7 main::@8/(byte*) SCREEN#8 ) + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte*) SCREEN#8 ← phi( main::@2/(byte*) SCREEN#3 ) + (byte) main::j#3 ← phi( main::@2/(byte) main::j#2 ) + (byte) main::j#1 ← ++ (byte) main::j#3 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte*) SCREEN#9 ← phi( main::@8/(byte*) SCREEN#8 ) + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte*) SCREEN#4 ← phi( main::@5/(byte*) SCREEN#9 main::@9/(byte*) SCREEN#10 ) + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte*) SCREEN#10 ← phi( main::@3/(byte*) SCREEN#4 ) + (byte) main::k#3 ← phi( main::@3/(byte) main::k#2 ) + (byte) main::k#1 ← ++ (byte) main::k#3 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#4 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + (byte*) SCREEN#11 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@end +@end: scope:[] from @2 + +Not aliassing across scopes: plot::x#0 main::i#2 +Not aliassing across scopes: plot::x#1 main::j#2 +Not aliassing across scopes: plot::x#2 main::k#2 +Alias (byte*) SCREEN#0 = (byte*) SCREEN#5 (byte*) SCREEN#11 +Alias (byte) main::i#2 = (byte) main::i#3 +Alias (byte*) SCREEN#2 = (byte*) SCREEN#6 (byte*) SCREEN#7 +Alias (byte) main::j#2 = (byte) main::j#3 +Alias (byte*) SCREEN#3 = (byte*) SCREEN#8 (byte*) SCREEN#9 +Alias (byte) main::k#2 = (byte) main::k#3 +Alias (byte*) SCREEN#10 = (byte*) SCREEN#4 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#0 main::@7/(byte*) SCREEN#2 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte*) SCREEN#3 ← phi( main::@4/(byte*) SCREEN#2 main::@8/(byte*) SCREEN#3 ) + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte*) SCREEN#10 ← phi( main::@5/(byte*) SCREEN#3 main::@9/(byte*) SCREEN#10 ) + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#10 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Not aliassing across scopes: plot::x#0 main::i#2 +Not aliassing across scopes: plot::x#1 main::j#2 +Not aliassing across scopes: plot::x#2 main::k#2 +Self Phi Eliminated (byte*) SCREEN#2 +Self Phi Eliminated (byte*) SCREEN#3 +Self Phi Eliminated (byte*) SCREEN#10 +Succesful SSA optimization Pass2SelfPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte*) SCREEN#2 ← phi( main/(byte*) SCREEN#0 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte*) SCREEN#3 ← phi( main::@4/(byte*) SCREEN#2 ) + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte*) SCREEN#10 ← phi( main::@5/(byte*) SCREEN#3 ) + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#2 main::@2/(byte*) SCREEN#3 main::@3/(byte*) SCREEN#10 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Redundant Phi (byte*) SCREEN#2 (byte*) SCREEN#0 +Redundant Phi (byte*) SCREEN#3 (byte*) SCREEN#2 +Redundant Phi (byte*) SCREEN#10 (byte*) SCREEN#3 +Succesful SSA optimization Pass2RedundantPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + (byte*) SCREEN#1 ← phi( main::@1/(byte*) SCREEN#0 main::@2/(byte*) SCREEN#0 main::@3/(byte*) SCREEN#0 ) + *((byte*) SCREEN#1 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Redundant Phi (byte*) SCREEN#1 (byte*) SCREEN#0 +Succesful SSA optimization Pass2RedundantPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$1 ← (byte) main::i#1 != (byte) 11 + if((boolean~) main::$1) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$3 ← (byte) main::j#1 != (byte) 11 + if((boolean~) main::$3) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + (boolean~) main::$5 ← (byte) main::k#1 != (byte) 11 + if((boolean~) main::$5) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + *((byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Simple Condition (boolean~) main::$1 if((byte) main::i#1!=(byte) 11) goto main::@1 +Simple Condition (boolean~) main::$3 if((byte) main::j#1!=(byte) 11) goto main::@2 +Simple Condition (boolean~) main::$5 if((byte) main::k#1!=(byte) 11) goto main::@3 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← (word) 1024 + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte) 11) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + (byte) main::j#0 ← (byte) 0 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte) main::j#2 ← phi( main::@4/(byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + if((byte) main::j#1!=(byte) 11) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + (byte) main::k#0 ← (byte) 0 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte) main::k#2 ← phi( main::@5/(byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + if((byte) main::k#1!=(byte) 11) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + *((byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Constant (const byte*) SCREEN#0 = 1024 +Constant (const byte) main::i#0 = 0 +Constant (const byte) main::j#0 = 0 +Constant (const byte) main::k#0 = 0 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte) 11) goto main::@1 + to:main::@4 +main::@4: scope:[main] from main::@7 + to:main::@2 +main::@2: scope:[main] from main::@4 main::@8 + (byte) main::j#2 ← phi( main::@4/(const byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + if((byte) main::j#1!=(byte) 11) goto main::@2 + to:main::@5 +main::@5: scope:[main] from main::@8 + to:main::@3 +main::@3: scope:[main] from main::@5 main::@9 + (byte) main::k#2 ← phi( main::@5/(const byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + if((byte) main::k#1!=(byte) 11) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Culled Empty Block (label) main::@4 +Culled Empty Block (label) main::@5 +Succesful SSA optimization Pass2CullEmptyBlocks +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte) 11) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@7 main::@8 + (byte) main::j#2 ← phi( main::@7/(const byte) main::j#0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + if((byte) main::j#1!=(byte) 11) goto main::@2 + to:main::@3 +main::@3: scope:[main] from main::@8 main::@9 + (byte) main::k#2 ← phi( main::@8/(const byte) main::k#0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + if((byte) main::k#1!=(byte) 11) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Not aliassing across scopes: plot::x#0 main::i#2 +Not aliassing across scopes: plot::x#1 main::j#2 +Not aliassing across scopes: plot::x#2 main::k#2 +Not aliassing across scopes: plot::x#0 main::i#2 +Not aliassing across scopes: plot::x#1 main::j#2 +Not aliassing across scopes: plot::x#2 main::k#2 +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) main::j#0 +Inlining constant with var siblings (const byte) main::j#0 +Inlining constant with var siblings (const byte) main::k#0 +Inlining constant with var siblings (const byte) main::k#0 +Constant inlined main::k#0 = (byte) 0 +Constant inlined main::j#0 = (byte) 0 +Constant inlined main::i#0 = (byte) 0 +Succesful SSA optimization Pass2ConstantInlining +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + to:main::@1 +main::@1: scope:[main] from main main::@7 + (byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte) main::i#1 ) + (byte) plot::x#0 ← (byte) main::i#2 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte) 11) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@7 main::@8 + (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@8/(byte) main::j#1 ) + (byte) plot::x#1 ← (byte) main::j#2 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + if((byte) main::j#1!=(byte) 11) goto main::@2 + to:main::@3 +main::@3: scope:[main] from main::@8 main::@9 + (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@9/(byte) main::k#1 ) + (byte) plot::x#2 ← (byte) main::k#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + if((byte) main::k#1!=(byte) 11) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) + *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 = (word) 1024 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return +(byte) main::i +(byte) main::i#1 +(byte) main::i#2 +(byte) main::j +(byte) main::j#1 +(byte) main::j#2 +(byte) main::k +(byte) main::k#1 +(byte) main::k#2 +(void()) plot((byte) plot::x) +(label) plot::@return +(byte) plot::x +(byte) plot::x#0 +(byte) plot::x#1 +(byte) plot::x#2 +(byte) plot::x#3 + +Block Sequence Planned @begin @2 @end main main::@1 main::@7 main::@2 main::@8 main::@3 main::@9 main::@return plot plot::@return +Added new block during phi lifting main::@10(between main::@7 and main::@1) +Added new block during phi lifting main::@11(between main::@8 and main::@2) +Added new block during phi lifting main::@12(between main::@9 and main::@3) +Block Sequence Planned @begin @2 @end main main::@1 main::@7 main::@2 main::@8 main::@3 main::@9 main::@return main::@12 main::@11 main::@10 plot plot::@return +CONTROL FLOW GRAPH - PHI LIFTED +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + to:main::@1 +main::@1: scope:[main] from main main::@10 + (byte) main::i#2 ← phi( main/(byte) 0 main::@10/(byte~) main::i#4 ) + (byte) plot::x#0 ← (byte) main::i#2 + (byte~) plot::x#4 ← (byte) plot::x#0 + call plot param-assignment + to:main::@7 +main::@7: scope:[main] from main::@1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte) 11) goto main::@10 + to:main::@2 +main::@2: scope:[main] from main::@11 main::@7 + (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@11/(byte~) main::j#4 ) + (byte) plot::x#1 ← (byte) main::j#2 + (byte~) plot::x#5 ← (byte) plot::x#1 + call plot param-assignment + to:main::@8 +main::@8: scope:[main] from main::@2 + (byte) main::j#1 ← ++ (byte) main::j#2 + if((byte) main::j#1!=(byte) 11) goto main::@11 + to:main::@3 +main::@3: scope:[main] from main::@12 main::@8 + (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@12/(byte~) main::k#4 ) + (byte) plot::x#2 ← (byte) main::k#2 + (byte~) plot::x#6 ← (byte) plot::x#2 + call plot param-assignment + to:main::@9 +main::@9: scope:[main] from main::@3 + (byte) main::k#1 ← ++ (byte) main::k#2 + if((byte) main::k#1!=(byte) 11) goto main::@12 + to:main::@return +main::@return: scope:[main] from main::@9 + return + to:@return +main::@12: scope:[main] from main::@9 + (byte~) main::k#4 ← (byte) main::k#1 + to:main::@3 +main::@11: scope:[main] from main::@8 + (byte~) main::j#4 ← (byte) main::j#1 + to:main::@2 +main::@10: scope:[main] from main::@7 + (byte~) main::i#4 ← (byte) main::i#1 + to:main::@1 +plot: scope:[plot] from main::@1 main::@2 main::@3 + (byte) plot::x#3 ← phi( main::@1/(byte~) plot::x#4 main::@2/(byte~) plot::x#5 main::@3/(byte~) plot::x#6 ) + *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' + to:plot::@return +plot::@return: scope:[plot] from plot + return + to:@return + +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to 0:main +Calls in [main] to 5:plot 11:plot 17:plot + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES FOUND +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@10 + [2] (byte) main::i#2 ← phi( main/(byte) 0 main::@10/(byte~) main::i#4 ) [ main::i#2 ] + [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] + [4] (byte~) plot::x#4 ← (byte) plot::x#0 [ main::i#2 plot::x#4 ] + [5] call plot param-assignment [ main::i#2 ] + to:main::@7 +main::@7: scope:[main] from main::@1 + [6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + [7] if((byte) main::i#1!=(byte) 11) goto main::@10 [ main::i#1 ] + to:main::@2 +main::@2: scope:[main] from main::@11 main::@7 + [8] (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@11/(byte~) main::j#4 ) [ main::j#2 ] + [9] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] + [10] (byte~) plot::x#5 ← (byte) plot::x#1 [ main::j#2 plot::x#5 ] + [11] call plot param-assignment [ main::j#2 ] + to:main::@8 +main::@8: scope:[main] from main::@2 + [12] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] + [13] if((byte) main::j#1!=(byte) 11) goto main::@11 [ main::j#1 ] + to:main::@3 +main::@3: scope:[main] from main::@12 main::@8 + [14] (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@12/(byte~) main::k#4 ) [ main::k#2 ] + [15] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] + [16] (byte~) plot::x#6 ← (byte) plot::x#2 [ main::k#2 plot::x#6 ] + [17] call plot param-assignment [ main::k#2 ] + to:main::@9 +main::@9: scope:[main] from main::@3 + [18] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] + [19] if((byte) main::k#1!=(byte) 11) goto main::@12 [ main::k#1 ] + to:main::@return +main::@return: scope:[main] from main::@9 + [20] return [ ] + to:@return +main::@12: scope:[main] from main::@9 + [21] (byte~) main::k#4 ← (byte) main::k#1 [ main::k#4 ] + to:main::@3 +main::@11: scope:[main] from main::@8 + [22] (byte~) main::j#4 ← (byte) main::j#1 [ main::j#4 ] + to:main::@2 +main::@10: scope:[main] from main::@7 + [23] (byte~) main::i#4 ← (byte) main::i#1 [ main::i#4 ] + to:main::@1 +plot: scope:[plot] from main::@1 main::@2 main::@3 + [24] (byte) plot::x#3 ← phi( main::@1/(byte~) plot::x#4 main::@2/(byte~) plot::x#5 main::@3/(byte~) plot::x#6 ) [ plot::x#3 ] + [25] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] + to:plot::@return +plot::@return: scope:[plot] from plot + [26] return [ ] + to:@return + +Created 4 initial phi equivalence classes +Coalesced [4] plot::x#4 ← plot::x#0 +Coalesced [10] plot::x#5 ← plot::x#1 +Coalesced [16] plot::x#6 ← plot::x#2 +Coalesced [21] main::k#4 ← main::k#1 +Coalesced [22] main::j#4 ← main::j#1 +Coalesced [23] main::i#4 ← main::i#1 +Coalesced down to 4 phi equivalence classes +Culled Empty Block (label) main::@12 +Culled Empty Block (label) main::@11 +Culled Empty Block (label) main::@10 +Block Sequence Planned @begin @2 @end main main::@1 main::@7 main::@2 main::@8 main::@3 main::@9 main::@return plot plot::@return +Adding NOP phi() at start of main +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@7 + [2] (byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte) main::i#1 ) [ main::i#2 ] + [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] + [4] call plot param-assignment [ main::i#2 ] + to:main::@7 +main::@7: scope:[main] from main::@1 + [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] + to:main::@2 +main::@2: scope:[main] from main::@7 main::@8 + [7] (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@8/(byte) main::j#1 ) [ main::j#2 ] + [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] + [9] call plot param-assignment [ main::j#2 ] + to:main::@8 +main::@8: scope:[main] from main::@2 + [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] + [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] + to:main::@3 +main::@3: scope:[main] from main::@8 main::@9 + [12] (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@9/(byte) main::k#1 ) [ main::k#2 ] + [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] + [14] call plot param-assignment [ main::k#2 ] + to:main::@9 +main::@9: scope:[main] from main::@3 + [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] + [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] + to:main::@return +main::@return: scope:[main] from main::@9 + [17] return [ ] + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + [18] (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) [ plot::x#3 ] + [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] + to:plot::@return +plot::@return: scope:[plot] from plot + [20] return [ ] + to:@return + +CONTROL FLOW GRAPH - PHI MEM COALESCED +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + [1] phi() [ ] ( [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@7 + [2] (byte) main::i#2 ← phi( main/(byte) 0 main::@7/(byte) main::i#1 ) [ main::i#2 ] ( [ main::i#2 ] ) + [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + to:main::@7 +main::@7: scope:[main] from main::@1 + [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) + [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) + to:main::@2 +main::@2: scope:[main] from main::@7 main::@8 + [7] (byte) main::j#2 ← phi( main::@7/(byte) 0 main::@8/(byte) main::j#1 ) [ main::j#2 ] ( [ main::j#2 ] ) + [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + to:main::@8 +main::@8: scope:[main] from main::@2 + [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) + [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) + to:main::@3 +main::@3: scope:[main] from main::@8 main::@9 + [12] (byte) main::k#2 ← phi( main::@8/(byte) 0 main::@9/(byte) main::k#1 ) [ main::k#2 ] ( [ main::k#2 ] ) + [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + to:main::@9 +main::@9: scope:[main] from main::@3 + [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) + [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@9 + [17] return [ ] ( [ ] ) + to:@return +plot: scope:[plot] from main::@1 main::@2 main::@3 + [18] (byte) plot::x#3 ← phi( main::@1/(byte) plot::x#0 main::@2/(byte) plot::x#1 main::@3/(byte) plot::x#2 ) [ plot::x#3 ] ( [ main::i#2 plot::x#3 ] [ main::j#2 plot::x#3 ] [ main::k#2 plot::x#3 ] ) + [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + to:plot::@return +plot::@return: scope:[plot] from plot + [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@2 dominated by @2 @begin +@end dominated by @2 @end @begin +main dominated by @2 @begin main +main::@1 dominated by @2 @begin main::@1 main +main::@7 dominated by main::@7 @2 @begin main::@1 main +main::@2 dominated by main::@7 @2 @begin main::@2 main::@1 main +main::@8 dominated by main::@7 main::@8 @2 @begin main::@2 main::@1 main +main::@3 dominated by main::@7 main::@8 @2 @begin main::@2 main::@1 main::@3 main +main::@9 dominated by main::@7 main::@8 main::@9 @2 @begin main::@2 main::@1 main::@3 main +main::@return dominated by main::@7 main::@8 main::@9 @2 main::@return @begin main::@2 main::@1 main::@3 main +plot dominated by @2 @begin main::@1 plot main +plot::@return dominated by @2 @begin main::@1 plot::@return plot main + +Found back edge: Loop head: main::@1 tails: main::@7 blocks: null +Found back edge: Loop head: main::@2 tails: main::@8 blocks: null +Found back edge: Loop head: main::@3 tails: main::@9 blocks: null +Populated: Loop head: main::@1 tails: main::@7 blocks: main::@7 main::@1 +Populated: Loop head: main::@2 tails: main::@8 blocks: main::@8 main::@2 +Populated: Loop head: main::@3 tails: main::@9 blocks: main::@9 main::@3 +NATURAL LOOPS +Loop head: main::@1 tails: main::@7 blocks: main::@7 main::@1 +Loop head: main::@2 tails: main::@8 blocks: main::@8 main::@2 +Loop head: main::@3 tails: main::@9 blocks: main::@9 main::@3 + +Found 0 loops in scope [] +Found 3 loops in scope [main] + Loop head: main::@1 tails: main::@7 blocks: main::@7 main::@1 + Loop head: main::@2 tails: main::@8 blocks: main::@8 main::@2 + Loop head: main::@3 tails: main::@9 blocks: main::@9 main::@3 +Found 0 loops in scope [plot] +NATURAL LOOPS WITH DEPTH +Loop head: main::@1 tails: main::@7 blocks: main::@7 main::@1 depth: 1 +Loop head: main::@2 tails: main::@8 blocks: main::@8 main::@2 depth: 1 +Loop head: main::@3 tails: main::@9 blocks: main::@9 main::@3 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(byte*) SCREEN +(void()) main() +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 11.0 +(byte) main::j +(byte) main::j#1 16.5 +(byte) main::j#2 11.0 +(byte) main::k +(byte) main::k#1 16.5 +(byte) main::k#2 11.0 +(void()) plot((byte) plot::x) +(byte) plot::x +(byte) plot::x#0 22.0 +(byte) plot::x#1 22.0 +(byte) plot::x#2 22.0 +(byte) plot::x#3 35.0 + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#2 main::j#1 ] +[ main::k#2 main::k#1 ] +[ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#2 main::j#1 ] +[ main::k#2 main::k#1 ] +[ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] +Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Allocated zp ZP_BYTE:3 [ main::j#2 main::j#1 ] +Allocated zp ZP_BYTE:4 [ main::k#2 main::k#1 ] +Allocated zp ZP_BYTE:5 [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +bbegin: + jmp b2 +//SEG3 @2 +b2: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main + jmp bend +//SEG6 @end +bend: +//SEG7 main +main: { + .label i = 2 + .label j = 3 + .label k = 4 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- zpby1=coby1 + lda #0 + sta i + jmp b1 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + b1_from_b7: + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + jmp b1 + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) -- zpby1=zpby2 + lda i + sta plot.x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + plot_from_b1: + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + jmp b7 + //SEG17 main::@7 + b7: + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- zpby1=_inc_zpby1 + inc i + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- zpby1_neq_coby1_then_la1 + lda i + cmp #$b + bne b1_from_b7 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + b2_from_b7: + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- zpby1=coby1 + lda #0 + sta j + jmp b2 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + b2_from_b8: + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + jmp b2 + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) -- zpby1=zpby2 + lda j + sta plot.x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + plot_from_b2: + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + jmp b8 + //SEG29 main::@8 + b8: + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- zpby1=_inc_zpby1 + inc j + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- zpby1_neq_coby1_then_la1 + lda j + cmp #$b + bne b2_from_b8 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + b3_from_b8: + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- zpby1=coby1 + lda #0 + sta k + jmp b3 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + b3_from_b9: + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + jmp b3 + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) -- zpby1=zpby2 + lda k + sta plot.x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + plot_from_b3: + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + jmp b9 + //SEG41 main::@9 + b9: + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- zpby1=_inc_zpby1 + inc k + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- zpby1_neq_coby1_then_la1 + lda k + cmp #$b + bne b3_from_b9 + jmp breturn + //SEG44 main::@return + breturn: + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + .label x = 5 + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_zpby1=coby2 + lda #'*' + ldx x + sta SCREEN,x + jmp breturn + //SEG48 plot::@return + breturn: + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::j#2 main::j#1 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ main::k#2 main::k#1 ] +Statement [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ main::j#2 main::j#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:4 [ main::k#2 main::k#1 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:5 [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [plot] 101: zp ZP_BYTE:5 [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] +Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 27.5: zp ZP_BYTE:3 [ main::j#2 main::j#1 ] 27.5: zp ZP_BYTE:4 [ main::k#2 main::k#1 ] +Uplift Scope [] + +Uplifting [plot] best 913 combination reg byte x [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] +Uplifting [main] best 553 combination reg byte x [ main::i#2 main::i#1 ] reg byte x [ main::j#2 main::j#1 ] reg byte x [ main::k#2 main::k#1 ] +Uplifting [] best 553 combination +Removing instruction jmp b2 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b7 +Removing instruction jmp b2 +Removing instruction jmp b8 +Removing instruction jmp b3 +Removing instruction jmp b9 +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +bbegin: +//SEG3 @2 +b2: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + b1_from_b7: + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + // (byte) plot::x#0 = (byte) main::i#2 // register copy reg byte x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + plot_from_b1: + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + //SEG17 main::@7 + b7: + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1_from_b7 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + b2_from_b7: + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- xby=coby1 + ldx #0 + jmp b2 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + b2_from_b8: + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + // (byte) plot::x#1 = (byte) main::j#2 // register copy reg byte x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + plot_from_b2: + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + //SEG29 main::@8 + b8: + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby=_inc_xby + inx + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b2_from_b8 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + b3_from_b8: + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- xby=coby1 + ldx #0 + jmp b3 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + b3_from_b9: + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + // (byte) plot::x#2 = (byte) main::k#2 // register copy reg byte x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + plot_from_b3: + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + //SEG41 main::@9 + b9: + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- xby=_inc_xby + inx + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b3_from_b9 + //SEG44 main::@return + breturn: + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_xby=coby2 + lda #'*' + sta SCREEN,x + //SEG48 plot::@return + breturn: + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + +Replacing label b1_from_b7 with b1 +Replacing label b2_from_b8 with b2 +Replacing label b3_from_b9 with b3 +Removing instruction bbegin: +Removing instruction main_from_b2: +Removing instruction b1_from_b7: +Removing instruction b2_from_b8: +Removing instruction b3_from_b9: +Succesful ASM optimization Pass5RedundantLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +//SEG3 @2 +b2: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + // (byte) plot::x#0 = (byte) main::i#2 // register copy reg byte x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + plot_from_b1: + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + //SEG17 main::@7 + b7: + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + b2_from_b7: + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- xby=coby1 + ldx #0 + jmp b2 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + // (byte) plot::x#1 = (byte) main::j#2 // register copy reg byte x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + plot_from_b2: + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + //SEG29 main::@8 + b8: + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby=_inc_xby + inx + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b2 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + b3_from_b8: + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- xby=coby1 + ldx #0 + jmp b3 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + // (byte) plot::x#2 = (byte) main::k#2 // register copy reg byte x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + plot_from_b3: + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + //SEG41 main::@9 + b9: + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- xby=_inc_xby + inx + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b3 + //SEG44 main::@return + breturn: + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_xby=coby2 + lda #'*' + sta SCREEN,x + //SEG48 plot::@return + breturn: + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + +Removing instruction b2: +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction plot_from_b1: +Removing instruction b7: +Removing instruction b2_from_b7: +Removing instruction plot_from_b2: +Removing instruction b8: +Removing instruction b3_from_b8: +Removing instruction plot_from_b3: +Removing instruction b9: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +//SEG3 @2 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + // (byte) plot::x#0 = (byte) main::i#2 // register copy reg byte x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + //SEG17 main::@7 + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- xby=coby1 + ldx #0 + jmp b2 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + // (byte) plot::x#1 = (byte) main::j#2 // register copy reg byte x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + //SEG29 main::@8 + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby=_inc_xby + inx + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b2 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- xby=coby1 + ldx #0 + jmp b3 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + // (byte) plot::x#2 = (byte) main::k#2 // register copy reg byte x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + //SEG41 main::@9 + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- xby=_inc_xby + inx + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b3 + //SEG44 main::@return + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_xby=coby2 + lda #'*' + sta SCREEN,x + //SEG48 plot::@return + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +//SEG3 @2 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + // (byte) plot::x#0 = (byte) main::i#2 // register copy reg byte x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + //SEG17 main::@7 + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- xby=coby1 + ldx #0 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + // (byte) plot::x#1 = (byte) main::j#2 // register copy reg byte x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + //SEG29 main::@8 + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby=_inc_xby + inx + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b2 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- xby=coby1 + ldx #0 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + // (byte) plot::x#2 = (byte) main::k#2 // register copy reg byte x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + //SEG41 main::@9 + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- xby=_inc_xby + inx + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b3 + //SEG44 main::@return + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_xby=coby2 + lda #'*' + sta SCREEN,x + //SEG48 plot::@return + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = (word) 1024 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 11.0 +(byte) main::j +(byte) main::j#1 reg byte x 16.5 +(byte) main::j#2 reg byte x 11.0 +(byte) main::k +(byte) main::k#1 reg byte x 16.5 +(byte) main::k#2 reg byte x 11.0 +(void()) plot((byte) plot::x) +(label) plot::@return +(byte) plot::x +(byte) plot::x#0 reg byte x 22.0 +(byte) plot::x#1 reg byte x 22.0 +(byte) plot::x#2 reg byte x 22.0 +(byte) plot::x#3 reg byte x 35.0 + +reg byte x [ main::i#2 main::i#1 ] +reg byte x [ main::j#2 main::j#1 ] +reg byte x [ main::k#2 main::k#1 ] +reg byte x [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ] + +FINAL CODE +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 +//SEG2 @begin +//SEG3 @2 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @2 to main [phi:@2->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 [2] phi from main::@7 to main::@1 [phi:main::@7->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@7->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte) plot::x#0 ← (byte) main::i#2 [ main::i#2 plot::x#0 ] ( [ main::i#2 plot::x#0 ] ) + // (byte) plot::x#0 = (byte) main::i#2 // register copy reg byte x + //SEG14 [4] call plot param-assignment [ main::i#2 ] ( [ main::i#2 ] ) + //SEG15 [18] phi from main::@1 to plot [phi:main::@1->plot] + //SEG16 [18] phi (byte) plot::x#3 = (byte) plot::x#0 [phi:main::@1->plot#0] -- register_copy + jsr plot + //SEG17 main::@7 + //SEG18 [5] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [6] if((byte) main::i#1!=(byte) 11) goto main::@1 [ main::i#1 ] ( [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG20 [7] phi from main::@7 to main::@2 [phi:main::@7->main::@2] + //SEG21 [7] phi (byte) main::j#2 = (byte) 0 [phi:main::@7->main::@2#0] -- xby=coby1 + ldx #0 + //SEG22 [7] phi from main::@8 to main::@2 [phi:main::@8->main::@2] + //SEG23 [7] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@8->main::@2#0] -- register_copy + //SEG24 main::@2 + b2: + //SEG25 [8] (byte) plot::x#1 ← (byte) main::j#2 [ main::j#2 plot::x#1 ] ( [ main::j#2 plot::x#1 ] ) + // (byte) plot::x#1 = (byte) main::j#2 // register copy reg byte x + //SEG26 [9] call plot param-assignment [ main::j#2 ] ( [ main::j#2 ] ) + //SEG27 [18] phi from main::@2 to plot [phi:main::@2->plot] + //SEG28 [18] phi (byte) plot::x#3 = (byte) plot::x#1 [phi:main::@2->plot#0] -- register_copy + jsr plot + //SEG29 main::@8 + //SEG30 [10] (byte) main::j#1 ← ++ (byte) main::j#2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby=_inc_xby + inx + //SEG31 [11] if((byte) main::j#1!=(byte) 11) goto main::@2 [ main::j#1 ] ( [ main::j#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b2 + //SEG32 [12] phi from main::@8 to main::@3 [phi:main::@8->main::@3] + //SEG33 [12] phi (byte) main::k#2 = (byte) 0 [phi:main::@8->main::@3#0] -- xby=coby1 + ldx #0 + //SEG34 [12] phi from main::@9 to main::@3 [phi:main::@9->main::@3] + //SEG35 [12] phi (byte) main::k#2 = (byte) main::k#1 [phi:main::@9->main::@3#0] -- register_copy + //SEG36 main::@3 + b3: + //SEG37 [13] (byte) plot::x#2 ← (byte) main::k#2 [ main::k#2 plot::x#2 ] ( [ main::k#2 plot::x#2 ] ) + // (byte) plot::x#2 = (byte) main::k#2 // register copy reg byte x + //SEG38 [14] call plot param-assignment [ main::k#2 ] ( [ main::k#2 ] ) + //SEG39 [18] phi from main::@3 to plot [phi:main::@3->plot] + //SEG40 [18] phi (byte) plot::x#3 = (byte) plot::x#2 [phi:main::@3->plot#0] -- register_copy + jsr plot + //SEG41 main::@9 + //SEG42 [15] (byte) main::k#1 ← ++ (byte) main::k#2 [ main::k#1 ] ( [ main::k#1 ] ) -- xby=_inc_xby + inx + //SEG43 [16] if((byte) main::k#1!=(byte) 11) goto main::@3 [ main::k#1 ] ( [ main::k#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b3 + //SEG44 main::@return + //SEG45 [17] return [ ] ( [ ] ) + rts +} +//SEG46 plot +plot: { + //SEG47 [19] *((const byte*) SCREEN#0 + (byte) plot::x#3) ← (byte) '*' [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) -- cowo1_staridx_xby=coby2 + lda #'*' + sta SCREEN,x + //SEG48 plot::@return + //SEG49 [20] return [ ] ( [ main::i#2 ] [ main::j#2 ] [ main::k#2 ] ) + rts +} + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.sym b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.sym new file mode 100644 index 000000000..e8ea1cc48 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/overlap-allocation.sym @@ -0,0 +1,34 @@ +(label) @2 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = (word) 1024 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@7 +(label) main::@8 +(label) main::@9 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 11.0 +(byte) main::j +(byte) main::j#1 reg byte x 16.5 +(byte) main::j#2 reg byte x 11.0 +(byte) main::k +(byte) main::k#1 reg byte x 16.5 +(byte) main::k#2 reg byte x 11.0 +(void()) plot((byte) plot::x) +(label) plot::@return +(byte) plot::x +(byte) plot::x#0 reg byte x 22.0 +(byte) plot::x#1 reg byte x 22.0 +(byte) plot::x#2 reg byte x 22.0 +(byte) plot::x#3 reg byte x 35.0 + +reg byte x [ main::i#2 main::i#1 ] +reg byte x [ main::j#2 main::j#1 ] +reg byte x [ main::k#2 main::k#1 ] +reg byte x [ plot::x#3 plot::x#0 plot::x#1 plot::x#2 ]