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 ]