mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-03-24 00:30:25 +00:00
Progress on memory variables. Avoided const/alias/... passes. Added new register type and the first few fragments. The first few tests working. #328
This commit is contained in:
parent
cfff09e038
commit
7b7d7de49d
6
src/main/fragment/mos6502-common/_deref_pbum1=vbuaa.asm
Normal file
6
src/main/fragment/mos6502-common/_deref_pbum1=vbuaa.asm
Normal file
@ -0,0 +1,6 @@
|
||||
ldy {m1}
|
||||
sty $fe
|
||||
ldy {m1}+1
|
||||
sty $ff
|
||||
ldy #0
|
||||
sta ($fe),y
|
@ -0,0 +1,6 @@
|
||||
clc
|
||||
adc {m2}
|
||||
sta {m1}
|
||||
lda #0
|
||||
adc {m2}+1
|
||||
sta {m1}+1
|
4
src/main/fragment/mos6502-common/pbum1=vwuc1.asm
Normal file
4
src/main/fragment/mos6502-common/pbum1=vwuc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c1}
|
||||
sta {m1}
|
||||
lda #>{c1}
|
||||
sta {m1}+1
|
@ -227,7 +227,7 @@ public class Compiler {
|
||||
|
||||
new Pass1ProcedureCallParameters(program).generate();
|
||||
new PassNUnwindLValueLists(program).execute();
|
||||
new Pass1PointifyMemoryVariables(program).execute();
|
||||
//new Pass1PointifyMemoryVariables(program).execute();
|
||||
|
||||
//getLog().append("CONTROL FLOW GRAPH (CALL PARAMETERS)");
|
||||
//getLog().append(program.getGraph().toString(program));
|
||||
|
@ -81,6 +81,8 @@ public class AsmFragmentInstance {
|
||||
Registers.Register register = boundVar.getAllocation();
|
||||
if(register != null && register instanceof Registers.RegisterZp) {
|
||||
return new AsmParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), true);
|
||||
} else if(register!=null && register instanceof Registers.RegisterMemory) {
|
||||
return new AsmParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), false);
|
||||
} else {
|
||||
throw new RuntimeException("Register Type not implemented " + register);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ public class AsmFragmentInstanceSpecFactory {
|
||||
|
||||
/** Indexing for zeropages/constants/labels */
|
||||
private int nextZpIdx = 1;
|
||||
private int nextMemIdx = 1;
|
||||
private int nextConstIdx = 1;
|
||||
private int nextLabelIdx = 1;
|
||||
|
||||
@ -477,6 +478,10 @@ public class AsmFragmentInstanceSpecFactory {
|
||||
zpNameIdx = Integer.toString(nextZpIdx++);
|
||||
}
|
||||
return "z" + zpNameIdx;
|
||||
} else if(Registers.RegisterType.MEMORY.equals(register.getType())) {
|
||||
// TODO: Examine of Memory is already bound!
|
||||
|
||||
return "m"+(nextMemIdx++);
|
||||
} else if(Registers.RegisterType.REG_A_BYTE.equals(register.getType())) {
|
||||
return "aa";
|
||||
} else if(Registers.RegisterType.REG_X_BYTE.equals(register.getType())) {
|
||||
|
@ -81,24 +81,46 @@ public class AsmFragmentTemplate {
|
||||
// Generate a dummy instance to find clobber & cycles
|
||||
ProgramScope scope = new ProgramScope();
|
||||
LinkedHashMap<String, Value> bindings = new LinkedHashMap<>();
|
||||
Variable v1 = new Variable("$tmp1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v2 = new Variable("$tmp2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v3 = new Variable("$tmp3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v4 = new Variable("$tmp4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v5 = new Variable("$tmp5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v6 = new Variable("$tmp6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
v1.setAllocation(new Registers.RegisterZpByte(2));
|
||||
v2.setAllocation(new Registers.RegisterZpByte(4));
|
||||
v3.setAllocation(new Registers.RegisterZpByte(6));
|
||||
v4.setAllocation(new Registers.RegisterZpByte(8));
|
||||
v5.setAllocation(new Registers.RegisterZpByte(9));
|
||||
v6.setAllocation(new Registers.RegisterZpByte(10));
|
||||
if(signature.contains("z1")) bindings.put("z1", v1);
|
||||
if(signature.contains("z2")) bindings.put("z2", v2);
|
||||
if(signature.contains("z3")) bindings.put("z3", v3);
|
||||
if(signature.contains("z4")) bindings.put("z4", v4);
|
||||
if(signature.contains("z5")) bindings.put("z5", v5);
|
||||
if(signature.contains("z6")) bindings.put("z6", v6);
|
||||
{
|
||||
Variable v1 = new Variable("z1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v2 = new Variable("z2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v3 = new Variable("z3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v4 = new Variable("z4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v5 = new Variable("z5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
Variable v6 = new Variable("z6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.PHI_VERSION);
|
||||
v1.setAllocation(new Registers.RegisterZpByte(2));
|
||||
v2.setAllocation(new Registers.RegisterZpByte(4));
|
||||
v3.setAllocation(new Registers.RegisterZpByte(6));
|
||||
v4.setAllocation(new Registers.RegisterZpByte(8));
|
||||
v5.setAllocation(new Registers.RegisterZpByte(9));
|
||||
v6.setAllocation(new Registers.RegisterZpByte(10));
|
||||
if(signature.contains("z1")) bindings.put("z1", v1);
|
||||
if(signature.contains("z2")) bindings.put("z2", v2);
|
||||
if(signature.contains("z3")) bindings.put("z3", v3);
|
||||
if(signature.contains("z4")) bindings.put("z4", v4);
|
||||
if(signature.contains("z5")) bindings.put("z5", v5);
|
||||
if(signature.contains("z6")) bindings.put("z6", v6);
|
||||
}
|
||||
{
|
||||
Variable v1 = new Variable("m1", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
Variable v2 = new Variable("m2", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
Variable v3 = new Variable("m3", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
Variable v4 = new Variable("m4", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
Variable v5 = new Variable("m5", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
Variable v6 = new Variable("m6", scope, SymbolType.BYTE, null, SymbolVariable.StorageStrategy.MEMORY);
|
||||
v1.setAllocation(new Registers.RegisterMemory());
|
||||
v2.setAllocation(new Registers.RegisterMemory());
|
||||
v3.setAllocation(new Registers.RegisterMemory());
|
||||
v4.setAllocation(new Registers.RegisterMemory());
|
||||
v5.setAllocation(new Registers.RegisterMemory());
|
||||
v6.setAllocation(new Registers.RegisterMemory());
|
||||
if(signature.contains("m1")) bindings.put("m1", v1);
|
||||
if(signature.contains("m2")) bindings.put("m2", v2);
|
||||
if(signature.contains("m3")) bindings.put("m3", v3);
|
||||
if(signature.contains("m4")) bindings.put("m4", v4);
|
||||
if(signature.contains("m5")) bindings.put("m5", v5);
|
||||
if(signature.contains("m6")) bindings.put("m6", v6);
|
||||
}
|
||||
if(signature.contains("c1")) bindings.put("c1", new ConstantInteger(310L));
|
||||
if(signature.contains("c2")) bindings.put("c2", new ConstantInteger(320L));
|
||||
if(signature.contains("c3")) bindings.put("c3", new ConstantInteger(330L));
|
||||
|
@ -222,6 +222,14 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
Map<String, String> mapZ4 = new LinkedHashMap<>();
|
||||
mapZ4.put("z5", "z4");
|
||||
mapZ4.put("z6", "z5");
|
||||
// M1 is replaced by something non-mem - all above are moved down
|
||||
Map<String, String> mapM1 = new LinkedHashMap<>();
|
||||
mapM1.put("m2", "m1");
|
||||
mapM1.put("m3", "m2");
|
||||
mapM1.put("m4", "m3");
|
||||
mapM1.put("m5", "m4");
|
||||
mapM1.put("m6", "m5");
|
||||
|
||||
// C1 is replaced by something non-C - all above are moved down
|
||||
Map<String, String> mapC1 = new LinkedHashMap<>();
|
||||
mapC1.put("c2", "c1");
|
||||
@ -320,10 +328,16 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
String lvalZ1 = "...z1=.*";
|
||||
String lvalZ2 = "...z2=.*";
|
||||
String lvalZ3 = "...z3=.*";
|
||||
String lvalM1 = "...m1=.*";
|
||||
String lvalM2 = "...m2=.*";
|
||||
String lvalM3 = "...m3=.*";
|
||||
// Multiple occurences of Z1/...
|
||||
String twoZ1 = ".*z1.*z1.*";
|
||||
String twoZ2 = ".*z2.*z2.*";
|
||||
String twoZ3 = ".*z3.*z3.*";
|
||||
String twoM1 = ".*m1.*m1.*";
|
||||
String twoM2 = ".*m2.*m2.*";
|
||||
String twoM3 = ".*m3.*m3.*";
|
||||
String twoC1 = ".*c1.*c1.*";
|
||||
String twoC2 = ".*c2.*c2.*";
|
||||
String threeC1 = ".*c1.*c1.*c1.*";
|
||||
@ -331,6 +345,9 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
String threeZ2 = ".*z2.*z2.*z2.*";
|
||||
String threeZ3 = ".*z3.*z3.*z3.*";
|
||||
String threeZ4 = ".*z4.*z4.*z4.*";
|
||||
String threeM1 = ".*m1.*m1.*m1.*";
|
||||
String threeM2 = ".*m2.*m2.*m2.*";
|
||||
String threeM3 = ".*m3.*m3.*m3.*";
|
||||
String threeAa = ".*aa.*aa.*aa.*";
|
||||
|
||||
// Presence of unwanted single symbols
|
||||
@ -452,6 +469,20 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
// Replace Z3 with XX (only one)
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)z3(.*)", lvalZ3+"|"+twoZ3+"|"+rvalXx, "ldx {z3}", "$1xx$2", null, mapZ3));
|
||||
|
||||
// Replace M1 with AA (only one)
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)m1(.*)", lvalM1+"|"+rvalAa+"|"+ twoM1, "lda {m1}", "$1aa$2", null, mapM1));
|
||||
// Replace two M1s with AA
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)m1(.*vb.)m1(.*)", lvalM1+"|"+rvalAa+"|"+ threeM1, "lda {m1}", "$1aa$2aa$3", null, mapM1));
|
||||
// Replace first (not second) M1 with AA
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*vb.)m1(.*)m1(.*)", lvalM1+"|"+rvalAa, "lda {m1}", "$1aa$2m1$3", null, null));
|
||||
// Replace second (not first) M1 with AA
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)m1(.*vb.)m1(.*)", lvalM1+"|"+rvalAa, "lda {m1}", "$1m1$2aa$3", null, null));
|
||||
// Replace non-assigned M1 with AA
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(...aa)=(.*vb.)m1(.*)", rvalAa+"|"+ twoM1, "lda {m1}", "$1=$2aa$3", null, mapM1));
|
||||
// Replace assigned M1 with AA
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(vb.)m1=(.*)", twoM1, null, "$1aa=$2", "sta {m1}", mapM1));
|
||||
|
||||
|
||||
// Correct wrong ordered Z2/Z1
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)z2(.*)z1(.*)", twoZ1+"|"+twoZ2, null, "$1z1$2z2$3", null, mapZ2Swap, false));
|
||||
// Correct wrong ordered Z3/Z2
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.Value;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
@ -51,7 +52,8 @@ public class Registers {
|
||||
ZP_STRUCT,
|
||||
ZP_BOOL,
|
||||
ZP_VAR,
|
||||
CONSTANT
|
||||
CONSTANT,
|
||||
MEMORY
|
||||
}
|
||||
|
||||
/** A register used for storing a single variable. */
|
||||
@ -63,6 +65,29 @@ public class Registers {
|
||||
|
||||
}
|
||||
|
||||
public static class RegisterMemory implements Register {
|
||||
|
||||
@Override
|
||||
public RegisterType getType() {
|
||||
return RegisterType.MEMORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "mem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class RegisterZp implements Register {
|
||||
|
||||
/** The ZP address used for the byte. */
|
||||
|
@ -202,7 +202,7 @@ public abstract class SymbolVariable implements Symbol {
|
||||
}
|
||||
|
||||
public boolean isVolatile() {
|
||||
return declaredVolatile || inferedVolatile;
|
||||
return declaredVolatile || inferedVolatile || StorageStrategy.MEMORY.equals(getStorageStrategy());
|
||||
}
|
||||
|
||||
public boolean isDeclaredExport() {
|
||||
|
@ -51,6 +51,10 @@ public class Variable extends SymbolVariable {
|
||||
this.setComments(phiMaster.getComments());
|
||||
}
|
||||
|
||||
public VariableRef getRef() {
|
||||
return new VariableRef(this);
|
||||
}
|
||||
|
||||
public Registers.Register getAllocation() {
|
||||
return allocation;
|
||||
}
|
||||
@ -86,9 +90,6 @@ public class Variable extends SymbolVariable {
|
||||
return getScope().getVariable(versionOfName);
|
||||
}
|
||||
|
||||
public VariableRef getRef() {
|
||||
return new VariableRef(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
@ -115,6 +115,8 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
// Add self-assignments for all variables modified in the procedure
|
||||
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
||||
for(VariableRef modifiedVar : modifiedVars) {
|
||||
if(getScope().getVariable(modifiedVar).isStorageMemory())
|
||||
continue;
|
||||
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, origCall.getSource(), Comment.NO_COMMENTS));
|
||||
}
|
||||
return null;
|
||||
@ -132,6 +134,8 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
// Add self-assignments for all variables modified in the procedure
|
||||
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
||||
for(VariableRef modifiedVar : modifiedVars) {
|
||||
if(getScope().getVariable(modifiedVar).isStorageMemory())
|
||||
continue;
|
||||
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, orig.getSource(), Comment.NO_COMMENTS));
|
||||
}
|
||||
return super.visitReturn(orig);
|
||||
|
@ -220,6 +220,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
memberVariable.setInferedVolatile(variable.isInferedVolatile());
|
||||
memberVariable.setDeclaredConstant(variable.isDeclaredConstant());
|
||||
memberVariable.setDeclaredExport(variable.isDeclaredExport());
|
||||
if(variable.getStorageStrategy().equals(SymbolVariable.StorageStrategy.MEMORY)) {
|
||||
if(member.getStorageStrategy().equals(SymbolVariable.StorageStrategy.PHI_MASTER))
|
||||
memberVariable.setStorageStrategy(SymbolVariable.StorageStrategy.MEMORY);
|
||||
}
|
||||
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef());
|
||||
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementLValue;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@ -27,7 +28,7 @@ public class Pass2AssertSingleAssignment extends Pass2SsaAssertion {
|
||||
if(statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
checkAssignment(assignments, lValue, statement);
|
||||
checkAssignment(assignments, (VariableRef) lValue, statement);
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
@ -39,11 +40,13 @@ public class Pass2AssertSingleAssignment extends Pass2SsaAssertion {
|
||||
|
||||
}
|
||||
|
||||
private void checkAssignment(Map<VariableRef, Statement> assignments, LValue lValue, Statement statement) {
|
||||
private void checkAssignment(Map<VariableRef, Statement> assignments, VariableRef lValue, Statement statement) {
|
||||
if(getScope().getVariable(lValue).isStorageMemory())
|
||||
return;
|
||||
if(assignments.get(lValue) != null) {
|
||||
throw new AssertionFailed("Multiple assignments to variable " + lValue + " 1: " + assignments.get(lValue) + " 2:" + statement);
|
||||
} else {
|
||||
assignments.put((VariableRef) lValue, statement);
|
||||
assignments.put(lValue, statement);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
if(getConstant(phiRValue.getrValue()) != null) {
|
||||
VariableRef variable = phiVariable.getVariable();
|
||||
Variable var = getScope().getVariable(variable);
|
||||
if(var.isVolatile()) {
|
||||
if(var.isVolatile() || var.isStorageMemory()) {
|
||||
// Volatile variables cannot be constant
|
||||
continue;
|
||||
}
|
||||
@ -184,8 +184,8 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef variable = (VariableRef) lValue;
|
||||
Variable var = getScope().getVariable(variable);
|
||||
if(var.isVolatile()) {
|
||||
// Volatile variables cannot be constant
|
||||
if(var.isVolatile() || var.isStorageMemory()) {
|
||||
// Volatile or memory variables cannot be constant
|
||||
return;
|
||||
}
|
||||
if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof ConstantValue) {
|
||||
|
@ -1,12 +1,11 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/*** Initialize potential registers for each equivalence class.
|
||||
@ -46,12 +45,12 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
|
||||
Registers.RegisterType registerType = defaultRegister.getType();
|
||||
List<Registers.Register> potentials = new ArrayList<>();
|
||||
potentials.add(defaultRegister);
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BYTE) &&!varVolatile(equivalenceClass)) {
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BYTE) && !varVolatile(equivalenceClass)) {
|
||||
potentials.add(Registers.getRegisterA());
|
||||
potentials.add(Registers.getRegisterX());
|
||||
potentials.add(Registers.getRegisterY());
|
||||
}
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) &&!varVolatile(equivalenceClass)) {
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) && !varVolatile(equivalenceClass)) {
|
||||
potentials.add(Registers.getRegisterA());
|
||||
}
|
||||
registerPotentials.setPotentialRegisters(equivalenceClass, potentials);
|
||||
@ -62,13 +61,14 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
|
||||
|
||||
/**
|
||||
* Determine if any variable is declared as volatile
|
||||
*
|
||||
* @param equivalenceClass The variable equivalence class
|
||||
* @return true if any variable is volatile
|
||||
*/
|
||||
private boolean varVolatile(LiveRangeEquivalenceClass equivalenceClass) {
|
||||
for(VariableRef variableRef : equivalenceClass.getVariables()) {
|
||||
Variable variable = getSymbols().getVariable(variableRef);
|
||||
if(variable.isVolatile()) {
|
||||
if(variable.isVolatile() || variable.isStorageMemory()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,11 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
String before = register == null ? null : register.toString();
|
||||
VariableRef variableRef = equivalenceClass.getVariables().get(0);
|
||||
Variable variable = getProgram().getSymbolInfos().getVariable(variableRef);
|
||||
register = allocateNewRegisterZp(variable);
|
||||
if(variable.isStorageMemory()) {
|
||||
register = new Registers.RegisterMemory();
|
||||
} else {
|
||||
register = allocateNewRegisterZp(variable);
|
||||
}
|
||||
equivalenceClass.setRegister(register);
|
||||
if(before == null || !before.equals(register.toString())) {
|
||||
getLog().append("Allocated " + (before == null ? "" : ("(was " + before + ") ")) + equivalenceClass.toString());
|
||||
|
@ -35,6 +35,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclaredMemoryVar5() throws IOException, URISyntaxException {
|
||||
compileAndCompare("declared-memory-var-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclaredMemoryVar4() throws IOException, URISyntaxException {
|
||||
compileAndCompare("declared-memory-var-4");
|
||||
|
17
src/test/kc/declared-memory-var-5.kc
Normal file
17
src/test/kc/declared-memory-var-5.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
|
||||
struct foo {
|
||||
char thing1;
|
||||
char thing2;
|
||||
};
|
||||
|
||||
memory struct foo bar = { 'a', 'b' };
|
||||
|
||||
void main(void) {
|
||||
const char* SCREEN = 0x0400;
|
||||
char i=0;
|
||||
SCREEN[i++] = bar.thing1;
|
||||
SCREEN[i++] = bar.thing2;
|
||||
|
||||
}
|
@ -2,26 +2,24 @@
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label idx_ptr = idx
|
||||
.label SCREEN = $400
|
||||
__bbegin:
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
sta idx
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
ldx #0
|
||||
__b1:
|
||||
lda idx_ptr
|
||||
lda idx
|
||||
sta SCREEN,x
|
||||
txa
|
||||
stx.z $ff
|
||||
clc
|
||||
adc idx_ptr
|
||||
sta idx_ptr
|
||||
adc.z $ff
|
||||
sta idx
|
||||
inx
|
||||
cpx #6
|
||||
bne __b1
|
||||
sta idx_ptr
|
||||
rts
|
||||
}
|
||||
idx: .byte 0
|
||||
|
@ -1,28 +1,24 @@
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte*) idx_ptr) ← (byte) 0
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr)
|
||||
[8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx
|
||||
[7] (byte) idx ← (byte) idx + (byte) main::i#2
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
[12] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
@ -1,17 +1,8 @@
|
||||
Culled Empty Block (label) main::@2
|
||||
Adding memory variable constant pointer (const byte*) idx_ptr
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
*((const byte*) idx_ptr) ← (byte) 0
|
||||
(byte) idx ← (byte) 0
|
||||
(byte*) SCREEN ← ((byte*)) (number) $400
|
||||
to:@1
|
||||
|
||||
@ -21,21 +12,19 @@ main: scope:[main] from @1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
*((byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr)
|
||||
*((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2
|
||||
*((byte*) SCREEN + (byte) main::i#2) ← (byte) idx
|
||||
(byte) idx ← (byte) idx + (byte) main::i#2
|
||||
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,5)
|
||||
(bool~) main::$0 ← (byte) main::i#1 != rangelast(0,5)
|
||||
if((bool~) main::$0) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
*((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
*((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
@ -46,7 +35,6 @@ SYMBOL TABLE SSA
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte) idx memory
|
||||
(const byte*) idx_ptr = &(byte) idx
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(label) main::@1
|
||||
@ -78,14 +66,16 @@ Constant inlined main::i#0 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Added new block during phi lifting main::@3(between main::@1 and main::@1)
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [13] main::i#3 ← main::i#1
|
||||
Coalesced [12] main::i#3 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@3
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
@ -93,37 +83,33 @@ Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte*) idx_ptr) ← (byte) 0
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr)
|
||||
[8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx
|
||||
[7] (byte) idx ← (byte) idx + (byte) main::i#2
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr)
|
||||
[12] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) idx memory
|
||||
(byte) idx memory 5.0
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
@ -131,9 +117,12 @@ VARIABLE REGISTER WEIGHTS
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable idx to zero page equivalence class [ idx ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ idx ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated mem [ idx ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -144,95 +133,82 @@ Target platform is c64basic / MOS6502X
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
jmp __b2
|
||||
// @2
|
||||
__b2:
|
||||
// [3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
lda idx_ptr
|
||||
sta idx_ptr
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
__bend_from___b2:
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label i = 2
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr) -- pbuc1_derefidx_vbuz1=_deref_pbuc2
|
||||
lda idx_ptr
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx -- pbuc1_derefidx_vbuz1=vbum1
|
||||
lda idx
|
||||
ldy.z i
|
||||
sta SCREEN,y
|
||||
// [8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuz1
|
||||
lda idx_ptr
|
||||
// [7] (byte) idx ← (byte) idx + (byte) main::i#2 -- vbum1=vbum2_plus_vbuz1
|
||||
lda idx
|
||||
clc
|
||||
adc.z i
|
||||
sta idx_ptr
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
sta idx
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #6
|
||||
cmp.z i
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
lda idx_ptr
|
||||
sta idx_ptr
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
idx: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((const byte*) idx_ptr) ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx [ main::i#2 ] ( main:2 [ main::i#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 ]
|
||||
Statement [8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [0] *((const byte*) idx_ptr) ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#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 mem [ idx ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 31.17: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope []
|
||||
Uplift Scope [] 5: mem [ idx ]
|
||||
|
||||
Uplifting [main] best 428 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 428 combination
|
||||
Uplifting [main] best 449 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 449 combination mem [ idx ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -242,66 +218,57 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
jmp __b2
|
||||
// @2
|
||||
__b2:
|
||||
// [3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
lda idx_ptr
|
||||
sta idx_ptr
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
__bend_from___b2:
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr) -- pbuc1_derefidx_vbuxx=_deref_pbuc2
|
||||
lda idx_ptr
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx -- pbuc1_derefidx_vbuxx=vbum1
|
||||
lda idx
|
||||
sta SCREEN,x
|
||||
// [8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuxx
|
||||
txa
|
||||
// [7] (byte) idx ← (byte) idx + (byte) main::i#2 -- vbum1=vbum2_plus_vbuxx
|
||||
lda idx
|
||||
stx.z $ff
|
||||
clc
|
||||
adc idx_ptr
|
||||
sta idx_ptr
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
adc.z $ff
|
||||
sta idx
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #6
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
lda idx_ptr
|
||||
sta idx_ptr
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
@ -309,19 +276,19 @@ main: {
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda idx
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __b1_from___b1 with __b1
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction main_from___b1:
|
||||
Removing instruction __bend_from___b2:
|
||||
Removing instruction __bend_from___b1:
|
||||
Removing instruction __b1_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __b2:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
@ -330,20 +297,13 @@ Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp __b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda idx_ptr
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing unreachable instruction lda idx_ptr
|
||||
Removing unreachable instruction sta idx_ptr
|
||||
Succesful ASM optimization Pass5UnreachableCodeElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte) idx memory
|
||||
(const byte*) idx_ptr idx_ptr = &(byte) idx
|
||||
(byte) idx memory mem 5.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -352,10 +312,11 @@ FINAL SYMBOL TABLE
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
mem [ idx ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 323
|
||||
Score: 319
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
@ -364,54 +325,49 @@ Score: 323
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// idx
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
jsr main
|
||||
rts
|
||||
// @2
|
||||
// [3] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// main::@1
|
||||
__b1:
|
||||
// SCREEN[i] = idx
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_ptr) -- pbuc1_derefidx_vbuxx=_deref_pbuc2
|
||||
lda idx_ptr
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx -- pbuc1_derefidx_vbuxx=vbum1
|
||||
lda idx
|
||||
sta SCREEN,x
|
||||
// idx +=i
|
||||
// [8] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuxx
|
||||
txa
|
||||
// [7] (byte) idx ← (byte) idx + (byte) main::i#2 -- vbum1=vbum2_plus_vbuxx
|
||||
stx.z $ff
|
||||
clc
|
||||
adc idx_ptr
|
||||
sta idx_ptr
|
||||
adc.z $ff
|
||||
sta idx
|
||||
// for( char i: 0..5 )
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #6
|
||||
bne __b1
|
||||
// main::@return
|
||||
// }
|
||||
// [11] *((const byte*) idx_ptr) ← *((const byte*) idx_ptr) -- _deref_pbuc1=_deref_pbuc1
|
||||
sta idx_ptr
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
@ -1,10 +1,8 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte) idx memory
|
||||
(const byte*) idx_ptr idx_ptr = &(byte) idx
|
||||
(byte) idx memory mem 5.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -13,3 +11,4 @@
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
mem [ idx ]
|
||||
|
@ -3,28 +3,22 @@
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label idx_ptr = idx
|
||||
.label idx_p = idx
|
||||
.label SCREEN = $400
|
||||
.label idx_p = 2
|
||||
__bbegin:
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
lda #<idx_ptr
|
||||
sta.z idx_p
|
||||
lda #>idx_ptr
|
||||
sta.z idx_p+1
|
||||
sta idx
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
ldx #0
|
||||
__b1:
|
||||
ldy #0
|
||||
lda (idx_p),y
|
||||
lda idx_p
|
||||
sta SCREEN,x
|
||||
txa
|
||||
clc
|
||||
adc (idx_p),y
|
||||
sta (idx_p),y
|
||||
adc idx_p
|
||||
sta idx_p
|
||||
inx
|
||||
cpx #6
|
||||
bne __b1
|
||||
|
@ -1,25 +1,24 @@
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte*) idx_ptr) ← (byte) 0
|
||||
[1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr)
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0)
|
||||
[8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0)
|
||||
[7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
@ -1,13 +1,10 @@
|
||||
Setting inferred volatile on symbol affected by address-of (byte*~) $0 ← & (byte) idx
|
||||
Culled Empty Block (label) main::@2
|
||||
Adding memory variable constant pointer (const byte*) idx_ptr
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
Updating memory variable reference *((const byte*) idx_ptr)
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
*((const byte*) idx_ptr) ← (byte) 0
|
||||
(byte*~) $0 ← & *((const byte*) idx_ptr)
|
||||
(byte) idx ← (byte) 0
|
||||
(byte*~) $0 ← & (byte) idx
|
||||
(byte*) idx_p#0 ← (byte*~) $0
|
||||
(byte*) SCREEN ← ((byte*)) (number) $400
|
||||
to:@1
|
||||
@ -50,7 +47,6 @@ SYMBOL TABLE SSA
|
||||
(byte*) idx_p#1
|
||||
(byte*) idx_p#2
|
||||
(byte*) idx_p#3
|
||||
(const byte*) idx_ptr = &(byte) idx
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(label) main::@1
|
||||
@ -71,6 +67,9 @@ Identical Phi Values (byte*) idx_p#1 (byte*) idx_p#2
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) main::$0 [11] if((byte) main::i#1!=rangelast(0,5)) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant right-side identified [1] (byte*) idx_p#0 ← & (byte) idx
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) idx_p#0 = &idx
|
||||
Constant (const byte*) SCREEN = (byte*) 1024
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
@ -91,10 +90,10 @@ Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [13] main::i#3 ← main::i#1
|
||||
Coalesced [12] main::i#3 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@3
|
||||
@ -104,36 +103,34 @@ Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte*) idx_ptr) ← (byte) 0
|
||||
[1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr)
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0)
|
||||
[8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0)
|
||||
[7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) 6) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) idx memory
|
||||
(byte) idx memory 20.0
|
||||
(byte*) idx_p
|
||||
(byte*) idx_p#0 4.375
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
@ -141,12 +138,12 @@ VARIABLE REGISTER WEIGHTS
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable idx_p#0 to zero page equivalence class [ idx_p#0 ]
|
||||
Added variable idx to zero page equivalence class [ idx ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ idx_p#0 ]
|
||||
[ idx ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp ZP_WORD:3 [ idx_p#0 ]
|
||||
Allocated mem [ idx ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -158,29 +155,23 @@ Target platform is c64basic / MOS6502X
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label idx_p = idx
|
||||
.label SCREEN = $400
|
||||
.label idx_p = 3
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
// [1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr) -- pbuz1=_addr__deref_pbuc1
|
||||
lda #<idx_ptr
|
||||
sta.z idx_p
|
||||
lda #>idx_ptr
|
||||
sta.z idx_p+1
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
@ -188,66 +179,59 @@ __bend:
|
||||
// main
|
||||
main: {
|
||||
.label i = 2
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0) -- pbuc1_derefidx_vbuz1=_deref_pbuz2
|
||||
ldx.z i
|
||||
ldy #0
|
||||
lda (idx_p),y
|
||||
sta SCREEN,x
|
||||
// [8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuz1=_deref_pbuz1_plus_vbuz2
|
||||
lda.z i
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0) -- pbuc1_derefidx_vbuz1=_deref_pbuc2
|
||||
lda idx_p
|
||||
ldy.z i
|
||||
sta SCREEN,y
|
||||
// [7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuz1
|
||||
lda idx_p
|
||||
clc
|
||||
ldy #0
|
||||
adc (idx_p),y
|
||||
ldy #0
|
||||
sta (idx_p),y
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
adc.z i
|
||||
sta idx_p
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #6
|
||||
cmp.z i
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
idx: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((const byte*) idx_ptr) ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr) [ idx_p#0 ] ( [ idx_p#0 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0) [ idx_p#0 main::i#2 ] ( main:3 [ idx_p#0 main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [0] (byte) idx ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0) [ main::i#2 ] ( main:2 [ main::i#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 y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2 [ idx_p#0 main::i#2 ] ( main:3 [ idx_p#0 main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [0] *((const byte*) idx_ptr) ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr) [ idx_p#0 ] ( [ idx_p#0 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0) [ idx_p#0 main::i#2 ] ( main:3 [ idx_p#0 main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2 [ idx_p#0 main::i#2 ] ( main:3 [ idx_p#0 main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x ,
|
||||
Potential registers zp ZP_WORD:3 [ idx_p#0 ] : zp ZP_WORD:3 ,
|
||||
Statement [7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) idx ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#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 mem [ idx ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 31.17: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope [] 4.38: zp ZP_WORD:3 [ idx_p#0 ]
|
||||
Uplift Scope [] 20: mem [ idx ]
|
||||
|
||||
Uplifting [main] best 529 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 529 combination zp ZP_WORD:3 [ idx_p#0 ]
|
||||
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ idx_p#0 ]
|
||||
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 409 combination mem [ idx ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -258,66 +242,57 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label idx_p = idx
|
||||
.label SCREEN = $400
|
||||
.label idx_p = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
// [1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr) -- pbuz1=_addr__deref_pbuc1
|
||||
lda #<idx_ptr
|
||||
sta.z idx_p
|
||||
lda #>idx_ptr
|
||||
sta.z idx_p+1
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0) -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (idx_p),y
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0) -- pbuc1_derefidx_vbuxx=_deref_pbuc2
|
||||
lda idx_p
|
||||
sta SCREEN,x
|
||||
// [8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuz1=_deref_pbuz1_plus_vbuxx
|
||||
// [7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuxx
|
||||
txa
|
||||
clc
|
||||
ldy #0
|
||||
adc (idx_p),y
|
||||
ldy #0
|
||||
sta (idx_p),y
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
adc idx_p
|
||||
sta idx_p
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #6
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
@ -329,9 +304,6 @@ Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction ldy #0
|
||||
Removing instruction ldy #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __b1_from___b1 with __b1
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction main_from___b1:
|
||||
@ -353,10 +325,9 @@ FINAL SYMBOL TABLE
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte) idx memory
|
||||
(byte) idx memory mem 20.0
|
||||
(byte*) idx_p
|
||||
(byte*) idx_p#0 idx_p zp ZP_WORD:2 4.375
|
||||
(const byte*) idx_ptr idx_ptr = &(byte) idx
|
||||
(const byte*) idx_p#0 idx_p = &(byte) idx
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -365,11 +336,11 @@ FINAL SYMBOL TABLE
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ idx_p#0 ]
|
||||
mem [ idx ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 399
|
||||
Score: 319
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
@ -379,58 +350,50 @@ Score: 399
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label idx_ptr = idx
|
||||
.label idx_p = idx
|
||||
.label SCREEN = $400
|
||||
.label idx_p = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// idx
|
||||
// [0] *((const byte*) idx_ptr) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
|
||||
lda #0
|
||||
sta idx_ptr
|
||||
// idx_p = &idx
|
||||
// [1] (byte*) idx_p#0 ← & *((const byte*) idx_ptr) -- pbuz1=_addr__deref_pbuc1
|
||||
lda #<idx_ptr
|
||||
sta.z idx_p
|
||||
lda #>idx_ptr
|
||||
sta.z idx_p+1
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
sta idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [3] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
jsr main
|
||||
rts
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// main::@1
|
||||
__b1:
|
||||
// SCREEN[i] = *idx_p
|
||||
// [7] *((const byte*) SCREEN + (byte) main::i#2) ← *((byte*) idx_p#0) -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (idx_p),y
|
||||
// [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p#0) -- pbuc1_derefidx_vbuxx=_deref_pbuc2
|
||||
lda idx_p
|
||||
sta SCREEN,x
|
||||
// *idx_p +=i
|
||||
// [8] *((byte*) idx_p#0) ← *((byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuz1=_deref_pbuz1_plus_vbuxx
|
||||
// [7] *((const byte*) idx_p#0) ← *((const byte*) idx_p#0) + (byte) main::i#2 -- _deref_pbuc1=_deref_pbuc1_plus_vbuxx
|
||||
txa
|
||||
clc
|
||||
adc (idx_p),y
|
||||
sta (idx_p),y
|
||||
adc idx_p
|
||||
sta idx_p
|
||||
// for( char i: 0..5 )
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #6
|
||||
bne __b1
|
||||
// main::@return
|
||||
// }
|
||||
// [11] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
@ -2,10 +2,9 @@
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte) idx memory
|
||||
(byte) idx memory mem 20.0
|
||||
(byte*) idx_p
|
||||
(byte*) idx_p#0 idx_p zp ZP_WORD:2 4.375
|
||||
(const byte*) idx_ptr idx_ptr = &(byte) idx
|
||||
(const byte*) idx_p#0 idx_p = &(byte) idx
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -14,4 +13,4 @@
|
||||
(byte) main::i#2 reg byte x 14.666666666666666
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ idx_p#0 ]
|
||||
mem [ idx ]
|
||||
|
@ -3,32 +3,31 @@
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label cursor_ptr = cursor
|
||||
.label SCREEN = $400
|
||||
__bbegin:
|
||||
lda #<SCREEN
|
||||
sta cursor_ptr
|
||||
sta cursor
|
||||
lda #>SCREEN
|
||||
sta cursor_ptr+1
|
||||
sta cursor+1
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
ldx #0
|
||||
__b1:
|
||||
lda #'*'
|
||||
ldy cursor_ptr
|
||||
ldy cursor
|
||||
sty.z $fe
|
||||
ldy cursor_ptr+1
|
||||
ldy cursor+1
|
||||
sty.z $ff
|
||||
ldy #0
|
||||
sta ($fe),y
|
||||
lda cursor_ptr
|
||||
lda #$29
|
||||
clc
|
||||
adc #$29
|
||||
sta cursor_ptr
|
||||
lda cursor_ptr+1
|
||||
adc #0
|
||||
sta cursor_ptr+1
|
||||
adc cursor
|
||||
sta cursor
|
||||
tya
|
||||
adc cursor+1
|
||||
sta cursor+1
|
||||
inx
|
||||
cpx #$19
|
||||
bne __b1
|
||||
|
@ -1,28 +1,24 @@
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN
|
||||
[0] (byte*) cursor ← (const byte*) SCREEN
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *(*((const byte**) cursor_ptr)) ← (byte) '*'
|
||||
[8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) $19) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((byte*) cursor) ← (byte) '*'
|
||||
[7] (byte*) cursor ← (byte*) cursor + (byte) $29
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) $19) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
[12] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
@ -1,18 +1,9 @@
|
||||
Culled Empty Block (label) main::@2
|
||||
Adding memory variable constant pointer (const byte**) cursor_ptr
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
Updating memory variable reference *((const byte**) cursor_ptr)
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) SCREEN ← ((byte*)) (number) $400
|
||||
*((const byte**) cursor_ptr) ← (byte*) SCREEN
|
||||
(byte*) cursor ← (byte*) SCREEN
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
@ -21,21 +12,19 @@ main: scope:[main] from @1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
|
||||
*(*((const byte**) cursor_ptr)) ← (byte) '*'
|
||||
*((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (number) $29
|
||||
*((byte*) cursor) ← (byte) '*'
|
||||
(byte*) cursor ← (byte*) cursor + (number) $29
|
||||
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,$18)
|
||||
(bool~) main::$0 ← (byte) main::i#1 != rangelast(0,$18)
|
||||
if((bool~) main::$0) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
*((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
*((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
@ -46,7 +35,6 @@ SYMBOL TABLE SSA
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte*) cursor memory
|
||||
(const byte**) cursor_ptr = &(byte*) cursor
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(label) main::@1
|
||||
@ -56,7 +44,7 @@ SYMBOL TABLE SSA
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
|
||||
Adding number conversion cast (unumber) $29 in *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (number) $29
|
||||
Adding number conversion cast (unumber) $29 in (byte*) cursor ← (byte*) cursor + (number) $29
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) SCREEN ← (byte*)(number) $400
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
@ -65,6 +53,7 @@ Simplifying constant integer cast $29
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) $29
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias candidate removed (volatile)(byte*) SCREEN = (byte*) cursor
|
||||
Simple Condition (bool~) main::$0 [8] if((byte) main::i#1!=rangelast(0,$18)) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte*) SCREEN = (byte*) 1024
|
||||
@ -83,14 +72,16 @@ Constant inlined main::i#0 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Added new block during phi lifting main::@3(between main::@1 and main::@1)
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [13] main::i#3 ← main::i#1
|
||||
Coalesced [12] main::i#3 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@3
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
@ -98,37 +89,33 @@ Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN
|
||||
[0] (byte*) cursor ← (const byte*) SCREEN
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] phi()
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[6] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[7] *(*((const byte**) cursor_ptr)) ← (byte) '*'
|
||||
[8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) $19) goto main::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[6] *((byte*) cursor) ← (byte) '*'
|
||||
[7] (byte*) cursor ← (byte*) cursor + (byte) $29
|
||||
[8] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[9] if((byte) main::i#1!=(byte) $19) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[11] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr)
|
||||
[12] return
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) cursor memory
|
||||
(byte*) cursor memory 5.0
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
@ -136,9 +123,12 @@ VARIABLE REGISTER WEIGHTS
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable cursor to zero page equivalence class [ cursor ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ cursor ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated mem [ cursor ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -150,97 +140,92 @@ Target platform is c64basic / MOS6502X
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label cursor_ptr = cursor
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN -- _deref_pptc1=pbuc2
|
||||
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
|
||||
lda #<SCREEN
|
||||
sta cursor_ptr
|
||||
sta cursor
|
||||
lda #>SCREEN
|
||||
sta cursor_ptr+1
|
||||
sta cursor+1
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
jmp __b2
|
||||
// @2
|
||||
__b2:
|
||||
// [3] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
__bend_from___b2:
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label i = 2
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *(*((const byte**) cursor_ptr)) ← (byte) '*' -- _deref_(_deref_pptc1)=vbuc2
|
||||
// [6] *((byte*) cursor) ← (byte) '*' -- _deref_pbum1=vbuc1
|
||||
lda #'*'
|
||||
ldy cursor_ptr
|
||||
ldy cursor
|
||||
sty.z $fe
|
||||
ldy cursor_ptr+1
|
||||
ldy cursor+1
|
||||
sty.z $ff
|
||||
ldy #0
|
||||
sta ($fe),y
|
||||
// [8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29 -- _deref_pptc1=_deref_pptc1_plus_vbuc2
|
||||
lda cursor_ptr
|
||||
// [7] (byte*) cursor ← (byte*) cursor + (byte) $29 -- pbum1=pbum2_plus_vbuc1
|
||||
lda #$29
|
||||
clc
|
||||
adc #$29
|
||||
sta cursor_ptr
|
||||
lda cursor_ptr+1
|
||||
adc #0
|
||||
sta cursor_ptr+1
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
adc cursor
|
||||
sta cursor
|
||||
lda #0
|
||||
adc cursor+1
|
||||
sta cursor+1
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [10] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$19
|
||||
cmp.z i
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
cursor: .word 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [7] *(*((const byte**) cursor_ptr)) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [0] (byte*) cursor ← (const byte*) SCREEN [ cursor ] ( [ cursor ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*) cursor) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
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 y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [7] *(*((const byte**) cursor_ptr)) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ cursor main::i#2 ] ( main:2 [ cursor main::i#2 ] ) always clobbers reg byte a
|
||||
Statement [0] (byte*) cursor ← (const byte*) SCREEN [ cursor ] ( [ cursor ] ) always clobbers reg byte a
|
||||
Statement [6] *((byte*) cursor) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ cursor main::i#2 ] ( main:2 [ cursor main::i#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 ,
|
||||
Potential registers mem [ cursor ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 23.83: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope []
|
||||
Uplift Scope [] 5: mem [ cursor ]
|
||||
|
||||
Uplifting [main] best 668 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 668 combination
|
||||
Uplifting [main] best 665 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 665 combination mem [ cursor ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -251,72 +236,66 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label cursor_ptr = cursor
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN -- _deref_pptc1=pbuc2
|
||||
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
|
||||
lda #<SCREEN
|
||||
sta cursor_ptr
|
||||
sta cursor
|
||||
lda #>SCREEN
|
||||
sta cursor_ptr+1
|
||||
sta cursor+1
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from___b1:
|
||||
jsr main
|
||||
jmp __b2
|
||||
// @2
|
||||
__b2:
|
||||
// [3] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
__bend_from___b2:
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [7] *(*((const byte**) cursor_ptr)) ← (byte) '*' -- _deref_(_deref_pptc1)=vbuc2
|
||||
// [6] *((byte*) cursor) ← (byte) '*' -- _deref_pbum1=vbuc1
|
||||
lda #'*'
|
||||
ldy cursor_ptr
|
||||
ldy cursor
|
||||
sty.z $fe
|
||||
ldy cursor_ptr+1
|
||||
ldy cursor+1
|
||||
sty.z $ff
|
||||
ldy #0
|
||||
sta ($fe),y
|
||||
// [8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29 -- _deref_pptc1=_deref_pptc1_plus_vbuc2
|
||||
lda cursor_ptr
|
||||
// [7] (byte*) cursor ← (byte*) cursor + (byte) $29 -- pbum1=pbum2_plus_vbuc1
|
||||
lda #$29
|
||||
clc
|
||||
adc #$29
|
||||
sta cursor_ptr
|
||||
lda cursor_ptr+1
|
||||
adc #0
|
||||
sta cursor_ptr+1
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
adc cursor
|
||||
sta cursor
|
||||
lda #0
|
||||
adc cursor+1
|
||||
sta cursor+1
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #$19
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
@ -324,20 +303,19 @@ main: {
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction lda #0 with TYA
|
||||
Replacing label __b1_from___b1 with __b1
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction main_from___b1:
|
||||
Removing instruction __bend_from___b2:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __bend_from___b1:
|
||||
Removing instruction __b1_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __b2:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
@ -348,12 +326,10 @@ Succesful ASM optimization Pass5NextJumpElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte*) cursor memory
|
||||
(const byte**) cursor_ptr cursor_ptr = &(byte*) cursor
|
||||
(byte*) cursor memory mem 5.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -362,6 +338,7 @@ FINAL SYMBOL TABLE
|
||||
(byte) main::i#2 reg byte x 7.333333333333333
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
mem [ cursor ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
@ -375,63 +352,59 @@ Score: 575
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label cursor_ptr = cursor
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
__bbegin:
|
||||
// cursor = SCREEN
|
||||
// [0] *((const byte**) cursor_ptr) ← (const byte*) SCREEN -- _deref_pptc1=pbuc2
|
||||
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
|
||||
lda #<SCREEN
|
||||
sta cursor_ptr
|
||||
sta cursor
|
||||
lda #>SCREEN
|
||||
sta cursor_ptr+1
|
||||
sta cursor+1
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [5] phi from @1 to main [phi:@1->main]
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
jsr main
|
||||
rts
|
||||
// @2
|
||||
// [3] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [4] phi from @2 to @end [phi:@2->@end]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [6] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [6] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// main::@1
|
||||
__b1:
|
||||
// *cursor = '*'
|
||||
// [7] *(*((const byte**) cursor_ptr)) ← (byte) '*' -- _deref_(_deref_pptc1)=vbuc2
|
||||
// [6] *((byte*) cursor) ← (byte) '*' -- _deref_pbum1=vbuc1
|
||||
lda #'*'
|
||||
ldy cursor_ptr
|
||||
ldy cursor
|
||||
sty.z $fe
|
||||
ldy cursor_ptr+1
|
||||
ldy cursor+1
|
||||
sty.z $ff
|
||||
ldy #0
|
||||
sta ($fe),y
|
||||
// cursor += 41
|
||||
// [8] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) + (byte) $29 -- _deref_pptc1=_deref_pptc1_plus_vbuc2
|
||||
lda cursor_ptr
|
||||
// [7] (byte*) cursor ← (byte*) cursor + (byte) $29 -- pbum1=pbum2_plus_vbuc1
|
||||
lda #$29
|
||||
clc
|
||||
adc #$29
|
||||
sta cursor_ptr
|
||||
lda cursor_ptr+1
|
||||
adc #0
|
||||
sta cursor_ptr+1
|
||||
adc cursor
|
||||
sta cursor
|
||||
tya
|
||||
adc cursor+1
|
||||
sta cursor+1
|
||||
// for( char i: 0..24 )
|
||||
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
// [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
// [9] if((byte) main::i#1!=(byte) $19) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #$19
|
||||
bne __b1
|
||||
// main::@return
|
||||
// }
|
||||
// [11] *((const byte**) cursor_ptr) ← *((const byte**) cursor_ptr) -- _deref_pptc1=_deref_pptc1
|
||||
// [12] return
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
@ -1,10 +1,8 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN SCREEN = (byte*) 1024
|
||||
(byte*) cursor memory
|
||||
(const byte**) cursor_ptr cursor_ptr = &(byte*) cursor
|
||||
(byte*) cursor memory mem 5.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
@ -13,3 +11,4 @@
|
||||
(byte) main::i#2 reg byte x 7.333333333333333
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
mem [ cursor ]
|
||||
|
@ -4,28 +4,21 @@
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
__bbegin:
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
sta bar_thing1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label barp = 4
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
lda barp
|
||||
sta SCREEN
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1#0 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2#0 ← (byte) 'b'
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
@ -11,10 +11,9 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr)
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
[5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
[7] return
|
||||
to:@return
|
||||
|
@ -6,19 +6,17 @@ Adding struct value list initializer (byte) bar_thing1 ← (byte) 'a'
|
||||
Adding struct value list initializer (byte) bar_thing2 ← (byte) 'b'
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing1
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing2
|
||||
Adding memory variable constant pointer (const struct foo*) bar_ptr
|
||||
Updating memory variable reference *((const struct foo*) bar_ptr)
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) bar_thing1#0 ← (byte) 'a'
|
||||
(byte) bar_thing2#0 ← (byte) 'b'
|
||||
(struct foo) bar ← struct-unwound {(byte) bar_thing1#0, (byte) bar_thing2#0}
|
||||
(byte) bar_thing1 ← (byte) 'a'
|
||||
(byte) bar_thing2 ← (byte) 'b'
|
||||
(struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(struct foo*~) main::$0 ← & *((const struct foo*) bar_ptr)
|
||||
(struct foo*~) main::$0 ← & (struct foo) bar
|
||||
(struct foo*) main::barp#0 ← (struct foo*~) main::$0
|
||||
(byte*) main::SCREEN ← ((byte*)) (number) $400
|
||||
(byte) main::i#0 ← (number) 0
|
||||
@ -47,11 +45,8 @@ SYMBOL TABLE SSA
|
||||
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(struct foo) bar memory
|
||||
(const struct foo*) bar_ptr = &(struct foo) bar
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0
|
||||
(byte) bar_thing1 memory
|
||||
(byte) bar_thing2 memory
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
@ -79,25 +74,29 @@ Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (struct foo*) main::barp#0 = (struct foo*~) main::$0
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Rewriting struct address-of to first member &(struct foo) bar
|
||||
Rewriting struct address-of to first member [3] (struct foo*) main::barp#0 ← (struct foo*)&(byte) bar_thing1
|
||||
Successful SSA optimization PassNStructAddressOfRewriting
|
||||
Constant (const struct foo*) main::barp#0 = (struct foo*)&bar_thing1
|
||||
Constant (const byte*) main::SCREEN = (byte*) 1024
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::barp#0 in [7] (byte*) main::$1 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant value identified (byte*)main::barp#0 in [10] (byte*) main::$2 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Converting *(pointer+n) to pointer[n] [8] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*) main::$1) -- *((byte*)main::barp#0 + OFFSET_STRUCT_FOO_THING1)
|
||||
Converting *(pointer+n) to pointer[n] [11] *((const byte*) main::SCREEN + (byte) main::i#1) ← *((byte*) main::$2) -- *((byte*)main::barp#0 + OFFSET_STRUCT_FOO_THING2)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [7] (byte*) main::$1 ← (byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [8] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1)
|
||||
Simplifying expression containing zero main::SCREEN in [8] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(struct foo*) main::barp#0)
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [7] (byte*) main::$1 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [8] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1)
|
||||
Simplifying expression containing zero main::SCREEN in [8] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct foo) bar and assignment [2] (struct foo) bar ← struct-unwound {(byte) bar_thing1#0, (byte) bar_thing2#0}
|
||||
Eliminating unused variable (byte*) main::$1 and assignment [4] (byte*) main::$1 ← (byte*)(struct foo*) main::barp#0
|
||||
Eliminating unused variable (byte*) main::$2 and assignment [7] (byte*) main::$2 ← (byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [9] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused variable (struct foo) bar and assignment [2] (struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2}
|
||||
Eliminating unused variable (byte*) main::$1 and assignment [3] (byte*) main::$1 ← (byte*)(const struct foo*) main::barp#0
|
||||
Eliminating unused variable (byte*) main::$2 and assignment [6] (byte*) main::$2 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [8] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant right-side identified [4] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Constant right-side identified [3] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#1 = ++main::i#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
@ -106,6 +105,7 @@ Inlining constant with different constant siblings (const byte) main::i#1
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#1 = ++(byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)main::barp#0+OFFSET_STRUCT_FOO_THING2)
|
||||
Consolidated array index constant in *(main::SCREEN+++0)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Simplifying constant integer increment ++0
|
||||
@ -124,8 +124,8 @@ Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1#0 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2#0 ← (byte) 'b'
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
@ -136,36 +136,31 @@ FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr)
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
[5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[8] return
|
||||
[7] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 20.0
|
||||
(byte) bar_thing1 memory 20.0
|
||||
(byte) bar_thing2 memory 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 1.0
|
||||
(byte) main::i
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::barp#0 to zero page equivalence class [ main::barp#0 ]
|
||||
Added variable bar_thing1 to zero page equivalence class [ bar_thing1 ]
|
||||
Added variable bar_thing2 to zero page equivalence class [ bar_thing2 ]
|
||||
Complete equivalence classes
|
||||
[ bar_thing1#0 ]
|
||||
[ bar_thing2#0 ]
|
||||
[ main::barp#0 ]
|
||||
Allocated zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
Allocated zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Allocated zp ZP_WORD:4 [ main::barp#0 ]
|
||||
[ bar_thing1 ]
|
||||
[ bar_thing2 ]
|
||||
Allocated mem [ bar_thing1 ]
|
||||
Allocated mem [ bar_thing2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -178,17 +173,14 @@ Target platform is c64basic / MOS6502X
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
@ -203,51 +195,40 @@ __bend_from___b1:
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label barp = 4
|
||||
// [5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] (byte) bar_thing1#0 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2#0 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) [ main::barp#0 ] ( main:3 [ main::barp#0 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) [ main::barp#0 ] ( main:3 [ main::barp#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ bar_thing1#0 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ bar_thing2#0 ] : zp ZP_BYTE:3 ,
|
||||
Potential registers zp ZP_WORD:4 [ main::barp#0 ] : zp ZP_WORD:4 ,
|
||||
Statement [0] (byte) bar_thing1 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers mem [ bar_thing1 ] : mem ,
|
||||
Potential registers mem [ bar_thing2 ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 20: zp ZP_BYTE:2 [ bar_thing1#0 ] 20: zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Uplift Scope [main] 1: zp ZP_WORD:4 [ main::barp#0 ]
|
||||
Uplift Scope [] 20: mem [ bar_thing1 ] 20: mem [ bar_thing2 ]
|
||||
Uplift Scope [foo]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [] best 63 combination zp ZP_BYTE:2 [ bar_thing1#0 ] zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Uplifting [main] best 63 combination zp ZP_WORD:4 [ main::barp#0 ]
|
||||
Uplifting [foo] best 63 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
Uplifting [] best 63 combination zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Uplifting [] best 63 combination zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Uplifting [] best 49 combination mem [ bar_thing1 ] mem [ bar_thing2 ]
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -259,17 +240,14 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
@ -284,28 +262,23 @@ __bend_from___b1:
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label barp = 4
|
||||
// [5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
@ -327,27 +300,23 @@ FINAL SYMBOL TABLE
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const struct foo*) bar_ptr bar_ptr = (struct foo*)&(byte) bar_thing1#0
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 bar_thing1 zp ZP_BYTE:2 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 bar_thing2 zp ZP_BYTE:3 20.0
|
||||
(byte) bar_thing1 memory mem 20.0
|
||||
(byte) bar_thing2 memory mem 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 barp zp ZP_WORD:4 1.0
|
||||
(const struct foo*) main::barp#0 barp = (struct foo*)&(byte) bar_thing1
|
||||
(byte) main::i
|
||||
|
||||
zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
zp ZP_WORD:4 [ main::barp#0 ]
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 60
|
||||
Score: 46
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
@ -358,18 +327,15 @@ Score: 60
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
// @begin
|
||||
__bbegin:
|
||||
// bar = { 'a', 'b' }
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [3] call main
|
||||
@ -379,28 +345,22 @@ __bbegin:
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label barp = 4
|
||||
// barp = &bar
|
||||
// [5] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// SCREEN[i++] = barp->thing1
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// SCREEN[i++] = barp->thing2
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
|
@ -2,20 +2,16 @@
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const struct foo*) bar_ptr bar_ptr = (struct foo*)&(byte) bar_thing1#0
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 bar_thing1 zp ZP_BYTE:2 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 bar_thing2 zp ZP_BYTE:3 20.0
|
||||
(byte) bar_thing1 memory mem 20.0
|
||||
(byte) bar_thing2 memory mem 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 barp zp ZP_WORD:4 1.0
|
||||
(const struct foo*) main::barp#0 barp = (struct foo*)&(byte) bar_thing1
|
||||
(byte) main::i
|
||||
|
||||
zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
zp ZP_WORD:4 [ main::barp#0 ]
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
||||
|
@ -5,15 +5,12 @@
|
||||
.pc = $80d "Program"
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.const OFFSET_STRUCT_FOO_THING3 = 2
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
.label bar_thing3 = 4
|
||||
.label bar_thing3 = 2
|
||||
__bbegin:
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
sta bar_thing1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
lda #<__0
|
||||
sta.z bar_thing3
|
||||
lda #>__0
|
||||
@ -21,30 +18,16 @@ __bbegin:
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label __4 = 8
|
||||
.label barp = 6
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
lda barp
|
||||
sta SCREEN
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
ldx #2
|
||||
ldy #0
|
||||
__b1:
|
||||
lda #OFFSET_STRUCT_FOO_THING3
|
||||
clc
|
||||
adc.z barp
|
||||
sta.z __4
|
||||
lda #0
|
||||
adc.z barp+1
|
||||
sta.z __4+1
|
||||
lda (__4),y
|
||||
lda barp+OFFSET_STRUCT_FOO_THING3,y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
iny
|
||||
@ -54,3 +37,5 @@ main: {
|
||||
}
|
||||
__0: .text "qwe"
|
||||
.byte 0
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1#0 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2#0 ← (byte) 'b'
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
[2] (byte[$c]) bar_thing3#0 ← (const string) $0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
@ -12,19 +12,17 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr)
|
||||
[7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0)
|
||||
[8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[9] (byte) main::i#4 ← phi( main/(byte) 2 main::@1/(byte) main::i#3 )
|
||||
[9] (byte) main::j#2 ← phi( main/(byte) 0 main::@1/(byte) main::j#1 )
|
||||
[10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3
|
||||
[11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2)
|
||||
[12] (byte) main::i#3 ← ++ (byte) main::i#4
|
||||
[13] (byte) main::j#1 ← ++ (byte) main::j#2
|
||||
[14] if((byte) main::j#1!=(byte) $c) goto main::@1
|
||||
[8] (byte) main::i#4 ← phi( main/(byte) 2 main::@1/(byte) main::i#3 )
|
||||
[8] (byte) main::j#2 ← phi( main/(byte) 0 main::@1/(byte) main::j#1 )
|
||||
[9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2)
|
||||
[10] (byte) main::i#3 ← ++ (byte) main::i#4
|
||||
[11] (byte) main::j#1 ← ++ (byte) main::j#2
|
||||
[12] if((byte) main::j#1!=(byte) $c) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[15] return
|
||||
[13] return
|
||||
to:@return
|
||||
|
@ -12,20 +12,18 @@ Rewriting struct pointer member access *((struct foo*) main::barp).thing1
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing2
|
||||
Rewriting struct pointer member access *((struct foo*) main::barp).thing3
|
||||
Culled Empty Block (label) main::@2
|
||||
Adding memory variable constant pointer (const struct foo*) bar_ptr
|
||||
Updating memory variable reference *((const struct foo*) bar_ptr)
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) bar_thing1#0 ← (byte) 'a'
|
||||
(byte) bar_thing2#0 ← (byte) 'b'
|
||||
(byte) bar_thing1 ← (byte) 'a'
|
||||
(byte) bar_thing2 ← (byte) 'b'
|
||||
(byte[$c]) bar_thing3#0 ← (const string) $0
|
||||
(struct foo) bar ← struct-unwound {(byte) bar_thing1#0, (byte) bar_thing2#0, (byte[$c]) bar_thing3#0}
|
||||
(struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2, (byte[$c]) bar_thing3#0}
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(struct foo*~) main::$0 ← & *((const struct foo*) bar_ptr)
|
||||
(struct foo*~) main::$0 ← & (struct foo) bar
|
||||
(struct foo*) main::barp#0 ← (struct foo*~) main::$0
|
||||
(byte*) main::SCREEN ← ((byte*)) (number) $400
|
||||
(byte) main::i#0 ← (number) 0
|
||||
@ -68,11 +66,8 @@ SYMBOL TABLE SSA
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
|
||||
(struct foo) bar memory
|
||||
(const struct foo*) bar_ptr = &(struct foo) bar
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0
|
||||
(byte) bar_thing1 memory
|
||||
(byte) bar_thing2 memory
|
||||
(byte[$c]) bar_thing3
|
||||
(byte[$c]) bar_thing3#0
|
||||
(byte) foo::thing1
|
||||
@ -117,24 +112,29 @@ Identical Phi Values (struct foo*) main::barp#1 (struct foo*) main::barp#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) main::$1 [21] if((byte) main::j#1!=rangelast(0,$b)) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Rewriting struct address-of to first member &(struct foo) bar
|
||||
Rewriting struct address-of to first member [4] (struct foo*) main::barp#0 ← (struct foo*)&(byte) bar_thing1
|
||||
Successful SSA optimization PassNStructAddressOfRewriting
|
||||
Constant (const struct foo*) main::barp#0 = (struct foo*)&bar_thing1
|
||||
Constant (const byte*) main::SCREEN = (byte*) 1024
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const byte) main::j#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)main::barp#0 in [8] (byte*) main::$2 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Constant value identified (byte*)main::barp#0 in [11] (byte*) main::$3 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Constant value identified (byte[$c])main::barp#0 in [16] (byte[$c]) main::$4 ← (byte[$c])(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Resolved ranged next value [19] main::j#1 ← ++ main::j#2 to ++
|
||||
Resolved ranged comparison value [21] if(main::j#1!=rangelast(0,$b)) goto main::@1 to (number) $c
|
||||
Converting *(pointer+n) to pointer[n] [9] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*) main::$2) -- *((byte*)main::barp#0 + OFFSET_STRUCT_FOO_THING1)
|
||||
Converting *(pointer+n) to pointer[n] [12] *((const byte*) main::SCREEN + (byte) main::i#1) ← *((byte*) main::$3) -- *((byte*)main::barp#0 + OFFSET_STRUCT_FOO_THING2)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [8] (byte*) main::$2 ← (byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [9] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1)
|
||||
Simplifying expression containing zero main::SCREEN in [9] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(struct foo*) main::barp#0)
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [8] (byte*) main::$2 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Simplifying expression containing zero (byte*)main::barp#0 in [9] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING1)
|
||||
Simplifying expression containing zero main::SCREEN in [9] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (struct foo) bar and assignment [3] (struct foo) bar ← struct-unwound {(byte) bar_thing1#0, (byte) bar_thing2#0, (byte[$c]) bar_thing3#0}
|
||||
Eliminating unused variable (byte*) main::$2 and assignment [5] (byte*) main::$2 ← (byte*)(struct foo*) main::barp#0
|
||||
Eliminating unused variable (byte*) main::$3 and assignment [8] (byte*) main::$3 ← (byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Eliminating unused variable (struct foo) bar and assignment [3] (struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2, (byte[$c]) bar_thing3#0}
|
||||
Eliminating unused variable (byte*) main::$2 and assignment [4] (byte*) main::$2 ← (byte*)(const struct foo*) main::barp#0
|
||||
Eliminating unused variable (byte*) main::$3 and assignment [7] (byte*) main::$3 ← (byte*)(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Adding number conversion cast (unumber) $c in if((byte) main::j#1!=(number) $c) goto main::@1
|
||||
@ -143,11 +143,13 @@ Simplifying constant integer cast $c
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) $c
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant right-side identified [5] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Constant right-side identified [4] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Constant right-side identified [8] (byte[$c]) main::$4 ← (byte[$c])(const struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#1 = ++main::i#0
|
||||
Constant (const byte[$c]) main::$4 = (byte[$c])main::barp#0+OFFSET_STRUCT_FOO_THING3
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant right-side identified [6] (byte) main::i#2 ← ++ (const byte) main::i#1
|
||||
Constant right-side identified [5] (byte) main::i#2 ← ++ (const byte) main::i#1
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#2 = ++main::i#1
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
@ -157,9 +159,11 @@ Inlining constant with var siblings (const byte) main::i#1
|
||||
Inlining constant with var siblings (const byte) main::i#2
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#2 = ++++(byte) 0
|
||||
Constant inlined main::$4 = (byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3
|
||||
Constant inlined main::j#0 = (byte) 0
|
||||
Constant inlined main::i#1 = ++(byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)main::barp#0+OFFSET_STRUCT_FOO_THING2)
|
||||
Consolidated array index constant in *(main::SCREEN+++0)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Simplifying constant integer increment ++0
|
||||
@ -175,8 +179,8 @@ CALL GRAPH
|
||||
Calls in [] to main:4
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [17] main::j#3 ← main::j#1
|
||||
Coalesced [18] main::i#5 ← main::i#3
|
||||
Coalesced [15] main::j#3 ← main::j#1
|
||||
Coalesced [16] main::i#5 ← main::i#3
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@3
|
||||
@ -185,8 +189,8 @@ Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1#0 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2#0 ← (byte) 'b'
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
[2] (byte[$c]) bar_thing3#0 ← (const string) $0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
@ -198,65 +202,55 @@ FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr)
|
||||
[7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0)
|
||||
[8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0)
|
||||
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2)
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[9] (byte) main::i#4 ← phi( main/(byte) 2 main::@1/(byte) main::i#3 )
|
||||
[9] (byte) main::j#2 ← phi( main/(byte) 0 main::@1/(byte) main::j#1 )
|
||||
[10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3
|
||||
[11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2)
|
||||
[12] (byte) main::i#3 ← ++ (byte) main::i#4
|
||||
[13] (byte) main::j#1 ← ++ (byte) main::j#2
|
||||
[14] if((byte) main::j#1!=(byte) $c) goto main::@1
|
||||
[8] (byte) main::i#4 ← phi( main/(byte) 2 main::@1/(byte) main::i#3 )
|
||||
[8] (byte) main::j#2 ← phi( main/(byte) 0 main::@1/(byte) main::j#1 )
|
||||
[9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2)
|
||||
[10] (byte) main::i#3 ← ++ (byte) main::i#4
|
||||
[11] (byte) main::j#1 ← ++ (byte) main::j#2
|
||||
[12] if((byte) main::j#1!=(byte) $c) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[15] return
|
||||
[13] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 20.0
|
||||
(byte) bar_thing1 memory 20.0
|
||||
(byte) bar_thing2 memory 20.0
|
||||
(byte[$c]) bar_thing3
|
||||
(byte[$c]) bar_thing3#0 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(byte[$c]) foo::thing3
|
||||
(void()) main()
|
||||
(byte[$c]) main::$4 22.0
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 0.2222222222222222
|
||||
(byte) main::i
|
||||
(byte) main::i#3 7.333333333333333
|
||||
(byte) main::i#4 11.0
|
||||
(byte) main::i#4 16.5
|
||||
(byte) main::j
|
||||
(byte) main::j#1 16.5
|
||||
(byte) main::j#2 8.25
|
||||
(byte) main::j#2 11.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::j#2 main::j#1 ]
|
||||
[ main::i#4 main::i#3 ]
|
||||
Added variable main::barp#0 to zero page equivalence class [ main::barp#0 ]
|
||||
Added variable main::$4 to zero page equivalence class [ main::$4 ]
|
||||
Added variable bar_thing1 to zero page equivalence class [ bar_thing1 ]
|
||||
Added variable bar_thing2 to zero page equivalence class [ bar_thing2 ]
|
||||
Complete equivalence classes
|
||||
[ main::j#2 main::j#1 ]
|
||||
[ main::i#4 main::i#3 ]
|
||||
[ bar_thing1#0 ]
|
||||
[ bar_thing2#0 ]
|
||||
[ bar_thing3#0 ]
|
||||
[ main::barp#0 ]
|
||||
[ main::$4 ]
|
||||
[ bar_thing1 ]
|
||||
[ bar_thing2 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::j#2 main::j#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ main::i#4 main::i#3 ]
|
||||
Allocated zp ZP_BYTE:4 [ bar_thing1#0 ]
|
||||
Allocated zp ZP_BYTE:5 [ bar_thing2#0 ]
|
||||
Allocated zp ZP_WORD:6 [ bar_thing3#0 ]
|
||||
Allocated zp ZP_WORD:8 [ main::barp#0 ]
|
||||
Allocated zp ZP_WORD:10 [ main::$4 ]
|
||||
Allocated zp ZP_WORD:4 [ bar_thing3#0 ]
|
||||
Allocated mem [ bar_thing1 ]
|
||||
Allocated mem [ bar_thing2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
@ -270,18 +264,15 @@ Target platform is c64basic / MOS6502X
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.const OFFSET_STRUCT_FOO_THING3 = 2
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 4
|
||||
.label bar_thing2 = 5
|
||||
.label bar_thing3 = 6
|
||||
.label bar_thing3 = 4
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] (byte[$c]) bar_thing3#0 ← (const string) $0 -- pbuz1=pbuc1
|
||||
lda #<__0
|
||||
sta.z bar_thing3
|
||||
@ -301,115 +292,87 @@ __bend_from___b1:
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label __4 = $a
|
||||
.label barp = 8
|
||||
.label i = 3
|
||||
.label j = 2
|
||||
// [6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// [7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
// [9] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [9] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
// [8] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #2
|
||||
sta.z i
|
||||
// [9] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
// [8] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z j
|
||||
jmp __b1
|
||||
// [9] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [8] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [9] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [9] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
// [8] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [8] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #OFFSET_STRUCT_FOO_THING3
|
||||
clc
|
||||
adc.z barp
|
||||
sta.z __4
|
||||
lda #0
|
||||
adc.z barp+1
|
||||
sta.z __4+1
|
||||
// [11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuz3
|
||||
ldx.z i
|
||||
// [9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
|
||||
ldy.z j
|
||||
lda (__4),y
|
||||
sta SCREEN,x
|
||||
// [12] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuz1=_inc_vbuz1
|
||||
lda barp+OFFSET_STRUCT_FOO_THING3,y
|
||||
ldy.z i
|
||||
sta SCREEN,y
|
||||
// [10] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [13] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuz1=_inc_vbuz1
|
||||
// [11] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z j
|
||||
// [14] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
// [12] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$c
|
||||
cmp.z j
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [15] return
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .text "qwe"
|
||||
.byte 0
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] (byte) bar_thing1#0 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2#0 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) bar_thing1 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [2] (byte[$c]) bar_thing3#0 ← (const string) $0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3 [ main::barp#0 main::j#2 main::i#4 main::$4 ] ( main:4 [ main::barp#0 main::j#2 main::i#4 main::$4 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:4 [ main::j#2 main::i#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::j#2 main::j#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::i#4 main::i#3 ]
|
||||
Statement [11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2) [ main::barp#0 main::j#2 main::i#4 ] ( main:4 [ main::barp#0 main::j#2 main::i#4 ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) bar_thing1#0 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2#0 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [0] (byte) bar_thing1 ← (byte) 'a' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2 ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [2] (byte[$c]) bar_thing3#0 ← (const string) $0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) [ main::barp#0 ] ( main:4 [ main::barp#0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3 [ main::barp#0 main::j#2 main::i#4 main::$4 ] ( main:4 [ main::barp#0 main::j#2 main::i#4 main::$4 ] ) always clobbers reg byte a
|
||||
Statement [11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2) [ main::barp#0 main::j#2 main::i#4 ] ( main:4 [ main::barp#0 main::j#2 main::i#4 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:4 [ main::j#2 main::i#4 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::j#2 main::j#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::i#4 main::i#3 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ bar_thing1#0 ] : zp ZP_BYTE:4 ,
|
||||
Potential registers zp ZP_BYTE:5 [ bar_thing2#0 ] : zp ZP_BYTE:5 ,
|
||||
Potential registers zp ZP_WORD:6 [ bar_thing3#0 ] : zp ZP_WORD:6 ,
|
||||
Potential registers zp ZP_WORD:8 [ main::barp#0 ] : zp ZP_WORD:8 ,
|
||||
Potential registers zp ZP_WORD:10 [ main::$4 ] : zp ZP_WORD:10 ,
|
||||
Potential registers zp ZP_WORD:4 [ bar_thing3#0 ] : zp ZP_WORD:4 ,
|
||||
Potential registers mem [ bar_thing1 ] : mem ,
|
||||
Potential registers mem [ bar_thing2 ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 24.75: zp ZP_BYTE:2 [ main::j#2 main::j#1 ] 22: zp ZP_WORD:10 [ main::$4 ] 18.33: zp ZP_BYTE:3 [ main::i#4 main::i#3 ] 0.22: zp ZP_WORD:8 [ main::barp#0 ]
|
||||
Uplift Scope [] 20: zp ZP_BYTE:4 [ bar_thing1#0 ] 20: zp ZP_BYTE:5 [ bar_thing2#0 ] 20: zp ZP_WORD:6 [ bar_thing3#0 ]
|
||||
Uplift Scope [] 20: zp ZP_WORD:4 [ bar_thing3#0 ] 20: mem [ bar_thing1 ] 20: mem [ bar_thing2 ]
|
||||
Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::j#2 main::j#1 ] 23.83: zp ZP_BYTE:3 [ main::i#4 main::i#3 ]
|
||||
Uplift Scope [foo]
|
||||
|
||||
Uplifting [main] best 570 combination reg byte y [ main::j#2 main::j#1 ] zp ZP_WORD:10 [ main::$4 ] reg byte x [ main::i#4 main::i#3 ] zp ZP_WORD:8 [ main::barp#0 ]
|
||||
Uplifting [] best 570 combination zp ZP_BYTE:4 [ bar_thing1#0 ] zp ZP_BYTE:5 [ bar_thing2#0 ] zp ZP_WORD:6 [ bar_thing3#0 ]
|
||||
Uplifting [foo] best 570 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:4 [ bar_thing1#0 ]
|
||||
Uplifting [] best 570 combination zp ZP_BYTE:4 [ bar_thing1#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:5 [ bar_thing2#0 ]
|
||||
Uplifting [] best 570 combination zp ZP_BYTE:5 [ bar_thing2#0 ]
|
||||
Allocated (was zp ZP_BYTE:4) zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
Allocated (was zp ZP_WORD:6) zp ZP_WORD:4 [ bar_thing3#0 ]
|
||||
Allocated (was zp ZP_WORD:8) zp ZP_WORD:6 [ main::barp#0 ]
|
||||
Allocated (was zp ZP_WORD:10) zp ZP_WORD:8 [ main::$4 ]
|
||||
Uplifting [] best 576 combination zp ZP_WORD:4 [ bar_thing3#0 ] mem [ bar_thing1 ] mem [ bar_thing2 ]
|
||||
Uplifting [main] best 366 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ]
|
||||
Uplifting [foo] best 366 combination
|
||||
Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ bar_thing3#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -422,18 +385,15 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.const OFFSET_STRUCT_FOO_THING3 = 2
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
.label bar_thing3 = 4
|
||||
.label bar_thing3 = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] (byte[$c]) bar_thing3#0 ← (const string) $0 -- pbuz1=pbuc1
|
||||
lda #<__0
|
||||
sta.z bar_thing3
|
||||
@ -453,63 +413,49 @@ __bend_from___b1:
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label __4 = 8
|
||||
.label barp = 6
|
||||
// [6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// [7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
// [9] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [9] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [8] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #2
|
||||
// [9] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||
// [8] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
jmp __b1
|
||||
// [9] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [8] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
// [9] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [9] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
// [8] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [8] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #OFFSET_STRUCT_FOO_THING3
|
||||
clc
|
||||
adc.z barp
|
||||
sta.z __4
|
||||
lda #0
|
||||
adc.z barp+1
|
||||
sta.z __4+1
|
||||
// [11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (__4),y
|
||||
// [9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
|
||||
lda barp+OFFSET_STRUCT_FOO_THING3,y
|
||||
sta SCREEN,x
|
||||
// [12] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuxx=_inc_vbuxx
|
||||
// [10] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [13] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuyy=_inc_vbuyy
|
||||
// [11] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
// [12] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
cpy #$c
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [15] return
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .text "qwe"
|
||||
.byte 0
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
@ -539,41 +485,35 @@ FINAL SYMBOL TABLE
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_FOO_THING3 OFFSET_STRUCT_FOO_THING3 = (byte) 2
|
||||
(const struct foo*) bar_ptr bar_ptr = (struct foo*)&(byte) bar_thing1#0
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 bar_thing1 zp ZP_BYTE:2 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 bar_thing2 zp ZP_BYTE:3 20.0
|
||||
(byte) bar_thing1 memory mem 20.0
|
||||
(byte) bar_thing2 memory mem 20.0
|
||||
(byte[$c]) bar_thing3
|
||||
(byte[$c]) bar_thing3#0 bar_thing3 zp ZP_WORD:4 20.0
|
||||
(byte[$c]) bar_thing3#0 bar_thing3 zp ZP_WORD:2 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(byte[$c]) foo::thing3
|
||||
(void()) main()
|
||||
(byte[$c]) main::$4 $4 zp ZP_WORD:8 22.0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 barp zp ZP_WORD:6 0.2222222222222222
|
||||
(const struct foo*) main::barp#0 barp = (struct foo*)&(byte) bar_thing1
|
||||
(byte) main::i
|
||||
(byte) main::i#3 reg byte x 7.333333333333333
|
||||
(byte) main::i#4 reg byte x 11.0
|
||||
(byte) main::i#4 reg byte x 16.5
|
||||
(byte) main::j
|
||||
(byte) main::j#1 reg byte y 16.5
|
||||
(byte) main::j#2 reg byte y 8.25
|
||||
(byte) main::j#2 reg byte y 11.0
|
||||
|
||||
reg byte y [ main::j#2 main::j#1 ]
|
||||
reg byte x [ main::i#4 main::i#3 ]
|
||||
zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
zp ZP_WORD:4 [ bar_thing3#0 ]
|
||||
zp ZP_WORD:6 [ main::barp#0 ]
|
||||
zp ZP_WORD:8 [ main::$4 ]
|
||||
zp ZP_WORD:2 [ bar_thing3#0 ]
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 480
|
||||
Score: 276
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
@ -585,19 +525,16 @@ Score: 480
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_FOO_THING2 = 1
|
||||
.const OFFSET_STRUCT_FOO_THING3 = 2
|
||||
.label bar_ptr = bar_thing1
|
||||
.label bar_thing1 = 2
|
||||
.label bar_thing2 = 3
|
||||
.label bar_thing3 = 4
|
||||
.label bar_thing3 = 2
|
||||
// @begin
|
||||
__bbegin:
|
||||
// bar = { 'a', 'b', "qwe" }
|
||||
// [0] (byte) bar_thing1#0 ← (byte) 'a' -- vbuz1=vbuc1
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta.z bar_thing1
|
||||
// [1] (byte) bar_thing2#0 ← (byte) 'b' -- vbuz1=vbuc1
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta.z bar_thing2
|
||||
sta bar_thing2
|
||||
// [2] (byte[$c]) bar_thing3#0 ← (const string) $0 -- pbuz1=pbuc1
|
||||
lda #<__0
|
||||
sta.z bar_thing3
|
||||
@ -612,62 +549,47 @@ __bbegin:
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label barp = bar_thing1
|
||||
.label SCREEN = $400
|
||||
.label __4 = 8
|
||||
.label barp = 6
|
||||
// barp = &bar
|
||||
// [6] (struct foo*) main::barp#0 ← & *((const struct foo*) bar_ptr) -- pssz1=_addr__deref_pssc1
|
||||
lda #<bar_ptr
|
||||
sta.z barp
|
||||
lda #>bar_ptr
|
||||
sta.z barp+1
|
||||
// SCREEN[i++] = barp->thing1
|
||||
// [7] *((const byte*) main::SCREEN) ← *((byte*)(struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (barp),y
|
||||
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp
|
||||
sta SCREEN
|
||||
// SCREEN[i++] = barp->thing2
|
||||
// [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=pbuz1_derefidx_vbuc2
|
||||
ldy #OFFSET_STRUCT_FOO_THING2
|
||||
lda (barp),y
|
||||
// [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda barp+OFFSET_STRUCT_FOO_THING2
|
||||
sta SCREEN+1
|
||||
// [9] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [9] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
// [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [8] phi (byte) main::i#4 = (byte) 2 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #2
|
||||
// [9] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||
// [8] phi (byte) main::j#2 = (byte) 0 [phi:main->main::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [9] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [9] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [9] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
// [8] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
// [8] phi (byte) main::i#4 = (byte) main::i#3 [phi:main::@1->main::@1#0] -- register_copy
|
||||
// [8] phi (byte) main::j#2 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy
|
||||
// main::@1
|
||||
__b1:
|
||||
// SCREEN[i++] = barp->thing3[j]
|
||||
// [10] (byte[$c]) main::$4 ← (byte[$c])(struct foo*) main::barp#0 + (const byte) OFFSET_STRUCT_FOO_THING3 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #OFFSET_STRUCT_FOO_THING3
|
||||
clc
|
||||
adc.z barp
|
||||
sta.z __4
|
||||
lda #0
|
||||
adc.z barp+1
|
||||
sta.z __4+1
|
||||
// [11] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c]) main::$4 + (byte) main::j#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (__4),y
|
||||
// [9] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte[$c])(const struct foo*) main::barp#0+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
|
||||
lda barp+OFFSET_STRUCT_FOO_THING3,y
|
||||
sta SCREEN,x
|
||||
// SCREEN[i++] = barp->thing3[j];
|
||||
// [12] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuxx=_inc_vbuxx
|
||||
// [10] (byte) main::i#3 ← ++ (byte) main::i#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// for( char j: 0..11)
|
||||
// [13] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuyy=_inc_vbuyy
|
||||
// [11] (byte) main::j#1 ← ++ (byte) main::j#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
// [12] if((byte) main::j#1!=(byte) $c) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
|
||||
cpy #$c
|
||||
bne __b1
|
||||
// main::@return
|
||||
// }
|
||||
// [15] return
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .text "qwe"
|
||||
.byte 0
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
|
@ -4,34 +4,28 @@
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_FOO_THING2 OFFSET_STRUCT_FOO_THING2 = (byte) 1
|
||||
(const byte) OFFSET_STRUCT_FOO_THING3 OFFSET_STRUCT_FOO_THING3 = (byte) 2
|
||||
(const struct foo*) bar_ptr bar_ptr = (struct foo*)&(byte) bar_thing1#0
|
||||
(byte) bar_thing1
|
||||
(byte) bar_thing1#0 bar_thing1 zp ZP_BYTE:2 20.0
|
||||
(byte) bar_thing2
|
||||
(byte) bar_thing2#0 bar_thing2 zp ZP_BYTE:3 20.0
|
||||
(byte) bar_thing1 memory mem 20.0
|
||||
(byte) bar_thing2 memory mem 20.0
|
||||
(byte[$c]) bar_thing3
|
||||
(byte[$c]) bar_thing3#0 bar_thing3 zp ZP_WORD:4 20.0
|
||||
(byte[$c]) bar_thing3#0 bar_thing3 zp ZP_WORD:2 20.0
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(byte[$c]) foo::thing3
|
||||
(void()) main()
|
||||
(byte[$c]) main::$4 $4 zp ZP_WORD:8 22.0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(struct foo*) main::barp
|
||||
(struct foo*) main::barp#0 barp zp ZP_WORD:6 0.2222222222222222
|
||||
(const struct foo*) main::barp#0 barp = (struct foo*)&(byte) bar_thing1
|
||||
(byte) main::i
|
||||
(byte) main::i#3 reg byte x 7.333333333333333
|
||||
(byte) main::i#4 reg byte x 11.0
|
||||
(byte) main::i#4 reg byte x 16.5
|
||||
(byte) main::j
|
||||
(byte) main::j#1 reg byte y 16.5
|
||||
(byte) main::j#2 reg byte y 8.25
|
||||
(byte) main::j#2 reg byte y 11.0
|
||||
|
||||
reg byte y [ main::j#2 main::j#1 ]
|
||||
reg byte x [ main::i#4 main::i#3 ]
|
||||
zp ZP_BYTE:2 [ bar_thing1#0 ]
|
||||
zp ZP_BYTE:3 [ bar_thing2#0 ]
|
||||
zp ZP_WORD:4 [ bar_thing3#0 ]
|
||||
zp ZP_WORD:6 [ main::barp#0 ]
|
||||
zp ZP_WORD:8 [ main::$4 ]
|
||||
zp ZP_WORD:2 [ bar_thing3#0 ]
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
||||
|
22
src/test/ref/declared-memory-var-5.asm
Normal file
22
src/test/ref/declared-memory-var-5.asm
Normal file
@ -0,0 +1,22 @@
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
__bbegin:
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
lda bar_thing1
|
||||
sta SCREEN
|
||||
lda bar_thing2
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
19
src/test/ref/declared-memory-var-5.cfg
Normal file
19
src/test/ref/declared-memory-var-5.cfg
Normal file
@ -0,0 +1,19 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] *((const byte*) main::SCREEN) ← (byte) bar_thing1
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[7] return
|
||||
to:@return
|
324
src/test/ref/declared-memory-var-5.log
Normal file
324
src/test/ref/declared-memory-var-5.log
Normal file
@ -0,0 +1,324 @@
|
||||
Created struct value member variable (byte) bar_thing1
|
||||
Created struct value member variable (byte) bar_thing2
|
||||
Converted struct value to member variables (struct foo) bar
|
||||
Adding struct value list initializer (byte) bar_thing1 ← (byte) 'a'
|
||||
Adding struct value list initializer (byte) bar_thing2 ← (byte) 'b'
|
||||
Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference (byte) bar_thing1
|
||||
Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference (byte) bar_thing2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) bar_thing1 ← (byte) 'a'
|
||||
(byte) bar_thing2 ← (byte) 'b'
|
||||
to:@1
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
(byte*) main::SCREEN ← ((byte*)) (number) $400
|
||||
(byte) main::i#0 ← (number) 0
|
||||
*((byte*) main::SCREEN + (byte) main::i#0) ← (byte) bar_thing1
|
||||
(byte) main::i#1 ← ++ (byte) main::i#0
|
||||
*((byte*) main::SCREEN + (byte) main::i#1) ← (byte) bar_thing2
|
||||
(byte) main::i#2 ← ++ (byte) main::i#1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) bar_thing1 memory
|
||||
(byte) bar_thing2 memory
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(byte*) main::SCREEN
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (byte) main::i#0 ← (number) 0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) main::SCREEN ← (byte*)(number) $400
|
||||
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant (const byte*) main::SCREEN = (byte*) 1024
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (const byte) main::i#0) ← (byte) bar_thing1
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte) main::i#2 and assignment [5] (byte) main::i#2 ← ++ (byte) main::i#1
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Constant right-side identified [3] (byte) main::i#1 ← ++ (const byte) main::i#0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#1 = ++main::i#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with different constant siblings (const byte) main::i#0
|
||||
Inlining constant with different constant siblings (const byte) main::i#1
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#1 = ++(byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *(main::SCREEN+++0)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
Simplifying constant integer increment ++0
|
||||
Successful SSA optimization Pass2ConstantSimplification
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] (byte) bar_thing1 ← (byte) 'a'
|
||||
[1] (byte) bar_thing2 ← (byte) 'b'
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[4] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[5] *((const byte*) main::SCREEN) ← (byte) bar_thing1
|
||||
[6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[7] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) bar_thing1 memory 1.3333333333333333
|
||||
(byte) bar_thing2 memory 1.3333333333333333
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(byte) main::i
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable bar_thing1 to zero page equivalence class [ bar_thing1 ]
|
||||
Added variable bar_thing2 to zero page equivalence class [ bar_thing2 ]
|
||||
Complete equivalence classes
|
||||
[ bar_thing1 ]
|
||||
[ bar_thing2 ]
|
||||
Allocated mem [ bar_thing1 ]
|
||||
Allocated mem [ bar_thing2 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// [5] *((const byte*) main::SCREEN) ← (byte) bar_thing1 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing1
|
||||
sta SCREEN
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] (byte) bar_thing1 ← (byte) 'a' [ bar_thing1 ] ( [ bar_thing1 ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) bar_thing2 ← (byte) 'b' [ bar_thing1 bar_thing2 ] ( [ bar_thing1 bar_thing2 ] ) always clobbers reg byte a
|
||||
Statement [5] *((const byte*) main::SCREEN) ← (byte) bar_thing1 [ bar_thing2 ] ( main:3 [ bar_thing2 ] ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2 [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Potential registers mem [ bar_thing1 ] : mem ,
|
||||
Potential registers mem [ bar_thing2 ] : mem ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 1.33: mem [ bar_thing1 ] 1.33: mem [ bar_thing2 ]
|
||||
Uplift Scope [foo]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [] best 49 combination mem [ bar_thing1 ] mem [ bar_thing2 ]
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [3] call main
|
||||
jsr main
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// [5] *((const byte*) main::SCREEN) ← (byte) bar_thing1 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing1
|
||||
sta SCREEN
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing2
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __bend:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) bar_thing1 memory mem 1.3333333333333333
|
||||
(byte) bar_thing2 memory mem 1.3333333333333333
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(byte) main::i
|
||||
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 46
|
||||
|
||||
// File Comments
|
||||
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
|
||||
// Test a memory variable struct value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
__bbegin:
|
||||
// bar = { 'a', 'b' }
|
||||
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
|
||||
lda #'a'
|
||||
sta bar_thing1
|
||||
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
|
||||
lda #'b'
|
||||
sta bar_thing2
|
||||
// [2] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [3] call main
|
||||
jsr main
|
||||
rts
|
||||
// [4] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// SCREEN[i++] = bar.thing1
|
||||
// [5] *((const byte*) main::SCREEN) ← (byte) bar_thing1 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing1
|
||||
sta SCREEN
|
||||
// SCREEN[i++] = bar.thing2
|
||||
// [6] *((const byte*) main::SCREEN+(byte) 1) ← (byte) bar_thing2 -- _deref_pbuc1=vbum1
|
||||
lda bar_thing2
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [7] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
bar_thing1: .byte 0
|
||||
bar_thing2: .byte 0
|
||||
|
14
src/test/ref/declared-memory-var-5.sym
Normal file
14
src/test/ref/declared-memory-var-5.sym
Normal file
@ -0,0 +1,14 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte) bar_thing1 memory mem 1.3333333333333333
|
||||
(byte) bar_thing2 memory mem 1.3333333333333333
|
||||
(byte) foo::thing1
|
||||
(byte) foo::thing2
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::SCREEN SCREEN = (byte*) 1024
|
||||
(byte) main::i
|
||||
|
||||
mem [ bar_thing1 ]
|
||||
mem [ bar_thing2 ]
|
Loading…
x
Reference in New Issue
Block a user