mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-20 05:30:12 +00:00
Split zero page register allocation into separate phase steps. Added live range information to register allocation phases.
This commit is contained in:
parent
b4d5685222
commit
9634741d76
@ -49,7 +49,7 @@ public class Compiler {
|
||||
KickCParser.FileContext file = pass0ParseInput(input, log);
|
||||
Program program = pass1GenerateSSA(file, log);
|
||||
pass2OptimizeSSA(program, log);
|
||||
pass3LiveRangeAnalysis(program, log);
|
||||
pass3RegisterAllocation(program, log);
|
||||
AsmProgram asmProgram = pass4GenerateAsm(program, log);
|
||||
pass5OptimizeAsm(asmProgram, log);
|
||||
|
||||
@ -66,13 +66,13 @@ public class Compiler {
|
||||
}
|
||||
|
||||
public void pass5OptimizeAsm(AsmProgram asmProgram, CompileLog log) {
|
||||
List<Pass5AsmOptimization> pass4Optimizations = new ArrayList<>();
|
||||
pass4Optimizations.add(new Pass5NextJumpElimination(asmProgram, log));
|
||||
pass4Optimizations.add(new Pass5UnnecesaryLoadElimination(asmProgram, log));
|
||||
List<Pass5AsmOptimization> pass5Optimizations = new ArrayList<>();
|
||||
pass5Optimizations.add(new Pass5NextJumpElimination(asmProgram, log));
|
||||
pass5Optimizations.add(new Pass5UnnecesaryLoadElimination(asmProgram, log));
|
||||
boolean asmOptimized = true;
|
||||
while (asmOptimized) {
|
||||
asmOptimized = false;
|
||||
for (Pass5AsmOptimization optimization : pass4Optimizations) {
|
||||
for (Pass5AsmOptimization optimization : pass5Optimizations) {
|
||||
boolean stepOptimized = optimization.optimize();
|
||||
if (stepOptimized) {
|
||||
log.append("Succesful ASM optimization " + optimization.getClass().getSimpleName());
|
||||
@ -86,9 +86,6 @@ public class Compiler {
|
||||
|
||||
public AsmProgram pass4GenerateAsm(Program program, CompileLog log) {
|
||||
|
||||
Pass4ZeroPageAllocationLiveRange pass4ZeroPageAllocationLiveRange = new Pass4ZeroPageAllocationLiveRange(program, log);
|
||||
pass4ZeroPageAllocationLiveRange.allocate();
|
||||
|
||||
Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(program);
|
||||
AsmProgram asmProgram = pass4CodeGeneration.generate();
|
||||
|
||||
@ -98,54 +95,53 @@ public class Compiler {
|
||||
}
|
||||
|
||||
|
||||
private void pass3LiveRangeAnalysis(Program program, CompileLog log) {
|
||||
private void pass3RegisterAllocation(Program program, CompileLog log) {
|
||||
|
||||
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program, log);
|
||||
pass3BlockSequencePlanner.plan();
|
||||
|
||||
Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log);
|
||||
pass3PhiLifting.perform();
|
||||
new Pass3PhiLifting(program, log).perform();
|
||||
pass3BlockSequencePlanner.plan();
|
||||
log.append("CONTROL FLOW GRAPH - PHI LIFTED");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
|
||||
Pass3LiveRangesAnalysis pass3LiveRangesAnalysis = new Pass3LiveRangesAnalysis(program, log);
|
||||
pass3LiveRangesAnalysis.findLiveRanges();
|
||||
new Pass3LiveRangesAnalysis(program, log).findLiveRanges();
|
||||
log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
|
||||
Pass3PhiMemCoalesce pass3PhiMemCoalesce = new Pass3PhiMemCoalesce(program, log);
|
||||
pass3PhiMemCoalesce.optimize();
|
||||
Pass2CullEmptyBlocks cullEmptyBlocks = new Pass2CullEmptyBlocks(program, log);
|
||||
cullEmptyBlocks.optimize();
|
||||
new Pass3PhiMemCoalesce(program, log).optimize();
|
||||
new Pass2CullEmptyBlocks(program, log).optimize();
|
||||
pass3BlockSequencePlanner.plan();
|
||||
pass3LiveRangesAnalysis.findLiveRanges();
|
||||
new Pass3LiveRangesAnalysis(program, log).findLiveRanges();
|
||||
log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
|
||||
Pass3CallGraphAnalysis pass3CallGraphAnalysis = new Pass3CallGraphAnalysis(program, log);
|
||||
pass3CallGraphAnalysis.findCallGraph();
|
||||
new Pass3CallGraphAnalysis(program, log).findCallGraph();
|
||||
log.append("CALL GRAPH");
|
||||
log.append(program.getGraph().getCallGraph().toString());
|
||||
|
||||
Pass3DominatorsAnalysis pass3DominatorsAnalysis = new Pass3DominatorsAnalysis(program, log);
|
||||
pass3DominatorsAnalysis.findDominators();
|
||||
new Pass3DominatorsAnalysis(program, log).findDominators();
|
||||
log.append("DOMINATORS");
|
||||
log.append(program.getGraph().getDominators().toString());
|
||||
|
||||
Pass3LoopAnalysis pass3LoopAnalysis = new Pass3LoopAnalysis(program, log);
|
||||
pass3LoopAnalysis.findLoops();
|
||||
new Pass3LoopAnalysis(program, log).findLoops();
|
||||
log.append("NATURAL LOOPS");
|
||||
log.append(program.getGraph().getLoopSet().toString());
|
||||
|
||||
Pass3LoopDepthAnalysis pass3LoopDepthAnalysis = new Pass3LoopDepthAnalysis(program, log);
|
||||
pass3LoopDepthAnalysis.findLoopDepths();
|
||||
new Pass3LoopDepthAnalysis(program, log).findLoopDepths();
|
||||
log.append("NATURAL LOOPS WITH DEPTH");
|
||||
log.append(program.getGraph().getLoopSet().toString());
|
||||
|
||||
new Pass3ZeroPageAllocation(program, log).allocate();
|
||||
new Pass3ZeroPageCoalesce(program, log).allocate();
|
||||
new Pass3RegistersFinalize(program, log).allocate();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void pass2OptimizeSSA(Program program, CompileLog log) {
|
||||
|
@ -15,12 +15,24 @@ public class LiveRangeEquivalenceClass {
|
||||
private List<VariableRef> variables;
|
||||
|
||||
/** The combined live range of the variables. */
|
||||
private LiveRange classLiveRange;
|
||||
private LiveRange liveRange;
|
||||
|
||||
/** A register allocated to hold all variables of the equivalence class. (null if no register is currently allocated) */
|
||||
private RegisterAllocation.Register register;
|
||||
|
||||
public LiveRangeEquivalenceClass(Program program) {
|
||||
this.program = program;
|
||||
this.variables = new ArrayList<>();
|
||||
this.classLiveRange = new LiveRange();
|
||||
this.liveRange = new LiveRange();
|
||||
this.register = null;
|
||||
}
|
||||
|
||||
public RegisterAllocation.Register getRegister() {
|
||||
return register;
|
||||
}
|
||||
|
||||
public void setRegister(RegisterAllocation.Register register) {
|
||||
this.register = register;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,12 +44,12 @@ public class LiveRangeEquivalenceClass {
|
||||
if(variables.contains(variable)) {
|
||||
return;
|
||||
}
|
||||
LiveRangeVariables liveRanges = program.getScope().getLiveRanges();
|
||||
LiveRangeVariables liveRanges = program.getScope().getLiveRangeVariables();
|
||||
LiveRange varLiveRange = liveRanges.getLiveRange(variable);
|
||||
if (classLiveRange.overlaps(varLiveRange)) {
|
||||
if (liveRange.overlaps(varLiveRange)) {
|
||||
throw new RuntimeException("Compilation error! Variable live range overlaps live range equivalence class live range. " + variable);
|
||||
}
|
||||
classLiveRange.add(varLiveRange);
|
||||
liveRange.add(varLiveRange);
|
||||
variables.add(variable);
|
||||
}
|
||||
|
||||
@ -52,12 +64,12 @@ public class LiveRangeEquivalenceClass {
|
||||
}
|
||||
|
||||
public LiveRange getLiveRange() {
|
||||
return classLiveRange;
|
||||
return liveRange;
|
||||
}
|
||||
|
||||
public void addAll(LiveRangeEquivalenceClass other) {
|
||||
variables.addAll(other.variables);
|
||||
classLiveRange.add(other.classLiveRange);
|
||||
liveRange.add(other.liveRange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,6 +90,9 @@ public class LiveRangeEquivalenceClass {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
if(register!=null) {
|
||||
s.append(register.toString()).append(" ");
|
||||
}
|
||||
s.append("[ ");
|
||||
for (VariableRef variable : variables) {
|
||||
s.append(variable.toString());
|
||||
|
@ -11,7 +11,9 @@ public class ProgramScope extends Scope {
|
||||
|
||||
private RegisterAllocation allocation;
|
||||
|
||||
private LiveRangeVariables liveRanges;
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
|
||||
public ProgramScope() {
|
||||
super("", null);
|
||||
@ -50,12 +52,20 @@ public class ProgramScope extends Scope {
|
||||
return allocation;
|
||||
}
|
||||
|
||||
public void setLiveRanges(LiveRangeVariables liveRanges) {
|
||||
this.liveRanges = liveRanges;
|
||||
public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
|
||||
this.liveRangeVariables = liveRangeVariables;
|
||||
}
|
||||
|
||||
public LiveRangeVariables getLiveRanges() {
|
||||
return liveRanges;
|
||||
public LiveRangeVariables getLiveRangeVariables() {
|
||||
return liveRangeVariables;
|
||||
}
|
||||
|
||||
public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
public LiveRangeEquivalenceClassSet getLiveRangeEquivalenceClassSet() {
|
||||
return liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,6 +97,19 @@ public class ProgramScope extends Scope {
|
||||
return getSymbolTableContents(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbolTableContents(ProgramScope scope) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(super.getSymbolTableContents(scope));
|
||||
if(liveRangeEquivalenceClassSet!=null) {
|
||||
out.append("\n");
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
out.append(liveRangeEquivalenceClass);
|
||||
out.append("\n");
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -40,6 +39,8 @@ public class RegisterAllocation {
|
||||
|
||||
RegisterType getType();
|
||||
|
||||
boolean isZp();
|
||||
|
||||
}
|
||||
|
||||
/** The register type. */
|
||||
@ -65,6 +66,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.ZP_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "zp byte:"+zp;
|
||||
@ -108,6 +114,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.ZP_WORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "zp word :"+zp;
|
||||
@ -151,6 +162,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.ZP_BOOL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "zp bool:"+zp;
|
||||
@ -189,6 +205,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.ZP_PTR_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "zp ptr byte:"+zp;
|
||||
@ -226,6 +247,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.REG_X_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reg byte x";
|
||||
@ -252,6 +278,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.REG_Y_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reg byte y";
|
||||
@ -278,6 +309,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.REG_A_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reg byte a";
|
||||
@ -304,6 +340,11 @@ public class RegisterAllocation {
|
||||
return RegisterType.REG_ALU_BYTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reg byte alu";
|
||||
|
@ -46,10 +46,10 @@ public abstract class StatementBase implements Statement {
|
||||
}
|
||||
|
||||
public String aliveString(ProgramScope scope) {
|
||||
if(scope==null || scope.getLiveRanges()==null) {
|
||||
if(scope==null || scope.getLiveRangeVariables()==null) {
|
||||
return "";
|
||||
}
|
||||
LiveRangeVariables liveRanges = scope.getLiveRanges();
|
||||
LiveRangeVariables liveRanges = scope.getLiveRangeVariables();
|
||||
List<VariableRef> alive = liveRanges.getAlive(this);
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(" [ ");
|
||||
|
@ -24,18 +24,18 @@ public class Pass3LiveRangesAnalysis {
|
||||
public void findLiveRanges() {
|
||||
generateStatementIndexes();
|
||||
LiveRangeVariables liveRanges = initializeLiveRanges();
|
||||
program.getScope().setLiveRanges(liveRanges);
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
//log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
//log.append(program.getGraph().toString(program.getScope()));
|
||||
boolean propagating;
|
||||
do {
|
||||
propagating = propagateLiveRanges(liveRanges);
|
||||
program.getScope().setLiveRanges(liveRanges);
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
log.append("Propagating live ranges...");
|
||||
//log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
//log.append(program.getGraph().toString(program.getScope()));
|
||||
} while (propagating);
|
||||
program.getScope().setLiveRanges(liveRanges);
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
}
|
||||
|
||||
|
||||
|
78
src/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java
Normal file
78
src/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java
Normal file
@ -0,0 +1,78 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/**
|
||||
* Move register allocation from equivalence classes to RegisterAllocation.
|
||||
* Also rebase zero page registers.
|
||||
*/
|
||||
public class Pass3RegistersFinalize {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3RegistersFinalize(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
|
||||
|
||||
RegisterAllocation allocation = new RegisterAllocation();
|
||||
for (LiveRangeEquivalenceClass equivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
RegisterAllocation.Register register = equivalenceClass.getRegister();
|
||||
if(register.isZp()) {
|
||||
String before = register.toString();
|
||||
VariableRef variable = equivalenceClass.getVariables().get(0);
|
||||
Variable symbol = program.getScope().getVariable(variable);
|
||||
register = allocateNewRegisterZp(symbol.getType());
|
||||
log.append("Re-allocated ZP register from "+before+" to "+register.toString());
|
||||
}
|
||||
for (VariableRef variable : equivalenceClass.getVariables()) {
|
||||
allocation.allocate(variable, register);
|
||||
}
|
||||
}
|
||||
program.getScope().setAllocation(allocation);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The current zero page used to create new registers when needed.
|
||||
*/
|
||||
private int currentZp = 2;
|
||||
|
||||
/**
|
||||
* Create a new register for a specific variable type.
|
||||
*
|
||||
* @param varType The variable type to create a register for.
|
||||
* The register type created uses one or more zero page locations based on the variable type
|
||||
* @return The new zeropage register
|
||||
*/
|
||||
private RegisterAllocation.Register allocateNewRegisterZp(SymbolType varType) {
|
||||
if (varType.equals(SymbolTypeBasic.BYTE)) {
|
||||
return new RegisterAllocation.RegisterZpByte(currentZp++);
|
||||
} else if (varType.equals(SymbolTypeBasic.WORD)) {
|
||||
RegisterAllocation.RegisterZpWord registerZpWord =
|
||||
new RegisterAllocation.RegisterZpWord(currentZp);
|
||||
currentZp = currentZp + 2;
|
||||
return registerZpWord;
|
||||
} else if (varType.equals(SymbolTypeBasic.BOOLEAN)) {
|
||||
return new RegisterAllocation.RegisterZpBool(currentZp++);
|
||||
} else if (varType.equals(SymbolTypeBasic.VOID)) {
|
||||
// No need to allocate register for VOID value
|
||||
return null;
|
||||
} else if (varType instanceof SymbolTypePointer) {
|
||||
RegisterAllocation.RegisterZpPointerByte registerZpPointerByte =
|
||||
new RegisterAllocation.RegisterZpPointerByte(currentZp);
|
||||
currentZp = currentZp + 2;
|
||||
return registerZpPointerByte;
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled variable type " + varType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -9,12 +9,12 @@ import java.util.List;
|
||||
/**
|
||||
* Zero Page Register Allocation for variables based on live ranges and phi equivalence classes.
|
||||
*/
|
||||
public class Pass4ZeroPageAllocationLiveRange {
|
||||
public class Pass3ZeroPageAllocation {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass4ZeroPageAllocationLiveRange(Program program, CompileLog log) {
|
||||
public Pass3ZeroPageAllocation(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
@ -51,16 +51,16 @@ public class Pass4ZeroPageAllocationLiveRange {
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
List<VariableRef> variables = liveRangeEquivalenceClass.getVariables();
|
||||
Variable firstVar = program.getScope().getVariable(variables.get(0));
|
||||
RegisterAllocation.Register zpRegister = allocateNewRegister(firstVar.getType());
|
||||
for (VariableRef variable : variables) {
|
||||
allocation.allocate(variable, zpRegister);
|
||||
}
|
||||
log.append("Allocated "+zpRegister+" to "+liveRangeEquivalenceClass);
|
||||
RegisterAllocation.Register zpRegister = allocateNewRegisterZp(firstVar.getType());
|
||||
liveRangeEquivalenceClass.setRegister(zpRegister);
|
||||
log.append("Allocated " + zpRegister + " to " + liveRangeEquivalenceClass);
|
||||
}
|
||||
program.getScope().setAllocation(allocation);
|
||||
program.getScope().setLiveRangeEquivalenceClassSet(liveRangeEquivalenceClassSet);
|
||||
}
|
||||
|
||||
/** Add all variables to a non-overlapping equivalence or create a new one. */
|
||||
/**
|
||||
* Add all variables to a non-overlapping equivalence or create a new one.
|
||||
*/
|
||||
private class EquivalenceClassAdder extends ControlFlowGraphBaseVisitor<Void> {
|
||||
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
@ -82,10 +82,10 @@ public class Pass4ZeroPageAllocationLiveRange {
|
||||
}
|
||||
|
||||
private void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences) {
|
||||
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRanges();
|
||||
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
|
||||
LiveRangeEquivalenceClass lValEquivalenceClass =
|
||||
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
|
||||
if(lValEquivalenceClass==null) {
|
||||
if (lValEquivalenceClass == null) {
|
||||
LiveRange lValLiveRange = liveRangeVariables.getLiveRange(lValVar);
|
||||
// Variable in need of an equivalence class - Look through preferences
|
||||
LiveRangeEquivalenceClass chosen = null;
|
||||
@ -104,37 +104,24 @@ public class Pass4ZeroPageAllocationLiveRange {
|
||||
}
|
||||
}
|
||||
if (chosen == null) {
|
||||
// No preference usable - look through all others
|
||||
for (LiveRangeEquivalenceClass potentialEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
VariableRef potentialVariableRef = potentialEquivalenceClass.getVariables().get(0);
|
||||
Variable potentialVariable = program.getScope().getVariable(potentialVariableRef);
|
||||
Variable lValVariable = program.getScope().getVariable(lValVar);
|
||||
if (lValVariable.getType().equals(potentialVariable.getType())) {
|
||||
if (!lValLiveRange.overlaps(potentialEquivalenceClass.getLiveRange())) {
|
||||
chosen = potentialEquivalenceClass;
|
||||
chosen.addVariable(lValVar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(chosen==null) {
|
||||
// No other equivalence class is usable - create a new one
|
||||
// No preference usable - create a new one
|
||||
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
|
||||
}
|
||||
log.append("Added variable "+lValVar+" to zero page equivalence class "+chosen);
|
||||
log.append("Added variable " + lValVar + " to zero page equivalence class " + chosen);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPreference(List<VariableRef> preferences, RValue rValue) {
|
||||
if(rValue instanceof VariableRef) {
|
||||
if (rValue instanceof VariableRef) {
|
||||
preferences.add((VariableRef) rValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Coalesce equivalence classes when they do not overlap based on all copy assignments to variables. */
|
||||
/**
|
||||
* Coalesce equivalence classes when they do not overlap based on all copy assignments to variables.
|
||||
*/
|
||||
private class EquivalenceClassCopyCoalescer extends ControlFlowGraphBaseVisitor<Void> {
|
||||
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
@ -153,11 +140,11 @@ public class Pass4ZeroPageAllocationLiveRange {
|
||||
VariableRef assignVar = (VariableRef) assignment.getrValue2();
|
||||
LiveRangeEquivalenceClass assignVarEquivalenceClass = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(assignVar);
|
||||
if (lValEquivalenceClass.equals(assignVarEquivalenceClass)) {
|
||||
log.append("Coalesced (already) " + assignment+" in "+lValEquivalenceClass);
|
||||
log.append("Coalesced (already) " + assignment + " in " + lValEquivalenceClass);
|
||||
} else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) {
|
||||
lValEquivalenceClass.addAll(assignVarEquivalenceClass);
|
||||
liveRangeEquivalenceClassSet.remove(assignVarEquivalenceClass);
|
||||
log.append("Coalesced " + assignment+" into "+lValEquivalenceClass);
|
||||
log.append("Coalesced " + assignment + " into " + lValEquivalenceClass);
|
||||
} else {
|
||||
log.append("Not coalescing " + assignment);
|
||||
}
|
||||
@ -168,16 +155,19 @@ public class Pass4ZeroPageAllocationLiveRange {
|
||||
|
||||
}
|
||||
|
||||
/** The current zero page used to create new registers when needed. */
|
||||
/**
|
||||
* The current zero page used to create new registers when needed.
|
||||
*/
|
||||
private int currentZp = 2;
|
||||
|
||||
/**
|
||||
* Create a new register for a specific variable type.
|
||||
*
|
||||
* @param varType The variable type to create a register for.
|
||||
* The register type created uses one or more zero page locations based on the variable type
|
||||
* The register type created uses one or more zero page locations based on the variable type
|
||||
* @return The new zeropage register
|
||||
*/
|
||||
private RegisterAllocation.Register allocateNewRegister(SymbolType varType) {
|
||||
private RegisterAllocation.Register allocateNewRegisterZp(SymbolType varType) {
|
||||
if (varType.equals(SymbolTypeBasic.BYTE)) {
|
||||
return new RegisterAllocation.RegisterZpByte(currentZp++);
|
||||
} else if (varType.equals(SymbolTypeBasic.WORD)) {
|
71
src/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java
Normal file
71
src/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java
Normal file
@ -0,0 +1,71 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/**
|
||||
* Coalesces zero page registers where their live ranges do not overlap.
|
||||
* A final step done after all other register optimizations and before ASM generation.
|
||||
*/
|
||||
public class Pass3ZeroPageCoalesce {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3ZeroPageCoalesce(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
|
||||
|
||||
boolean change;
|
||||
do {
|
||||
change = coalesce(liveRangeEquivalenceClassSet);
|
||||
} while (change);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find two equivalence classes that can be coalesced into one - and perform the colalescence.
|
||||
*
|
||||
* @param liveRangeEquivalenceClassSet The set of live range equivalence classes
|
||||
* @return true if any classes were coalesced. False otherwise.
|
||||
*/
|
||||
private boolean coalesce(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
for (LiveRangeEquivalenceClass myEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
for (LiveRangeEquivalenceClass otherEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
if (!myEquivalenceClass.equals(otherEquivalenceClass)) {
|
||||
if(canCoalesce(myEquivalenceClass, otherEquivalenceClass)) {
|
||||
log.append("Coalescing zero page register [ "+myEquivalenceClass+" ] with [ "+otherEquivalenceClass+" ]" );
|
||||
myEquivalenceClass.addAll(otherEquivalenceClass);
|
||||
liveRangeEquivalenceClassSet.remove(otherEquivalenceClass);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean canCoalesce(LiveRangeEquivalenceClass myEquivalenceClass, LiveRangeEquivalenceClass otherEquivalenceClass) {
|
||||
VariableRef myVariableRef = myEquivalenceClass.getVariables().get(0);
|
||||
Variable myVariable = program.getScope().getVariable(myVariableRef);
|
||||
VariableRef otherVariableRef = otherEquivalenceClass.getVariables().get(0);
|
||||
Variable otherVariable = program.getScope().getVariable(otherVariableRef);
|
||||
if (myVariable.getType().equals(otherVariable.getType())) {
|
||||
// Types match
|
||||
if (myEquivalenceClass.getRegister().isZp() && otherEquivalenceClass.getRegister().isZp()) {
|
||||
// Both registers are on Zero Page
|
||||
if (!myEquivalenceClass.getLiveRange().overlaps(otherEquivalenceClass.getLiveRange())) {
|
||||
// Live ranges do not overlap
|
||||
// Perform coalesce!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -48,6 +48,7 @@ public class Pass4RegisterAllocationTrivial {
|
||||
*/
|
||||
|
||||
// Optimal Registers for flipper-rex2.kc
|
||||
/*
|
||||
allocation.allocate(new VariableRef("plot::i#0"), RegisterAllocation.getRegisterX());
|
||||
allocation.allocate(new VariableRef("plot::i#1"), RegisterAllocation.getRegisterX());
|
||||
allocation.allocate(new VariableRef("plot::i#2"), RegisterAllocation.getRegisterX());
|
||||
@ -103,6 +104,7 @@ public class Pass4RegisterAllocationTrivial {
|
||||
allocation.allocate(new VariableRef("main::c#2"), RegisterAllocation.getRegisterX());
|
||||
allocation.allocate(new VariableRef("main::c#3"), RegisterAllocation.getRegisterX());
|
||||
allocation.allocate(new VariableRef("main::c#4"), RegisterAllocation.getRegisterX());
|
||||
*/
|
||||
|
||||
symbols.setAllocation(allocation);
|
||||
|
||||
|
@ -1019,10 +1019,14 @@ Complete equivalence classes
|
||||
[ x#2 x#1 ]
|
||||
[ e#3 e#5 e#1 e#2 ]
|
||||
[ y#2 y#4 y#1 ]
|
||||
Allocated zp ptr byte:2 to [ cursor#3 cursor#5 cursor#1 cursor#2 ]
|
||||
Allocated zp byte:4 to [ x#2 x#1 ]
|
||||
Allocated zp byte:5 to [ e#3 e#5 e#1 e#2 ]
|
||||
Allocated zp byte:6 to [ y#2 y#4 y#1 ]
|
||||
Allocated zp ptr byte:2 to zp ptr byte:2 [ cursor#3 cursor#5 cursor#1 cursor#2 ]
|
||||
Allocated zp byte:4 to zp byte:4 [ x#2 x#1 ]
|
||||
Allocated zp byte:5 to zp byte:5 [ e#3 e#5 e#1 e#2 ]
|
||||
Allocated zp byte:6 to zp byte:6 [ y#2 y#4 y#1 ]
|
||||
Re-allocated ZP register from zp ptr byte:2 to zp ptr byte:2
|
||||
Re-allocated ZP register from zp byte:4 to zp byte:4
|
||||
Re-allocated ZP register from zp byte:5 to zp byte:5
|
||||
Re-allocated ZP register from zp byte:6 to zp byte:6
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
@ -1291,6 +1295,11 @@ FINAL SYMBOL TABLE
|
||||
(byte) y1
|
||||
(byte) yd
|
||||
|
||||
zp ptr byte:2 [ cursor#3 cursor#5 cursor#1 cursor#2 ]
|
||||
zp byte:4 [ x#2 x#1 ]
|
||||
zp byte:5 [ e#3 e#5 e#1 e#2 ]
|
||||
zp byte:6 [ y#2 y#4 y#1 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
|
@ -39,29 +39,29 @@ main__Breturn:
|
||||
plot:
|
||||
plot__B1_from_plot:
|
||||
lda #16
|
||||
sta 5
|
||||
sta 2
|
||||
lda #<1236
|
||||
sta 3
|
||||
lda #>1236
|
||||
sta 3+1
|
||||
lda #0
|
||||
sta 6
|
||||
sta 5
|
||||
plot__B1_from_B3:
|
||||
plot__B1:
|
||||
plot__B2_from_B1:
|
||||
lda #0
|
||||
sta 7
|
||||
sta 6
|
||||
plot__B2_from_B2:
|
||||
plot__B2:
|
||||
ldy 6
|
||||
ldy 5
|
||||
lda 4096,y
|
||||
sta 2
|
||||
lda 2
|
||||
ldy 7
|
||||
sta (3),y
|
||||
inc 6
|
||||
inc 7
|
||||
sta 7
|
||||
lda 7
|
||||
ldy 6
|
||||
sta (3),y
|
||||
inc 5
|
||||
inc 6
|
||||
lda 6
|
||||
cmp #16
|
||||
bcc plot__B2_from_B2
|
||||
plot__B3:
|
||||
@ -72,72 +72,72 @@ plot__B3:
|
||||
bcc !+
|
||||
inc 3+1
|
||||
!:
|
||||
dec 5
|
||||
lda 5
|
||||
dec 2
|
||||
lda 2
|
||||
bne plot__B1_from_B3
|
||||
plot__Breturn:
|
||||
rts
|
||||
flip:
|
||||
flip__B1_from_flip:
|
||||
lda #16
|
||||
sta 8
|
||||
sta 2
|
||||
lda #15
|
||||
sta 10
|
||||
sta 6
|
||||
lda #0
|
||||
sta 9
|
||||
sta 5
|
||||
flip__B1_from_B4:
|
||||
flip__B1:
|
||||
flip__B2_from_B1:
|
||||
lda #16
|
||||
sta 11
|
||||
sta 7
|
||||
flip__B2_from_B2:
|
||||
flip__B2:
|
||||
ldy 9
|
||||
ldy 5
|
||||
lda 4096,y
|
||||
sta 2
|
||||
lda 2
|
||||
ldy 10
|
||||
sta 8
|
||||
lda 8
|
||||
ldy 6
|
||||
sta 4352,y
|
||||
inc 9
|
||||
lda 10
|
||||
inc 5
|
||||
lda 6
|
||||
clc
|
||||
adc #16
|
||||
sta 10
|
||||
dec 11
|
||||
lda 11
|
||||
sta 6
|
||||
dec 7
|
||||
lda 7
|
||||
bne flip__B2_from_B2
|
||||
flip__B4:
|
||||
dec 10
|
||||
dec 8
|
||||
lda 8
|
||||
dec 6
|
||||
dec 2
|
||||
lda 2
|
||||
bne flip__B1_from_B4
|
||||
flip__B3_from_B4:
|
||||
lda #0
|
||||
sta 12
|
||||
sta 2
|
||||
flip__B3_from_B3:
|
||||
flip__B3:
|
||||
ldy 12
|
||||
ldy 2
|
||||
lda 4352,y
|
||||
sta 2
|
||||
lda 2
|
||||
ldy 12
|
||||
sta 5
|
||||
lda 5
|
||||
ldy 2
|
||||
sta 4096,y
|
||||
inc 12
|
||||
lda 12
|
||||
inc 2
|
||||
lda 2
|
||||
bne flip__B3_from_B3
|
||||
flip__Breturn:
|
||||
rts
|
||||
prepare:
|
||||
prepare__B1_from_prepare:
|
||||
lda #0
|
||||
sta 13
|
||||
sta 2
|
||||
prepare__B1_from_B1:
|
||||
prepare__B1:
|
||||
ldy 13
|
||||
ldy 2
|
||||
tya
|
||||
sta 4096,y
|
||||
inc 13
|
||||
lda 13
|
||||
inc 2
|
||||
lda 2
|
||||
bne prepare__B1_from_B1
|
||||
prepare__Breturn:
|
||||
rts
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,31 +5,31 @@
|
||||
(byte[256]) buffer1
|
||||
(byte[256]) buffer2
|
||||
(void()) flip()
|
||||
(byte~) flip::$0 zp byte:2
|
||||
(byte~) flip::$4 zp byte:2
|
||||
(byte~) flip::$0 zp byte:8
|
||||
(byte~) flip::$4 zp byte:5
|
||||
(label) flip::@1
|
||||
(label) flip::@2
|
||||
(label) flip::@3
|
||||
(label) flip::@4
|
||||
(label) flip::@return
|
||||
(byte) flip::c
|
||||
(byte) flip::c#1 zp byte:11
|
||||
(byte) flip::c#2 zp byte:11
|
||||
(byte) flip::c#1 zp byte:7
|
||||
(byte) flip::c#2 zp byte:7
|
||||
(byte) flip::dstIdx
|
||||
(byte) flip::dstIdx#1 zp byte:10
|
||||
(byte) flip::dstIdx#2 zp byte:10
|
||||
(byte) flip::dstIdx#3 zp byte:10
|
||||
(byte) flip::dstIdx#5 zp byte:10
|
||||
(byte) flip::dstIdx#1 zp byte:6
|
||||
(byte) flip::dstIdx#2 zp byte:6
|
||||
(byte) flip::dstIdx#3 zp byte:6
|
||||
(byte) flip::dstIdx#5 zp byte:6
|
||||
(byte) flip::i
|
||||
(byte) flip::i#1 zp byte:12
|
||||
(byte) flip::i#2 zp byte:12
|
||||
(byte) flip::i#1 zp byte:2
|
||||
(byte) flip::i#2 zp byte:2
|
||||
(byte) flip::r
|
||||
(byte) flip::r#1 zp byte:8
|
||||
(byte) flip::r#2 zp byte:8
|
||||
(byte) flip::r#1 zp byte:2
|
||||
(byte) flip::r#2 zp byte:2
|
||||
(byte) flip::srcIdx
|
||||
(byte) flip::srcIdx#1 zp byte:9
|
||||
(byte) flip::srcIdx#2 zp byte:9
|
||||
(byte) flip::srcIdx#3 zp byte:9
|
||||
(byte) flip::srcIdx#1 zp byte:5
|
||||
(byte) flip::srcIdx#2 zp byte:5
|
||||
(byte) flip::srcIdx#3 zp byte:5
|
||||
|
||||
(void()) main()
|
||||
(byte~) main::$1 zp byte:5
|
||||
@ -46,29 +46,29 @@
|
||||
(byte) main::c#2 zp byte:2
|
||||
|
||||
(void()) plot()
|
||||
(byte~) plot::$3 zp byte:2
|
||||
(byte~) plot::$3 zp byte:7
|
||||
(label) plot::@1
|
||||
(label) plot::@2
|
||||
(label) plot::@3
|
||||
(label) plot::@return
|
||||
(byte) plot::i
|
||||
(byte) plot::i#1 zp byte:6
|
||||
(byte) plot::i#2 zp byte:6
|
||||
(byte) plot::i#3 zp byte:6
|
||||
(byte) plot::i#1 zp byte:5
|
||||
(byte) plot::i#2 zp byte:5
|
||||
(byte) plot::i#3 zp byte:5
|
||||
(byte*) plot::line
|
||||
(byte*) plot::line#1 zp ptr byte:3
|
||||
(byte*) plot::line#2 zp ptr byte:3
|
||||
(byte) plot::x
|
||||
(byte) plot::x#1 zp byte:7
|
||||
(byte) plot::x#2 zp byte:7
|
||||
(byte) plot::x#1 zp byte:6
|
||||
(byte) plot::x#2 zp byte:6
|
||||
(byte) plot::y
|
||||
(byte) plot::y#1 zp byte:5
|
||||
(byte) plot::y#2 zp byte:5
|
||||
(byte) plot::y#1 zp byte:2
|
||||
(byte) plot::y#2 zp byte:2
|
||||
|
||||
(void()) prepare()
|
||||
(label) prepare::@1
|
||||
(label) prepare::@return
|
||||
(byte) prepare::i
|
||||
(byte) prepare::i#1 zp byte:13
|
||||
(byte) prepare::i#2 zp byte:13
|
||||
(byte) prepare::i#1 zp byte:2
|
||||
(byte) prepare::i#2 zp byte:2
|
||||
|
||||
|
@ -369,8 +369,10 @@ Copy Coalesced equivalence classes
|
||||
Complete equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ s#2 s#4 s#1 ]
|
||||
Allocated zp byte:2 to [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to [ s#2 s#4 s#1 ]
|
||||
Allocated zp byte:2 to zp byte:2 [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to zp byte:3 [ s#2 s#4 s#1 ]
|
||||
Re-allocated ZP register from zp byte:2 to zp byte:2
|
||||
Re-allocated ZP register from zp byte:3 to zp byte:3
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
@ -510,6 +512,9 @@ FINAL SYMBOL TABLE
|
||||
(byte) s#2 zp byte:3
|
||||
(byte) s#4 zp byte:3
|
||||
|
||||
zp byte:2 [ i#2 i#1 ]
|
||||
zp byte:3 [ s#2 s#4 s#1 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
|
@ -26,44 +26,44 @@ main__Breturn:
|
||||
nest1:
|
||||
nest1__B1_from_nest1:
|
||||
lda #100
|
||||
sta 4
|
||||
sta 2
|
||||
nest1__B1_from_B3:
|
||||
nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
lda #100
|
||||
sta 5
|
||||
sta 3
|
||||
nest1__B2_from_B5:
|
||||
nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
dec 5
|
||||
lda 5
|
||||
dec 3
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
dec 4
|
||||
lda 4
|
||||
dec 2
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
nest2:
|
||||
nest2__B1_from_nest2:
|
||||
lda #100
|
||||
sta 6
|
||||
sta 2
|
||||
nest2__B1_from_B3:
|
||||
nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
lda #100
|
||||
sta 7
|
||||
sta 3
|
||||
nest2__B2_from_B2:
|
||||
nest2__B2:
|
||||
lda 7
|
||||
lda 3
|
||||
sta 1024
|
||||
dec 7
|
||||
lda 7
|
||||
dec 3
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
dec 6
|
||||
lda 6
|
||||
dec 2
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
rts
|
||||
|
@ -1793,12 +1793,18 @@ Complete equivalence classes
|
||||
[ nest1::j#2 nest1::j#1 ]
|
||||
[ nest2::i#2 nest2::i#1 ]
|
||||
[ nest2::j#2 nest2::j#1 ]
|
||||
Allocated zp byte:2 to [ main::i#2 main::i#1 ]
|
||||
Allocated zp byte:3 to [ main::j#2 main::j#1 ]
|
||||
Allocated zp byte:4 to [ nest1::i#2 nest1::i#1 ]
|
||||
Allocated zp byte:5 to [ nest1::j#2 nest1::j#1 ]
|
||||
Allocated zp byte:6 to [ nest2::i#2 nest2::i#1 ]
|
||||
Allocated zp byte:7 to [ nest2::j#2 nest2::j#1 ]
|
||||
Allocated zp byte:2 to zp byte:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp byte:3 to zp byte:3 [ main::j#2 main::j#1 ]
|
||||
Allocated zp byte:4 to zp byte:4 [ nest1::i#2 nest1::i#1 ]
|
||||
Allocated zp byte:5 to zp byte:5 [ nest1::j#2 nest1::j#1 ]
|
||||
Allocated zp byte:6 to zp byte:6 [ nest2::i#2 nest2::i#1 ]
|
||||
Allocated zp byte:7 to zp byte:7 [ nest2::j#2 nest2::j#1 ]
|
||||
Coalescing zero page register [ zp byte:2 [ main::i#2 main::i#1 ] ] with [ zp byte:4 [ nest1::i#2 nest1::i#1 ] ]
|
||||
Coalescing zero page register [ zp byte:2 [ main::i#2 main::i#1 nest1::i#2 nest1::i#1 ] ] with [ zp byte:6 [ nest2::i#2 nest2::i#1 ] ]
|
||||
Coalescing zero page register [ zp byte:3 [ main::j#2 main::j#1 ] ] with [ zp byte:5 [ nest1::j#2 nest1::j#1 ] ]
|
||||
Coalescing zero page register [ zp byte:3 [ main::j#2 main::j#1 nest1::j#2 nest1::j#1 ] ] with [ zp byte:7 [ nest2::j#2 nest2::j#1 ] ]
|
||||
Re-allocated ZP register from zp byte:2 to zp byte:2
|
||||
Re-allocated ZP register from zp byte:3 to zp byte:3
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
jsr main
|
||||
@ -1845,7 +1851,7 @@ nest1:
|
||||
nest1__B1_from_nest1:
|
||||
// (byte) nest1::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 4
|
||||
sta 2
|
||||
jmp nest1__B1
|
||||
nest1__B1_from_B3:
|
||||
// (byte) nest1::i#2 = (byte) nest1::i#1 // register copy
|
||||
@ -1854,7 +1860,7 @@ nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
// (byte) nest1::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 5
|
||||
sta 3
|
||||
jmp nest1__B2
|
||||
nest1__B2_from_B5:
|
||||
// (byte) nest1::j#2 = (byte) nest1::j#1 // register copy
|
||||
@ -1864,16 +1870,16 @@ nest1__B2:
|
||||
jmp nest1__B5
|
||||
nest1__B5:
|
||||
// [12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 5
|
||||
dec 3
|
||||
// [13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 5
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
jmp nest1__B3
|
||||
nest1__B3:
|
||||
// [14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 4
|
||||
dec 2
|
||||
// [15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 4
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
jmp nest1__Breturn
|
||||
nest1__Breturn:
|
||||
@ -1882,7 +1888,7 @@ nest2:
|
||||
nest2__B1_from_nest2:
|
||||
// (byte) nest2::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 6
|
||||
sta 2
|
||||
jmp nest2__B1
|
||||
nest2__B1_from_B3:
|
||||
// (byte) nest2::i#2 = (byte) nest2::i#1 // register copy
|
||||
@ -1891,26 +1897,26 @@ nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
// (byte) nest2::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 7
|
||||
sta 3
|
||||
jmp nest2__B2
|
||||
nest2__B2_from_B2:
|
||||
// (byte) nest2::j#2 = (byte) nest2::j#1 // register copy
|
||||
jmp nest2__B2
|
||||
nest2__B2:
|
||||
// [19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ] // coptr1=zpby1
|
||||
lda 7
|
||||
lda 3
|
||||
sta 1024
|
||||
// [20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 7
|
||||
dec 3
|
||||
// [21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 7
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
jmp nest2__B3
|
||||
nest2__B3:
|
||||
// [22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 6
|
||||
dec 2
|
||||
// [23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 6
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
jmp nest2__Breturn
|
||||
nest2__Breturn:
|
||||
@ -1972,7 +1978,7 @@ nest1:
|
||||
nest1__B1_from_nest1:
|
||||
// (byte) nest1::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 4
|
||||
sta 2
|
||||
jmp nest1__B1
|
||||
nest1__B1_from_B3:
|
||||
// (byte) nest1::i#2 = (byte) nest1::i#1 // register copy
|
||||
@ -1980,7 +1986,7 @@ nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
// (byte) nest1::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 5
|
||||
sta 3
|
||||
jmp nest1__B2
|
||||
nest1__B2_from_B5:
|
||||
// (byte) nest1::j#2 = (byte) nest1::j#1 // register copy
|
||||
@ -1988,15 +1994,15 @@ nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
// [12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 5
|
||||
dec 3
|
||||
// [13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 5
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
// [14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 4
|
||||
dec 2
|
||||
// [15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 4
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
@ -2004,7 +2010,7 @@ nest2:
|
||||
nest2__B1_from_nest2:
|
||||
// (byte) nest2::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 6
|
||||
sta 2
|
||||
jmp nest2__B1
|
||||
nest2__B1_from_B3:
|
||||
// (byte) nest2::i#2 = (byte) nest2::i#1 // register copy
|
||||
@ -2012,24 +2018,24 @@ nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
// (byte) nest2::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 7
|
||||
sta 3
|
||||
jmp nest2__B2
|
||||
nest2__B2_from_B2:
|
||||
// (byte) nest2::j#2 = (byte) nest2::j#1 // register copy
|
||||
nest2__B2:
|
||||
// [19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ] // coptr1=zpby1
|
||||
lda 7
|
||||
lda 3
|
||||
sta 1024
|
||||
// [20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 7
|
||||
dec 3
|
||||
// [21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 7
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
// [22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 6
|
||||
dec 2
|
||||
// [23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 6
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
rts
|
||||
@ -2079,29 +2085,29 @@ nest1:
|
||||
nest1__B1_from_nest1:
|
||||
// (byte) nest1::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 4
|
||||
sta 2
|
||||
nest1__B1_from_B3:
|
||||
// (byte) nest1::i#2 = (byte) nest1::i#1 // register copy
|
||||
nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
// (byte) nest1::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 5
|
||||
sta 3
|
||||
nest1__B2_from_B5:
|
||||
// (byte) nest1::j#2 = (byte) nest1::j#1 // register copy
|
||||
nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
// [12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 5
|
||||
dec 3
|
||||
// [13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 5
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
// [14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 4
|
||||
dec 2
|
||||
// [15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 4
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
@ -2109,30 +2115,30 @@ nest2:
|
||||
nest2__B1_from_nest2:
|
||||
// (byte) nest2::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 6
|
||||
sta 2
|
||||
nest2__B1_from_B3:
|
||||
// (byte) nest2::i#2 = (byte) nest2::i#1 // register copy
|
||||
nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
// (byte) nest2::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 7
|
||||
sta 3
|
||||
nest2__B2_from_B2:
|
||||
// (byte) nest2::j#2 = (byte) nest2::j#1 // register copy
|
||||
nest2__B2:
|
||||
// [19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ] // coptr1=zpby1
|
||||
lda 7
|
||||
lda 3
|
||||
sta 1024
|
||||
// [20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 7
|
||||
dec 3
|
||||
// [21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 7
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
// [22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 6
|
||||
dec 2
|
||||
// [23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 6
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
rts
|
||||
@ -2161,11 +2167,11 @@ FINAL SYMBOL TABLE
|
||||
(label) nest1::@5
|
||||
(label) nest1::@return
|
||||
(byte) nest1::i
|
||||
(byte) nest1::i#1 zp byte:4
|
||||
(byte) nest1::i#2 zp byte:4
|
||||
(byte) nest1::i#1 zp byte:2
|
||||
(byte) nest1::i#2 zp byte:2
|
||||
(byte) nest1::j
|
||||
(byte) nest1::j#1 zp byte:5
|
||||
(byte) nest1::j#2 zp byte:5
|
||||
(byte) nest1::j#1 zp byte:3
|
||||
(byte) nest1::j#2 zp byte:3
|
||||
|
||||
(void()) nest2()
|
||||
(label) nest2::@1
|
||||
@ -2173,13 +2179,16 @@ FINAL SYMBOL TABLE
|
||||
(label) nest2::@3
|
||||
(label) nest2::@return
|
||||
(byte) nest2::i
|
||||
(byte) nest2::i#1 zp byte:6
|
||||
(byte) nest2::i#2 zp byte:6
|
||||
(byte) nest2::i#1 zp byte:2
|
||||
(byte) nest2::i#2 zp byte:2
|
||||
(byte) nest2::j
|
||||
(byte) nest2::j#1 zp byte:7
|
||||
(byte) nest2::j#2 zp byte:7
|
||||
(byte) nest2::j#1 zp byte:3
|
||||
(byte) nest2::j#2 zp byte:3
|
||||
|
||||
|
||||
zp byte:2 [ main::i#2 main::i#1 nest1::i#2 nest1::i#1 nest2::i#2 nest2::i#1 ]
|
||||
zp byte:3 [ main::j#2 main::j#1 nest1::j#2 nest1::j#1 nest2::j#2 nest2::j#1 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
jsr main
|
||||
@ -2218,29 +2227,29 @@ nest1:
|
||||
nest1__B1_from_nest1:
|
||||
// (byte) nest1::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 4
|
||||
sta 2
|
||||
nest1__B1_from_B3:
|
||||
// (byte) nest1::i#2 = (byte) nest1::i#1 // register copy
|
||||
nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
// (byte) nest1::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 5
|
||||
sta 3
|
||||
nest1__B2_from_B5:
|
||||
// (byte) nest1::j#2 = (byte) nest1::j#1 // register copy
|
||||
nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
// [12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 5
|
||||
dec 3
|
||||
// [13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 5
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
// [14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 4
|
||||
dec 2
|
||||
// [15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 4
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
@ -2248,30 +2257,30 @@ nest2:
|
||||
nest2__B1_from_nest2:
|
||||
// (byte) nest2::i#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 6
|
||||
sta 2
|
||||
nest2__B1_from_B3:
|
||||
// (byte) nest2::i#2 = (byte) nest2::i#1 // register copy
|
||||
nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
// (byte) nest2::j#2 = (byte) 100 // zpby1=coby1
|
||||
lda #100
|
||||
sta 7
|
||||
sta 3
|
||||
nest2__B2_from_B2:
|
||||
// (byte) nest2::j#2 = (byte) nest2::j#1 // register copy
|
||||
nest2__B2:
|
||||
// [19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ] // coptr1=zpby1
|
||||
lda 7
|
||||
lda 3
|
||||
sta 1024
|
||||
// [20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ] // zpby1=_dec_zpby1
|
||||
dec 7
|
||||
dec 3
|
||||
// [21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ] // zpby1_gt_0_then_la1
|
||||
lda 7
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
// [22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ] // zpby1=_dec_zpby1
|
||||
dec 6
|
||||
dec 2
|
||||
// [23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ] // zpby1_gt_0_then_la1
|
||||
lda 6
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
rts
|
||||
|
@ -21,11 +21,11 @@
|
||||
(label) nest1::@5
|
||||
(label) nest1::@return
|
||||
(byte) nest1::i
|
||||
(byte) nest1::i#1 zp byte:4
|
||||
(byte) nest1::i#2 zp byte:4
|
||||
(byte) nest1::i#1 zp byte:2
|
||||
(byte) nest1::i#2 zp byte:2
|
||||
(byte) nest1::j
|
||||
(byte) nest1::j#1 zp byte:5
|
||||
(byte) nest1::j#2 zp byte:5
|
||||
(byte) nest1::j#1 zp byte:3
|
||||
(byte) nest1::j#2 zp byte:3
|
||||
|
||||
(void()) nest2()
|
||||
(label) nest2::@1
|
||||
@ -33,9 +33,12 @@
|
||||
(label) nest2::@3
|
||||
(label) nest2::@return
|
||||
(byte) nest2::i
|
||||
(byte) nest2::i#1 zp byte:6
|
||||
(byte) nest2::i#2 zp byte:6
|
||||
(byte) nest2::i#1 zp byte:2
|
||||
(byte) nest2::i#2 zp byte:2
|
||||
(byte) nest2::j
|
||||
(byte) nest2::j#1 zp byte:7
|
||||
(byte) nest2::j#2 zp byte:7
|
||||
(byte) nest2::j#1 zp byte:3
|
||||
(byte) nest2::j#2 zp byte:3
|
||||
|
||||
|
||||
zp byte:2 [ main::i#2 main::i#1 nest1::i#2 nest1::i#1 nest2::i#2 nest2::i#1 ]
|
||||
zp byte:3 [ main::j#2 main::j#1 nest1::j#2 nest1::j#1 nest2::j#2 nest2::j#1 ]
|
||||
|
@ -393,8 +393,10 @@ Copy Coalesced equivalence classes
|
||||
Complete equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ s#3 s#1 s#2 ]
|
||||
Allocated zp byte:2 to [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to [ s#3 s#1 s#2 ]
|
||||
Allocated zp byte:2 to zp byte:2 [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to zp byte:3 [ s#3 s#1 s#2 ]
|
||||
Re-allocated ZP register from zp byte:2 to zp byte:2
|
||||
Re-allocated ZP register from zp byte:3 to zp byte:3
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
@ -532,6 +534,9 @@ FINAL SYMBOL TABLE
|
||||
(byte) s#2 zp byte:3
|
||||
(byte) s#3 zp byte:3
|
||||
|
||||
zp byte:2 [ i#2 i#1 ]
|
||||
zp byte:3 [ s#3 s#1 s#2 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
|
@ -289,8 +289,10 @@ Added variable $1 to zero page equivalence class [ $0 $1 ]
|
||||
Complete equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ $0 $1 ]
|
||||
Allocated zp byte:2 to [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to [ $0 $1 ]
|
||||
Allocated zp byte:2 to zp byte:2 [ i#2 i#1 ]
|
||||
Allocated zp byte:3 to zp byte:3 [ $0 $1 ]
|
||||
Re-allocated ZP register from zp byte:2 to zp byte:2
|
||||
Re-allocated ZP register from zp byte:3 to zp byte:3
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
@ -404,6 +406,9 @@ FINAL SYMBOL TABLE
|
||||
(byte) i#2 zp byte:2
|
||||
(byte[16]) p
|
||||
|
||||
zp byte:2 [ i#2 i#1 ]
|
||||
zp byte:3 [ $0 $1 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
|
@ -324,8 +324,10 @@ Added variable s1#0 to zero page equivalence class [ sum::a#2 s1#0 ]
|
||||
Complete equivalence classes
|
||||
[ sum::a#2 s1#0 ]
|
||||
[ sum::b#2 ]
|
||||
Allocated zp byte:2 to [ sum::a#2 s1#0 ]
|
||||
Allocated zp byte:3 to [ sum::b#2 ]
|
||||
Allocated zp byte:2 to zp byte:2 [ sum::a#2 s1#0 ]
|
||||
Allocated zp byte:3 to zp byte:3 [ sum::b#2 ]
|
||||
Re-allocated ZP register from zp byte:2 to zp byte:2
|
||||
Re-allocated ZP register from zp byte:3 to zp byte:3
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
sum_from_BBEGIN:
|
||||
@ -407,6 +409,9 @@ FINAL SYMBOL TABLE
|
||||
(byte) sum::return
|
||||
|
||||
|
||||
zp byte:2 [ sum::a#2 s1#0 ]
|
||||
zp byte:3 [ sum::b#2 ]
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
sum_from_BBEGIN:
|
||||
|
Loading…
x
Reference in New Issue
Block a user