1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-13 03:39:12 +00:00

Implemented C-classic struct functionality for loadstore struct variables. Works for most scenarios: declaration, initialization, assignment, member-access. Structs containing arrays not working yet.

This commit is contained in:
jespergravgaard 2019-12-27 22:35:05 +01:00
parent 3b043e11a7
commit e8a0478e5f
90 changed files with 7456 additions and 519 deletions
src
main/java/dk/camelot64/kickc
test

@ -190,6 +190,7 @@ public class Compiler {
new Pass1PointerSizeofFix(program).execute(); // After this point in the code all pointer math is byte-based
new PassNSizeOfSimplification(program).execute(); // Needed to eliminate sizeof() referencing pointer value variables
new Pass1UnwindStructVariables(program).execute();
new Pass1UnwindStructValues(program).execute();
new PassNStructPointerRewriting(program).execute();

@ -1,5 +1,7 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
@ -45,31 +47,29 @@ public class StructUnwinding {
public static class VariableUnwinding implements StructMemberUnwinding {
/** Maps member names to the unwound variables. */
Map<String, SymbolVariableRef> memberUnwinding = new LinkedHashMap<>();
Map<String, RValue> memberUnwinding = new LinkedHashMap<>();
/** Maps member names to the unwound variable types. */
Map<String, SymbolType> typesUnwinding = new LinkedHashMap<>();
/** Set how a member variable was unwound to a specific (new) variable. */
public void setMemberUnwinding(String memberName, SymbolVariableRef memberVariableUnwound) {
public void setMemberUnwinding(String memberName, RValue memberVariableUnwound, SymbolType memberType) {
this.memberUnwinding.put(memberName, memberVariableUnwound);
this.typesUnwinding.put(memberName, memberType);
}
/**
* Get the names of the members of the struct
*
* @return the names
*/
public List<String> getMemberNames() {
return new ArrayList<>(memberUnwinding.keySet());
}
/**
* Get the (new) variable that a specific member was unwound to
*
* @param memberName The member name
* @return The new variable
*/
public RValue getMemberUnwinding(String memberName) {
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
return this.memberUnwinding.get(memberName);
}
@Override
public SymbolType getMemberType(String memberName) {
return this.typesUnwinding.get(memberName);
}
}
/** Information about how members of an struct Lvalue is unwound. */
@ -86,8 +86,16 @@ public class StructUnwinding {
* Get the RValue that a specific member was unwound to
*
* @param memberName The member name
* @param programScope The program scope
* @return The unwinding of the member
*/
RValue getMemberUnwinding(String memberName);
RValue getMemberUnwinding(String memberName, ProgramScope programScope);
/**
* Get the type of a specific member
* @param memberName The name of the struct member
* @return The type of the member
*/
SymbolType getMemberType(String memberName);
}
}

@ -539,6 +539,27 @@ public class Variable implements Symbol {
return isVolatile || inferredVolatile;
}
/**
* Is the variable a struct that should be unwound to member variables
*
* @return true if an unwinding struct
*/
public boolean isStructUnwind() {
if(getType() instanceof SymbolTypeStruct)
return isKindPhiMaster() || isKindIntermediate() || isKindPhiVersion();
else
return false;
}
/**
* Is the variable a struct that should be handled using C Classic memory layout
*
* @return true if an classic struct
*/
public boolean isStructClassic() {
return getType() instanceof SymbolTypeStruct && isKindLoadStore();
}
public List<Comment> getComments() {
return comments;
}

@ -80,7 +80,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
if(returnVarUnwinding!=null) {
ArrayList<RValue> unwoundReturnVars = new ArrayList<>();
for(String memberName : returnVarUnwinding.getMemberNames()) {
unwoundReturnVars.add(returnVarUnwinding.getMemberUnwinding(memberName));
unwoundReturnVars.add(returnVarUnwinding.getMemberUnwinding(memberName, getScope()));
}
procReturnVarRef = new ValueList(unwoundReturnVars);
}

@ -1,7 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.*;
@ -18,10 +18,9 @@ import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicBoolean;
/** Convert all struct values that are not used as pointers (address-of used or declared volatile) into variables representing each member */
/** Convert all unwinding struct values into variables representing each member */
public class Pass1UnwindStructValues extends Pass1Base {
public Pass1UnwindStructValues(Program program) {
super(program);
}
@ -31,9 +30,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(getProgram().getStructUnwinding() == null) {
getProgram().setStructUnwinding(new StructUnwinding());
}
// Iterate through all scopes generating member-variables for each struct
boolean modified = false;
modified |= unwindStructVariables();
// Unwind all procedure declaration parameters
modified |= unwindStructParameters();
// Unwind all usages of struct values
@ -76,7 +73,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(structMemberRef.getStruct() instanceof VariableRef) {
StructUnwinding.StructMemberUnwinding memberVariables = getStructMemberUnwinding(structMemberRef.getStruct(), currentStmt, stmtIt, currentBlock);
if(memberVariables != null && memberVariables != POSTPONE_UNWINDING) {
RValue structMemberVariable = memberVariables.getMemberUnwinding(structMemberRef.getMemberName());
RValue structMemberVariable = memberVariables.getMemberUnwinding(structMemberRef.getMemberName(), getScope());
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member unwinding reference " + structMemberVariable.toString(getProgram()));
programValue.set(structMemberVariable);
modified.set(true);
@ -99,7 +96,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(lValueUnwinding != null && lValueUnwinding != POSTPONE_UNWINDING) {
ArrayList<RValue> unwoundMembers = new ArrayList<>();
for(String memberName : lValueUnwinding.getMemberNames()) {
unwoundMembers.add(lValueUnwinding.getMemberUnwinding(memberName));
unwoundMembers.add(lValueUnwinding.getMemberUnwinding(memberName, getScope()));
}
ValueList unwoundLValue = new ValueList(unwoundMembers);
call.setlValue(unwoundLValue);
@ -116,7 +113,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(parameterUnwinding != null && parameterUnwinding != POSTPONE_UNWINDING) {
// Passing a struct variable - convert it to member variables
for(String memberName : parameterUnwinding.getMemberNames()) {
unwoundParameters.add(parameterUnwinding.getMemberUnwinding(memberName));
unwoundParameters.add(parameterUnwinding.getMemberUnwinding(memberName, getScope()));
}
unwound = true;
anyParameterUnwound = true;
@ -146,7 +143,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(returnVarUnwinding != null && returnVarUnwinding != POSTPONE_UNWINDING) {
ArrayList<RValue> unwoundMembers = new ArrayList<>();
for(String memberName : returnVarUnwinding.getMemberNames()) {
unwoundMembers.add(returnVarUnwinding.getMemberUnwinding(memberName));
unwoundMembers.add(returnVarUnwinding.getMemberUnwinding(memberName, getScope()));
}
ValueList unwoundReturnValue = new ValueList(unwoundMembers);
statementReturn.setValue(unwoundReturnValue);
@ -171,7 +168,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
StructUnwinding.VariableUnwinding parameterUnwinding = structUnwinding.getVariableUnwinding(parameter.getRef());
for(String memberName : parameterUnwinding.getMemberNames()) {
SymbolVariableRef memberUnwinding = (SymbolVariableRef) parameterUnwinding.getMemberUnwinding(memberName);
SymbolVariableRef memberUnwinding = (SymbolVariableRef) parameterUnwinding.getMemberUnwinding(memberName, getScope());
unwoundParameterNames.add(memberUnwinding.getLocalName());
procedureUnwound = true;
}
@ -188,40 +185,6 @@ public class Pass1UnwindStructValues extends Pass1Base {
return modified;
}
/**
* Iterate through all scopes generating member-variables for each struct variable
*
* @return Information about all unwound struct variables
*/
private boolean unwindStructVariables() {
boolean modified = false;
// Iterate through all scopes generating member-variables for each struct
for(Variable variable : getScope().getAllVariables(true)) {
if(variable.getType() instanceof SymbolTypeStruct) {
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
// A non-volatile struct variable
Scope scope = variable.getScope();
if(!(scope instanceof StructDefinition)) {
// Not inside another struct
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef());
for(Variable member : structDefinition.getAllVars(false)) {
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
scope.add(memberVariable);
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef());
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
}
getLog().append("Converted struct value to member variables " + variable.toString(getProgram()));
modified = true;
}
}
}
}
return modified;
}
/**
* Unwind an assignment to a struct value variable into assignment of each member
*
@ -244,12 +207,12 @@ public class Pass1UnwindStructValues extends Pass1Base {
List<RValue> membersUnwound = new ArrayList<>();
stmtIt.previous();
for(String memberName : memberUnwinding.getMemberNames()) {
SymbolVariableRef memberVarRef = (SymbolVariableRef) memberUnwinding.getMemberUnwinding(memberName);
LValue memberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
membersUnwound.add(memberVarRef);
Variable memberVar = getScope().getVariable(memberVarRef);
StatementSource statementSource = assignment.getSource();
RValue initValue = Initializers.createZeroValue(memberVar.getType(), statementSource);
Statement initStmt = new StatementAssignment((LValue) memberVarRef, initValue, assignment.isInitialAssignment(), statementSource, Comment.NO_COMMENTS);
SymbolType memberType = memberUnwinding.getMemberType(memberName);
RValue initValue = Initializers.createZeroValue(memberType, statementSource);
Statement initStmt = new StatementAssignment(memberVarRef, initValue, assignment.isInitialAssignment(), statementSource, Comment.NO_COMMENTS);
stmtIt.add(initStmt);
getLog().append("Adding struct value member variable default initializer " + initStmt.toString(getProgram(), false));
}
@ -271,7 +234,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
List<RValue> membersUnwound = new ArrayList<>();
int idx = 0;
for(String memberName : memberUnwinding.getMemberNames()) {
LValue memberLvalue = (LValue) memberUnwinding.getMemberUnwinding(memberName);
LValue memberLvalue = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
membersUnwound.add(memberLvalue);
Statement initStmt = new StatementAssignment(memberLvalue, valueList.getList().get(idx++), assignment.isInitialAssignment(), assignment.getSource(), Comment.NO_COMMENTS);
stmtIt.add(initStmt);
@ -301,8 +264,8 @@ public class Pass1UnwindStructValues extends Pass1Base {
List<RValue> membersUnwound = new ArrayList<>();
stmtIt.previous();
for(String memberName : memberUnwinding.getMemberNames()) {
LValue assignedMemberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName);
RValue sourceMemberVarRef = sourceMemberUnwinding.getMemberUnwinding(memberName);
LValue assignedMemberVarRef = (LValue) memberUnwinding.getMemberUnwinding(memberName, getScope());
RValue sourceMemberVarRef = sourceMemberUnwinding.getMemberUnwinding(memberName, getScope());
membersUnwound.add(assignedMemberVarRef);
Statement copyStmt = new StatementAssignment(assignedMemberVarRef, sourceMemberVarRef, assignment.isInitialAssignment(), assignment.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt);
@ -335,12 +298,17 @@ public class Pass1UnwindStructValues extends Pass1Base {
*/
private StructUnwinding.StructMemberUnwinding getStructMemberUnwinding(RValue value, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
if(value != null) {
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), value);
if(lValueType instanceof SymbolTypeStruct) {
SymbolTypeStruct structType = (SymbolTypeStruct) lValueType;
SymbolType valueType = SymbolTypeInference.inferType(getScope(), value);
if(valueType instanceof SymbolTypeStruct) {
SymbolTypeStruct structType = (SymbolTypeStruct) valueType;
if(value instanceof VariableRef) {
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
return structUnwinding.getVariableUnwinding((VariableRef) value);
Variable variable = getScope().getVariable((VariableRef) value);
if(variable.isStructUnwind()) {
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
return structUnwinding.getVariableUnwinding((VariableRef) value);
} else if(variable.isStructClassic()) {
return new StructVariableMemberUnwinding(variable, structType.getStructDefinition(getScope()), currentBlock, stmtIt, currentStmt);
}
} else if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof VariableRef) {
return POSTPONE_UNWINDING;
} else if(value instanceof PointerDereferenceSimple) {
@ -348,7 +316,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
} else if(value instanceof PointerDereferenceIndexed) {
return new StructMemberUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structType.getStructDefinition(getScope()), stmtIt, currentBlock, currentStmt);
} else if(value instanceof ConstantStructValue) {
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structType.getStructDefinition(getScope()), stmtIt, currentBlock, currentStmt);
return new StructMemberUnwindingConstantValue((ConstantStructValue) value, structType.getStructDefinition(getScope()));
} else if(value instanceof StructZero) {
return new StructMemberUnwindingZero((StructZero) value, structType.getStructDefinition(getScope()));
} else {
throw new InternalError("Struct unwinding not implemented for " + value.toString(getProgram()));
}
@ -365,13 +335,18 @@ public class Pass1UnwindStructValues extends Pass1Base {
}
@Override
public LValue getMemberUnwinding(String memberName) {
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
return null;
}
@Override
public SymbolType getMemberType(String memberName) {
return null;
}
};
/** Unwinding for a simple pointer deref to a struct. */
private class StructMemberUnwindingPointerDerefSimple implements StructUnwinding.StructMemberUnwinding {
private static class StructMemberUnwindingPointerDerefSimple implements StructUnwinding.StructMemberUnwinding {
private final StructDefinition structDefinition;
private final ControlFlowBlock currentBlock;
private final ListIterator<Statement> stmtIt;
@ -397,10 +372,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
}
@Override
public LValue getMemberUnwinding(String memberName) {
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(getScope(), structDefinition, memberName);
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
Variable member = structDefinition.getMember(memberName);
Scope scope = getScope().getScope(currentBlock.getScope());
Scope scope = programScope.getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(member.getType()));
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), pointerDeref.getPointer());
@ -409,14 +384,19 @@ public class Pass1UnwindStructValues extends Pass1Base {
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER)
return new PointerDereferenceSimple(memberAddress.getRef());
}
@Override
public SymbolType getMemberType(String memberName) {
return structDefinition.getMember(memberName).getType();
}
}
/** Unwinding for a indexed pointer deref to a struct. */
private class StructMemberUnwindingPointerDerefIndexed implements StructUnwinding.StructMemberUnwinding {
private static class StructMemberUnwindingPointerDerefIndexed implements StructUnwinding.StructMemberUnwinding {
private final PointerDereferenceIndexed pointerDeref;
private final StructDefinition structDefinition;
private final ControlFlowBlock currentBlock;
private final ListIterator<Statement> stmtIt;
private final PointerDereferenceIndexed pointerDeref;
private final Statement currentStmt;
StructMemberUnwindingPointerDerefIndexed(PointerDereferenceIndexed pointerDeref, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
@ -438,10 +418,10 @@ public class Pass1UnwindStructValues extends Pass1Base {
}
@Override
public LValue getMemberUnwinding(String memberName) {
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(getScope(), structDefinition, memberName);
public LValue getMemberUnwinding(String memberName, ProgramScope programScope) {
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
Variable member = structDefinition.getMember(memberName);
Scope scope = getScope().getScope(currentBlock.getScope());
Scope scope = programScope.getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(member.getType()));
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), pointerDeref.getPointer());
@ -450,18 +430,57 @@ public class Pass1UnwindStructValues extends Pass1Base {
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER[idx]
return new PointerDereferenceIndexed(memberAddress.getRef(), pointerDeref.getIndex());
}
@Override
public SymbolType getMemberType(String memberName) {
return structDefinition.getMember(memberName).getType();
}
}
/** Unwinding for a simple pointer deref to a struct. */
private class StructMemberUnwindingConstantValue implements StructUnwinding.StructMemberUnwinding {
/** Unwinding for constant struct value. */
private static class StructMemberUnwindingConstantValue implements StructUnwinding.StructMemberUnwinding {
private final ConstantStructValue constantStructValue;
private final StructDefinition structDefinition;
StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition) {
this.constantStructValue = constantStructValue;
this.structDefinition = structDefinition;
}
@Override
public List<String> getMemberNames() {
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
ArrayList<String> memberNames = new ArrayList<>();
for(Variable structMemberVar : structMemberVars) {
memberNames.add(structMemberVar.getLocalName());
}
return memberNames;
}
@Override
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
Variable member = structDefinition.getMember(memberName);
return constantStructValue.getValue(member.getRef());
}
@Override
public SymbolType getMemberType(String memberName) {
return structDefinition.getMember(memberName).getType();
}
}
/** Unwinding for a struct value with C-classic memory layout. */
private static class StructVariableMemberUnwinding implements StructUnwinding.StructMemberUnwinding {
private Variable variable;
private StructDefinition structDefinition;
private final ControlFlowBlock currentBlock;
private final ListIterator<Statement> stmtIt;
private final Statement currentStmt;
StructMemberUnwindingConstantValue(ConstantStructValue constantStructValue, StructDefinition structDefinition, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
this.constantStructValue = constantStructValue;
public StructVariableMemberUnwinding(Variable variable, StructDefinition structDefinition, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Statement currentStmt) {
this.variable = variable;
this.structDefinition = structDefinition;
this.currentBlock = currentBlock;
this.stmtIt = stmtIt;
@ -479,11 +498,56 @@ public class Pass1UnwindStructValues extends Pass1Base {
}
@Override
public RValue getMemberUnwinding(String memberName) {
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, structDefinition, memberName);
Variable member = structDefinition.getMember(memberName);
return constantStructValue.getValue(member.getRef());
Scope scope = programScope.getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(member.getType()));
ConstantSymbolPointer structPointer = new ConstantSymbolPointer(variable.getRef());
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(member.getType()), structPointer);
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
// Unwind to *(ptr_struct+OFFSET_STRUCT_NAME_MEMBER)
return new PointerDereferenceSimple(memberAddress.getRef());
}
@Override
public SymbolType getMemberType(String memberName) {
return structDefinition.getMember(memberName).getType();
}
}
/** Unwinding for StructZero */
private static class StructMemberUnwindingZero implements StructUnwinding.StructMemberUnwinding {
private StructZero structZero;
private StructDefinition structDefinition;
public StructMemberUnwindingZero(StructZero structZero, StructDefinition structDefinition) {
this.structZero = structZero;
this.structDefinition = structDefinition;
}
@Override
public List<String> getMemberNames() {
Collection<Variable> structMemberVars = structDefinition.getAllVariables(false);
ArrayList<String> memberNames = new ArrayList<>();
for(Variable structMemberVar : structMemberVars) {
memberNames.add(structMemberVar.getLocalName());
}
return memberNames;
}
@Override
public RValue getMemberUnwinding(String memberName, ProgramScope programScope) {
return ZeroConstantValues.zeroValue(getMemberType(memberName), programScope);
}
@Override
public SymbolType getMemberType(String memberName) {
return structDefinition.getMember(memberName).getType();
}
}
}

@ -0,0 +1,63 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.StructUnwinding;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
/** Create unwindings for all unwinding struct variables. The unwinding is a conversion to one variable per member.
* The unwindings are stored in {@link Program#getStructUnwinding()}
* */
public class Pass1UnwindStructVariables extends Pass1Base {
public Pass1UnwindStructVariables(Program program) {
super(program);
}
@Override
public boolean step() {
if(getProgram().getStructUnwinding() == null) {
getProgram().setStructUnwinding(new StructUnwinding());
}
// Iterate through all scopes generating member-variables for each struct
return unwindStructVariables();
}
/**
* Iterate through all scopes generating member-variables for each struct variable
*
* @return Information about all unwound struct variables
*/
private boolean unwindStructVariables() {
boolean modified = false;
// Iterate through all scopes generating member-variables for each struct
for(Variable variable : getScope().getAllVariables(true)) {
if(variable.isStructUnwind()) {
StructUnwinding structUnwinding = getProgram().getStructUnwinding();
if(structUnwinding.getVariableUnwinding(variable.getRef()) == null) {
// A non-volatile struct variable
Scope scope = variable.getScope();
if(!(scope instanceof StructDefinition)) {
// Not inside another struct
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
StructUnwinding.VariableUnwinding variableUnwinding = structUnwinding.createVariableUnwinding(variable.getRef());
for(Variable member : structDefinition.getAllVars(false)) {
boolean isParameter = scope instanceof Procedure && ((Procedure) scope).getParameters().contains(variable);
Variable memberVariable = Variable.createStructMemberUnwound(variable, member, isParameter);
scope.add(memberVariable);
variableUnwinding.setMemberUnwinding(member.getLocalName(), memberVariable.getRef(), memberVariable.getType());
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
}
getLog().append("Converted struct value to member variables " + variable.toString(getProgram()));
modified = true;
}
}
}
}
return modified;
}
}

@ -45,7 +45,7 @@ public class Pass1UnwindStructVersions extends Pass1Base {
while(memberDefIt.hasNext()) {
Variable memberVar = memberDefIt.next();
RValue memberVal = memberUnwoundIt.next();
versionedUnwinding.setMemberUnwinding(memberVar.getLocalName(), (VariableRef) memberVal);
versionedUnwinding.setMemberUnwinding(memberVar.getLocalName(), memberVal, memberVar.getType());
}
getLog().append("Adding versioned struct unwinding for "+assignment.getlValue().toString(getProgram()));
modified = true;

@ -33,7 +33,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
// Add all versions of volatile variables to the same equivalence class
for(Variable variable : getSymbols().getAllVariables(true)) {
if(variable.isKindPhiVersion() && variable.isAnyVolatile()) {
if(variable.isKindPhiVersion() && variable.isAnyVolatile() && !variable.isStructUnwind()) {
// Found a volatile non-versioned variable
for(Variable otherVariable : variable.getScope().getAllVariables(false)) {
if(otherVariable.isKindPhiVersion()) {
@ -51,10 +51,15 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
}
}
// Add all other variables one by one to an available equivalence class - or create a new one
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
equivalenceClassAdder.visitGraph(getGraph());
// Add any remaining struct load/store variables
for(Variable variable : getSymbols().getAllVariables(true))
if(variable.isStructClassic())
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet );
getLog().append("Complete equivalence classes");
for(LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
getLog().append(liveRangeEquivalenceClass.toString());
@ -63,6 +68,36 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
getProgram().setLiveRangeEquivalenceClassSet(liveRangeEquivalenceClassSet);
}
void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences, LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
LiveRangeEquivalenceClass lValEquivalenceClass =
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
if(lValEquivalenceClass == null) {
LiveRange lValLiveRange = liveRangeVariables.getLiveRange(lValVar);
// Variable in need of an equivalence class - Look through preferences
LiveRangeEquivalenceClass chosen = null;
for(VariableRef preference : preferences) {
LiveRangeEquivalenceClass preferenceEquivalenceClass = liveRangeEquivalenceClassSet.getEquivalenceClass(preference);
if(preferenceEquivalenceClass != null) {
Variable potentialVariable = getProgram().getSymbolInfos().getVariable(preference);
Variable lValVariable = getProgram().getSymbolInfos().getVariable(lValVar);
if(lValVariable.getType().equals(potentialVariable.getType())) {
if(!lValLiveRange.overlaps(preferenceEquivalenceClass.getLiveRange())) {
chosen = preferenceEquivalenceClass;
chosen.addVariable(lValVar);
break;
}
}
}
}
if(chosen == null) {
// No preference usable - create a new one
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
}
getLog().append("Added variable " + lValVar + " to live range equivalence class " + chosen);
}
}
/**
* Add all variables to a non-overlapping equivalence or create a new one.
*/
@ -79,7 +114,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
if(assignment.getlValue() instanceof VariableRef) {
VariableRef lValVar = (VariableRef) assignment.getlValue();
List<VariableRef> preferences = new ArrayList<>();
addToEquivalenceClassSet(lValVar, preferences);
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
}
return null;
}
@ -89,7 +124,7 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
if(call.getlValue() instanceof VariableRef) {
VariableRef lValVar = (VariableRef) call.getlValue();
List<VariableRef> preferences = new ArrayList<>();
addToEquivalenceClassSet(lValVar, preferences);
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
}
return null;
}
@ -99,41 +134,11 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
if(callFinalize.getlValue() instanceof VariableRef) {
VariableRef lValVar = (VariableRef) callFinalize.getlValue();
List<VariableRef> preferences = new ArrayList<>();
addToEquivalenceClassSet(lValVar, preferences);
addToEquivalenceClassSet(lValVar, preferences, liveRangeEquivalenceClassSet);
}
return null;
}
private void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences) {
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
LiveRangeEquivalenceClass lValEquivalenceClass =
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
if(lValEquivalenceClass == null) {
LiveRange lValLiveRange = liveRangeVariables.getLiveRange(lValVar);
// Variable in need of an equivalence class - Look through preferences
LiveRangeEquivalenceClass chosen = null;
for(VariableRef preference : preferences) {
LiveRangeEquivalenceClass preferenceEquivalenceClass = liveRangeEquivalenceClassSet.getEquivalenceClass(preference);
if(preferenceEquivalenceClass != null) {
Variable potentialVariable = getProgram().getSymbolInfos().getVariable(preference);
Variable lValVariable = getProgram().getSymbolInfos().getVariable(lValVar);
if(lValVariable.getType().equals(potentialVariable.getType())) {
if(!lValLiveRange.overlaps(preferenceEquivalenceClass.getLiveRange())) {
chosen = preferenceEquivalenceClass;
chosen.addVariable(lValVar);
break;
}
}
}
}
if(chosen == null) {
// No preference usable - create a new one
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
}
getLog().append("Added variable " + lValVar + " to live range equivalence class " + chosen);
}
}
}
}

@ -47,7 +47,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
} else if(!variable.isAnyVolatile() && !variable.isExport()) {
// Not volatile
eliminate = true;
} else if(variable.isAnyVolatile() && variable.getType() instanceof SymbolTypeStruct) {
} else if(variable.isStruct()) {
if(assignment.getOperator()==null && assignment.getrValue2() instanceof StructUnwoundPlaceholder) {
eliminate = true;
}

@ -14,6 +14,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import java.util.Collection;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -28,6 +29,8 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
@Override
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
// Examine all expressions
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
Value value = programValue.get();
if(value instanceof ConstantSymbolPointer) {
@ -36,11 +39,11 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
Symbol toSymbol = getScope().getSymbol(toSymbolRef);
if(toSymbol.getType() instanceof SymbolTypeStruct) {
RValue rewrite = rewriteStructAddressOf((VariableRef) toSymbol.getRef());
if(rewrite!=null) {
if(rewrite != null) {
programValue.set(rewrite);
getLog().append("Rewriting struct address-of to first member " + value.toString(getProgram()));
modified.set(true);
}
getLog().append("Rewriting struct address-of to first member "+value.toString(getProgram()));
modified.set(true);
}
}
});
@ -50,16 +53,16 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
if(Operators.ADDRESS_OF.equals(assignment.getOperator())) {
RValue rValue = assignment.getrValue2();
if(rValue instanceof SymbolVariableRef) {
Symbol toSymbol = getScope().getSymbol((SymbolVariableRef) rValue);
if(toSymbol.getType() instanceof SymbolTypeStruct) {
RValue rewrite = rewriteStructAddressOf((VariableRef) toSymbol.getRef());
if(rewrite!=null) {
if(rewrite != null) {
assignment.setOperator(null);
assignment.setrValue2(rewrite);
getLog().append("Rewriting struct address-of to first member "+assignment.toString(getProgram(), false));
getLog().append("Rewriting struct address-of to first member " + assignment.toString(getProgram(), false));
}
modified.set(true);
}
@ -68,6 +71,22 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
}
}
}
// Remove all StructUnwoundPlaceholder assignments for C-classic structs
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue2() instanceof StructUnwoundPlaceholder && assignment.getlValue() instanceof VariableRef)
if(getScope().getVariable((SymbolVariableRef) assignment.getlValue()).isStructClassic()) {
getLog().append("Removing C-classic struct-unwound assignment "+assignment.toString(getProgram(), false));
stmtIt.remove();
}
}
}
}
return modified.get();
}
@ -90,8 +109,11 @@ public class PassNStructAddressOfRewriting extends Pass2SsaOptimization {
if(assignment.getrValue2() instanceof StructUnwoundPlaceholder) {
// Found placeholder assignment!
StructUnwoundPlaceholder placeholder = (StructUnwoundPlaceholder) assignment.getrValue2();
SymbolRef firstMember = (SymbolRef) placeholder.getUnwoundMembers().get(0);
return new ConstantCastValue(new SymbolTypePointer(placeholder.getTypeStruct()), new ConstantSymbolPointer(firstMember));
RValue firstUnwoundMember = placeholder.getUnwoundMembers().get(0);
if(firstUnwoundMember instanceof SymbolRef) {
SymbolRef firstMember = (SymbolRef) firstUnwoundMember;
return new ConstantCastValue(new SymbolTypePointer(placeholder.getTypeStruct()), new ConstantSymbolPointer(firstMember));
}
}
}
return null;

@ -112,6 +112,31 @@ public class PassNStructPointerRewriting extends Pass2SsaOptimization {
programValue.set(new PointerDereferenceIndexed(memberAddress.getRef(), ((PointerDereferenceIndexed) struct).getIndex()));
}
modified.set(true);
} else if(struct instanceof SymbolVariableRef) {
Variable structVar = getScope().getVar((SymbolVariableRef) struct);
if(structVar.isStructClassic()) {
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
if(!(structType instanceof SymbolTypeStruct)) {
throw new CompileError("Accessing member of a non-struct ", currentStmt.getSource());
}
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
ConstantRef memberOffsetConstant = getMemberOffsetConstant(getScope(), structDefinition, structMemberRef.getMemberName());
SymbolType memberType = SymbolTypeInference.inferType(getScope(), structMemberRef);
Variable memberVar = structDefinition.getMember(structMemberRef.getMemberName());
getLog().append("Rewriting struct member access " + programValue.get().toString(getProgram()));
// Cast struct pointer to the type of the member
CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), new ConstantSymbolPointer(structVar.getRef()));
// Create temporary variable to hold pointer to member ($1)
Scope scope = getScope().getScope(currentBlock.getScope());
Variable memberAddress = scope.addVariableIntermediate();
memberAddress.setType(new SymbolTypePointer(memberType));
// Add statement $1 = ptr_struct + OFFSET_STRUCT_NAME_MEMBER
stmtIt.previous();
stmtIt.add(new StatementAssignment((LValue) memberAddress.getRef(), structTypedPointer, Operators.PLUS, memberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments()));
stmtIt.next();
// Replace struct.x with *($1)
programValue.set(new PointerDereferenceSimple(memberAddress.getRef()));
}
}
}
});

@ -1127,6 +1127,61 @@ public class TestPrograms {
assertError("struct-err-0", "Unknown struct type");
}
@Test
public void testStruct23() throws IOException, URISyntaxException {
compileAndCompare("struct-23");
}
@Test
public void testStruct22() throws IOException, URISyntaxException {
compileAndCompare("struct-22");
}
@Test
public void testStruct21() throws IOException, URISyntaxException {
compileAndCompare("struct-21");
}
@Test
public void testStruct20() throws IOException, URISyntaxException {
compileAndCompare("struct-20");
}
@Test
public void testStruct19() throws IOException, URISyntaxException {
compileAndCompare("struct-19");
}
@Test
public void testStruct18() throws IOException, URISyntaxException {
compileAndCompare("struct-18");
}
@Test
public void testStruct17() throws IOException, URISyntaxException {
compileAndCompare("struct-17");
}
@Test
public void testStruct16() throws IOException, URISyntaxException {
compileAndCompare("struct-16");
}
@Test
public void testStruct15() throws IOException, URISyntaxException {
compileAndCompare("struct-15");
}
@Test
public void testStruct14() throws IOException, URISyntaxException {
compileAndCompare("struct-14");
}
@Test
public void testStruct13() throws IOException, URISyntaxException {
compileAndCompare("struct-13");
}
@Test
public void testStruct12() throws IOException, URISyntaxException {
compileAndCompare("struct-12", log());
@ -1194,7 +1249,7 @@ public class TestPrograms {
@Test
public void testStruct0() throws IOException, URISyntaxException {
compileAndCompare("struct-0", log());
compileAndCompare("struct-0");
}
@Test

17
src/test/kc/struct-13.kc Normal file

@ -0,0 +1,17 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
struct Point {
char x;
char y;
};
__ma struct Point point;
const char* SCREEN = 0x0400;
void main() {
point.x = 2;
point.y = 3;
SCREEN[0] = point.x;
SCREEN[1] = point.y;
}

17
src/test/kc/struct-14.kc Normal file

@ -0,0 +1,17 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
struct Point {
char x;
char y;
};
struct Point[1] points;
const char* SCREEN = 0x0400;
void main() {
points[0].x = 2;
points[0].y = 3;
SCREEN[0] = points[0].x;
SCREEN[1] = points[0].y;
}

17
src/test/kc/struct-15.kc Normal file

@ -0,0 +1,17 @@
// Minimal struct with C-Standard behavior - copying
struct Point {
char x;
char y;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Point point1;
point1.x = 2;
point1.y = 3;
__ma struct Point point2 = point1;
SCREEN[0] = point2.x;
SCREEN[1] = point2.y;
}

14
src/test/kc/struct-16.kc Normal file

@ -0,0 +1,14 @@
// Minimal struct with C-Standard behavior - initializer
struct Point {
char x;
char y;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Point point1 = { 2, 3 };
SCREEN[0] = point1.x;
SCREEN[1] = point1.y;
}

25
src/test/kc/struct-17.kc Normal file

@ -0,0 +1,25 @@
// Minimal struct with C-Standard behavior - struct containing struct
struct Point {
char x;
char y;
};
struct Vector {
struct Point p;
struct Point q;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Vector v;
v.p.x = 2;
v.p.y = 3;
v.q.x = 4;
v.q.y = 5;
SCREEN[0] = v.p.x;
SCREEN[1] = v.p.y;
SCREEN[2] = v.q.x;
SCREEN[3] = v.q.y;
}

21
src/test/kc/struct-18.kc Normal file

@ -0,0 +1,21 @@
// Minimal struct with C-Standard behavior - struct containing struct with initializer
struct Point {
char x;
char y;
};
struct Vector {
struct Point p;
struct Point q;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Vector v = { {2, 3}, {4, 5} };
SCREEN[0] = v.p.x;
SCREEN[1] = v.p.y;
SCREEN[2] = v.q.x;
SCREEN[3] = v.q.y;
}

25
src/test/kc/struct-19.kc Normal file

@ -0,0 +1,25 @@
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
struct Point {
char x;
char y;
};
struct Vector {
struct Point p;
struct Point q;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Vector v;
__ma struct Point p1 = { 2, 3 };
__ma struct Point p2 = { 4, 5 };
v.p = p1;
v.q = p2;
SCREEN[0] = v.p.x;
SCREEN[1] = v.p.y;
SCREEN[2] = v.q.x;
SCREEN[3] = v.q.y;
}

23
src/test/kc/struct-20.kc Normal file

@ -0,0 +1,23 @@
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
struct Point {
char x;
char y;
};
struct Vector {
struct Point p;
struct Point q;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Point p1 = { 2, 3 };
__ma struct Point p2 = { 4, 5 };
__ma struct Vector v = { p1, p2 };
SCREEN[0] = v.p.x;
SCREEN[1] = v.p.y;
SCREEN[2] = v.q.x;
SCREEN[3] = v.q.y;
}

15
src/test/kc/struct-21.kc Normal file

@ -0,0 +1,15 @@
// Minimal struct with C-Standard behavior - address-of
struct Point {
char x;
char y;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Point point1 = { 2, 3 };
struct Point* ptr = &point1;
SCREEN[0] = ptr->x;
SCREEN[1] = ptr->y;
}

20
src/test/kc/struct-22.kc Normal file

@ -0,0 +1,20 @@
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
struct Point {
char x;
char y;
};
void main() {
__ma struct Point point1 = { 2, 3 };
__ma struct Point point2 = { 4, 5 };
print(point1);
print(point2);
}
const char* SCREEN = 0x0400;
void print(struct Point p) {
SCREEN[0] = p.x;
SCREEN[1] = p.y;
}

22
src/test/kc/struct-23.kc Normal file

@ -0,0 +1,22 @@
// Minimal struct with C-Standard behavior - call return value (not supported yet)
struct Point {
char x;
char y;
};
const char* SCREEN = 0x0400;
void main() {
__ma struct Point point1 = getPoint(2, 3);
SCREEN[0] = point1.x;
SCREEN[1] = point1.y;
__ma struct Point point2 = getPoint(4, 5);
SCREEN[2] = point2.x;
SCREEN[3] = point2.y;
}
struct Point getPoint(char x, char y) {
struct Point p = { x, y };
return p;
}

@ -121,6 +121,12 @@ Converted struct value to member variables (struct SplineVector16) rotate::vecto
Created struct value member variable (signed word) rotate::rotated_x
Created struct value member variable (signed word) rotate::rotated_y
Converted struct value to member variables (struct SplineVector16) rotate::rotated
Created struct value member variable (signed word) show_letter::segment_to_x
Created struct value member variable (signed word) show_letter::segment_to_y
Converted struct value to member variables (struct SplineVector16) show_letter::segment_to
Created struct value member variable (signed word) show_letter::segment_via_x
Created struct value member variable (signed word) show_letter::segment_via_y
Converted struct value to member variables (struct SplineVector16) show_letter::segment_via
Converted procedure struct value parameter to member unwinding (void()) spline_16seg((signed word) spline_16seg::p0_x , (signed word) spline_16seg::p0_y , (signed word) spline_16seg::p1_x , (signed word) spline_16seg::p1_y , (signed word) spline_16seg::p2_x , (signed word) spline_16seg::p2_y)
Converted procedure struct value parameter to member unwinding (void()) spline_8seg((signed word) spline_8seg::p0_x , (signed word) spline_8seg::p0_y , (signed word) spline_8seg::p1_x , (signed word) spline_8seg::p1_y , (signed word) spline_8seg::p2_x , (signed word) spline_8seg::p2_y)
Converted procedure struct value parameter to member unwinding (void()) spline_8segB((signed word) spline_8segB::p0_x , (signed word) spline_8segB::p0_y , (signed word) spline_8segB::p1_x , (signed word) spline_8segB::p1_y , (signed word) spline_8segB::p2_x , (signed word) spline_8segB::p2_y)
@ -331,12 +337,6 @@ Replacing struct member reference (struct SplineVector16) rotate::vector.x with
Replacing struct member reference (struct SplineVector16) rotate::vector.y with member unwinding reference (signed word) rotate::vector_y
Replacing struct member reference (struct SplineVector16) rotate::vector.y with member unwinding reference (signed word) rotate::vector_y
Replacing struct member reference (struct SplineVector16) rotate::vector.x with member unwinding reference (signed word) rotate::vector_x
Created struct value member variable (signed word) show_letter::segment_to_x
Created struct value member variable (signed word) show_letter::segment_to_y
Converted struct value to member variables (struct SplineVector16) show_letter::segment_to
Created struct value member variable (signed word) show_letter::segment_via_x
Created struct value member variable (signed word) show_letter::segment_via_y
Converted struct value to member variables (struct SplineVector16) show_letter::segment_via
Adding struct value member variable copy (signed word) show_letter::segment_to_x ← (signed word) show_letter::to_x
Adding struct value member variable copy (signed word) show_letter::segment_to_y ← (signed word) show_letter::to_y
Adding struct value member variable copy (signed word) show_letter::segment_via_x ← (signed word) show_letter::via_x

@ -6,19 +6,18 @@
.const OFFSET_STRUCT_FOO_THING2 = 1
__bbegin:
lda #'a'
sta bar_thing1
sta bar
lda #'b'
sta bar_thing2
sta bar+OFFSET_STRUCT_FOO_THING2
jsr main
rts
main: {
.label SCREEN = $400
.label barp = bar_thing1
.label barp = bar
lda barp
sta SCREEN
lda barp+OFFSET_STRUCT_FOO_THING2
sta SCREEN+1
rts
}
bar_thing1: .byte 0
bar_thing2: .byte 0
bar: .byte 0, 0

@ -1,6 +1,6 @@
@begin: scope:[] from
[0] (byte) bar_thing1 ← (byte) 'a'
[1] (byte) bar_thing2 ← (byte) 'b'
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
to:@1
@1: scope:[] from @begin
[2] phi()

@ -1,18 +1,18 @@
Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar
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 member variable copy (byte) bar_thing1 ← (byte) 'a'
Adding struct value member variable copy (byte) bar_thing2 ← (byte) 'b'
Adding struct value member variable copy *((byte*~) $0) ← (byte) 'a'
Adding struct value member variable copy *((byte*~) $1) ← (byte) 'b'
Rewriting struct pointer member access *((struct foo*) main::barp).thing1
Rewriting struct pointer member access *((struct foo*) main::barp).thing2
Identified constant variable (struct foo*) main::barp
Adding versioned struct unwinding for (struct foo) bar
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) bar_thing1 ← (byte) 'a'
(byte) bar_thing2 ← (byte) 'b'
(struct foo) bar ← struct-unwound {(byte) bar_thing1, (byte) bar_thing2}
(byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
*((byte*~) $0) ← (byte) 'a'
(byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
*((byte*~) $1) ← (byte) 'b'
(struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
to:@1
(void()) main()
@ -36,6 +36,8 @@ main::@return: scope:[main] from main
@end: scope:[] from @2
SYMBOL TABLE SSA
(byte*~) $0
(byte*~) $1
(label) @1
(label) @2
(label) @begin
@ -43,8 +45,6 @@ SYMBOL TABLE SSA
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(struct foo) bar loadstore
(byte) bar_thing1 loadstore
(byte) bar_thing2 loadstore
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
@ -67,20 +67,23 @@ Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Rewriting struct address-of to first member &(struct foo) bar
Successful SSA optimization PassNStructAddressOfRewriting
Constant right-side identified [4] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [7] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
Removing C-classic struct-unwound assignment [4] (struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
Constant right-side identified [6] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [9] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) $0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
Constant (const byte*) $1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
Constant (const byte) main::i#0 = 0
Constant (const byte*) main::$0 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1
Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)main::barp in
Simplifying expression containing zero main::SCREEN in [5] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
Simplifying expression containing zero (byte*)&bar in
Simplifying expression containing zero main::SCREEN in [7] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
Successful SSA optimization PassNSimplifyExpressionWithZero
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::i#2 and assignment [6] (byte) main::i#2 ← ++ (byte) main::i#1
Eliminating unused variable (byte) main::i#2 and assignment [5] (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 [3] (byte) main::i#1 ← ++ (const byte) main::i#0
@ -92,6 +95,8 @@ 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
Constant inlined main::$1 = (byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2
Constant inlined $0 = (byte*)&(struct foo) bar
Constant inlined $1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
Constant inlined main::$0 = (byte*)(const struct foo*) main::barp
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::SCREEN+++0)
@ -112,8 +117,8 @@ 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'
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
to:@1
@1: scope:[] from @begin
[2] phi()
@ -133,21 +138,17 @@ main::@return: scope:[main] from main
VARIABLE REGISTER WEIGHTS
(byte) bar_thing1 loadstore 20.0
(byte) bar_thing2 loadstore 20.0
(struct foo) bar loadstore
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
(byte) main::i
Initial phi equivalence classes
Added variable bar_thing1 to live range equivalence class [ bar_thing1 ]
Added variable bar_thing2 to live range equivalence class [ bar_thing2 ]
Added variable bar to live range equivalence class [ bar ]
Complete equivalence classes
[ bar_thing1 ]
[ bar_thing2 ]
Allocated mem[1] [ bar_thing1 ]
Allocated mem[1] [ bar_thing2 ]
[ bar ]
Allocated mem[2] [ bar ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -162,12 +163,12 @@ Target platform is c64basic / MOS6502X
.const OFFSET_STRUCT_FOO_THING2 = 1
// @begin
__bbegin:
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar_thing1
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar_thing2
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -183,7 +184,7 @@ __bend:
// main
main: {
.label SCREEN = $400
.label barp = bar_thing1
.label barp = bar
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
lda barp
sta SCREEN
@ -197,29 +198,23 @@ main: {
rts
}
// File Data
bar_thing1: .byte 0
bar_thing2: .byte 0
bar: .byte 0, 0
REGISTER UPLIFT POTENTIAL REGISTERS
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 [0] *((byte*)&(struct foo) bar) ← (byte) 'a' [ bar ] ( [ bar ] ) always clobbers reg byte a
Statement [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' [ ] ( [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:3 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers mem[1] [ bar_thing1 ] : mem[1] ,
Potential registers mem[1] [ bar_thing2 ] : mem[1] ,
Potential registers mem[2] [ bar ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [] 20: mem[1] [ bar_thing1 ] 20: mem[1] [ bar_thing2 ]
Uplift Scope [foo]
Uplift Scope [main]
Uplift Scope [] 0: mem[2] [ bar ]
Uplifting [] best 49 combination mem[1] [ bar_thing1 ] mem[1] [ bar_thing2 ]
Uplifting [foo] best 49 combination
Uplifting [main] best 49 combination
Attempting to uplift remaining variables inmem[1] [ bar_thing1 ]
Uplifting [] best 49 combination mem[1] [ bar_thing1 ]
Attempting to uplift remaining variables inmem[1] [ bar_thing2 ]
Uplifting [] best 49 combination mem[1] [ bar_thing2 ]
Uplifting [] best 49 combination mem[2] [ bar ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -233,12 +228,12 @@ ASSEMBLER BEFORE OPTIMIZATION
.const OFFSET_STRUCT_FOO_THING2 = 1
// @begin
__bbegin:
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar_thing1
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar_thing2
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -254,7 +249,7 @@ __bend:
// main
main: {
.label SCREEN = $400
.label barp = bar_thing1
.label barp = bar
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
lda barp
sta SCREEN
@ -268,8 +263,7 @@ main: {
rts
}
// File Data
bar_thing1: .byte 0
bar_thing2: .byte 0
bar: .byte 0, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
@ -291,18 +285,16 @@ FINAL SYMBOL TABLE
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(byte) bar_thing1 loadstore mem[1] 20.0
(byte) bar_thing2 loadstore mem[1] 20.0
(struct foo) bar loadstore mem[2]
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
(const struct foo*) main::barp = &(struct foo) bar
(byte) main::i
mem[1] [ bar_thing1 ]
mem[1] [ bar_thing2 ]
mem[2] [ bar ]
FINAL ASSEMBLER
@ -320,12 +312,12 @@ Score: 46
// @begin
__bbegin:
// bar = { 'a', 'b' }
// [0] (byte) bar_thing1 ← (byte) 'a' -- vbum1=vbuc1
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar_thing1
// [1] (byte) bar_thing2 ← (byte) 'b' -- vbum1=vbuc1
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar_thing2
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
// @1
// [3] call main
@ -336,7 +328,7 @@ __bbegin:
// main
main: {
.label SCREEN = $400
.label barp = bar_thing1
.label barp = bar
// SCREEN[i++] = barp->thing1
// [5] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) -- _deref_pbuc1=_deref_pbuc2
lda barp
@ -351,6 +343,5 @@ main: {
rts
}
// File Data
bar_thing1: .byte 0
bar_thing2: .byte 0
bar: .byte 0, 0

@ -2,15 +2,13 @@
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(byte) bar_thing1 loadstore mem[1] 20.0
(byte) bar_thing2 loadstore mem[1] 20.0
(struct foo) bar loadstore mem[2]
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
(const struct foo*) main::barp = &(struct foo) bar
(byte) main::i
mem[1] [ bar_thing1 ]
mem[1] [ bar_thing2 ]
mem[2] [ bar ]

@ -1,20 +1,17 @@
(const string) $0 = (string) "qwe"
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
(byte) bar_thing1 loadstore mem[1] 20.0
(byte) bar_thing2 loadstore mem[1] 20.0
(const byte*) bar_thing3 loadstore zp[2]:2 20.0
(struct foo) bar loadstore mem[14]
(byte) foo::thing1
(byte) foo::thing2
(const byte*) foo::thing3 = { fill( $c, 0) }
(const byte*) foo::thing3[(number) $c] = { fill( $c, 0) }
(void()) main()
(label) main::@1
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const struct foo*) main::barp = (struct foo*)&(byte) bar_thing1
(const struct foo*) main::barp = &(struct foo) bar
(byte) main::i
(byte) main::i#3 reg byte x 7.333333333333333
(byte) main::i#4 reg byte x 16.5
@ -24,6 +21,4 @@
reg byte y [ main::j#2 main::j#1 ]
reg byte x [ main::i#4 main::i#3 ]
mem[1] [ bar_thing1 ]
mem[1] [ bar_thing2 ]
zp[2]:2 [ bar_thing3 ]
mem[14] [ bar ]

@ -1,15 +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(main)
:BasicUpstart(__bbegin)
.pc = $80d "Program"
.const bar_thing1 = 'a'
.const bar_thing2 = 'b'
.const OFFSET_STRUCT_FOO_THING2 = 1
__bbegin:
lda #'a'
sta bar
lda #'b'
sta bar+OFFSET_STRUCT_FOO_THING2
jsr main
rts
main: {
.label SCREEN = $400
lda #bar_thing1
lda bar
sta SCREEN
lda #bar_thing2
lda bar+OFFSET_STRUCT_FOO_THING2
sta SCREEN+1
rts
}
bar: .byte 0, 0

@ -1,18 +1,19 @@
@begin: scope:[] from
[0] phi()
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
[2] phi()
[3] call main
to:@end
@end: scope:[] from @1
[3] phi()
[4] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2
[5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar)
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2)
to:main::@return
main::@return: scope:[main] from main
[6] return
[7] return
to:@return

@ -1,23 +1,26 @@
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 member variable copy (byte) bar_thing1 ← (byte) 'a'
Adding struct value member variable copy (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
Identified constant variable (byte) bar_thing1
Identified constant variable (byte) bar_thing2
Adding struct value member variable copy *((byte*~) $0) ← (byte) 'a'
Adding struct value member variable copy *((byte*~) $1) ← (byte) 'b'
Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference *((byte*~) main::$0)
Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference *((byte*~) main::$1)
Adding versioned struct unwinding for (struct foo) bar
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
*((byte*~) $0) ← (byte) 'a'
(byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
*((byte*~) $1) ← (byte) 'b'
(struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
to:@1
(void()) main()
main: scope:[main] from @1
(byte) main::i#0 ← (number) 0
*((const byte*) main::SCREEN + (byte) main::i#0) ← (const byte) bar_thing1
*((const byte*) main::SCREEN + (byte) main::i#0) ← *((byte*~) main::$0)
(byte*~) main::$0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
(byte) main::i#1 ← ++ (byte) main::i#0
*((const byte*) main::SCREEN + (byte) main::i#1) ← (const byte) bar_thing2
*((const byte*) main::SCREEN + (byte) main::i#1) ← *((byte*~) main::$1)
(byte*~) main::$1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
(byte) main::i#2 ← ++ (byte) main::i#1
to:main::@return
main::@return: scope:[main] from main
@ -31,15 +34,20 @@ main::@return: scope:[main] from main
@end: scope:[] from @2
SYMBOL TABLE SSA
(byte*~) $0
(byte*~) $1
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte) bar_thing1 = (byte) 'a'
(const byte) bar_thing2 = (byte) 'b'
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(struct foo) bar loadstore
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(byte) main::i
@ -56,13 +64,26 @@ Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct foo) bar ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
Constant right-side identified [7] (byte*~) main::$0 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [10] (byte*~) main::$1 ← (byte*)&(struct foo) bar + (const byte) OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) $0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
Constant (const byte*) $1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
Constant (const byte) main::i#0 = 0
Constant (const byte*) main::$0 = (byte*)&bar+OFFSET_STRUCT_FOO_THING1
Constant (const byte*) main::$1 = (byte*)&bar+OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← (const byte) bar_thing1
Simplifying expression containing zero (byte*)&bar in
Simplifying expression containing zero (byte*)&bar in
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1
Eliminating unused variable (byte) main::i#2 and assignment [5] (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 [1] (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
@ -70,54 +91,61 @@ 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
Constant inlined main::$1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
Constant inlined $0 = (byte*)&(struct foo) bar
Constant inlined $1 = (byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2
Constant inlined main::$0 = (byte*)&(struct foo) bar
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 @begin
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:2
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 @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
[0] *((byte*)&(struct foo) bar) ← (byte) 'a'
[1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b'
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
[2] phi()
[3] call main
to:@end
@end: scope:[] from @1
[3] phi()
[4] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1
[5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2
[5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar)
[6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2)
to:main::@return
main::@return: scope:[main] from main
[6] return
[7] return
to:@return
VARIABLE REGISTER WEIGHTS
(struct foo) bar loadstore
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
(byte) main::i
Initial phi equivalence classes
Added variable bar to live range equivalence class [ bar ]
Complete equivalence classes
[ bar ]
Allocated mem[2] [ bar ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -129,18 +157,23 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const bar_thing1 = 'a'
.const bar_thing2 = 'b'
.const OFFSET_STRUCT_FOO_THING2 = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
// [3] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
// [4] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -148,32 +181,36 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
lda #bar_thing1
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
lda bar
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
lda #bar_thing2
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
lda bar+OFFSET_STRUCT_FOO_THING2
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [7] return
rts
}
// File Data
bar: .byte 0, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [0] *((byte*)&(struct foo) bar) ← (byte) 'a' [ bar ] ( [ bar ] ) always clobbers reg byte a
Statement [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' [ bar ] ( [ bar ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) [ bar ] ( main:3 [ bar ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ bar ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [foo]
Uplift Scope [main]
Uplift Scope []
Uplift Scope [] 0: mem[2] [ bar ]
Uplifting [foo] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
Uplifting [foo] best 49 combination
Uplifting [main] best 49 combination
Uplifting [] best 49 combination mem[2] [ bar ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -184,18 +221,23 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const bar_thing1 = 'a'
.const bar_thing2 = 'b'
.const OFFSET_STRUCT_FOO_THING2 = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
// [3] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
// [4] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
@ -203,45 +245,42 @@ __bend:
// main
main: {
.label SCREEN = $400
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
lda #bar_thing1
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
lda bar
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
lda #bar_thing2
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
lda bar+OFFSET_STRUCT_FOO_THING2
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [6] return
// [7] return
rts
}
// File Data
bar: .byte 0, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
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
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) bar_thing1 = (byte) 'a'
(const byte) bar_thing2 = (byte) 'b'
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(struct foo) bar loadstore mem[2]
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
@ -249,42 +288,53 @@ FINAL SYMBOL TABLE
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::i
mem[2] [ bar ]
FINAL ASSEMBLER
Score: 18
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(main)
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const bar_thing1 = 'a'
.const bar_thing2 = 'b'
.const OFFSET_STRUCT_FOO_THING2 = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
__bbegin:
// bar = { 'a', 'b' }
// [0] *((byte*)&(struct foo) bar) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta bar
// [1] *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta bar+OFFSET_STRUCT_FOO_THING2
// [2] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// [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
// [4] *((const byte*) main::SCREEN) ← (const byte) bar_thing1 -- _deref_pbuc1=vbuc2
lda #bar_thing1
// [5] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) -- _deref_pbuc1=_deref_pbuc2
lda bar
sta SCREEN
// SCREEN[i++] = bar.thing2
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (const byte) bar_thing2 -- _deref_pbuc1=vbuc2
lda #bar_thing2
// [6] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) -- _deref_pbuc1=_deref_pbuc2
lda bar+OFFSET_STRUCT_FOO_THING2
sta SCREEN+1
// main::@return
// }
// [6] return
// [7] return
rts
}
// File Data
bar: .byte 0, 0

@ -1,8 +1,8 @@
(label) @1
(label) @begin
(label) @end
(const byte) bar_thing1 = (byte) 'a'
(const byte) bar_thing2 = (byte) 'b'
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(struct foo) bar loadstore mem[2]
(byte) foo::thing1
(byte) foo::thing2
(void()) main()
@ -10,3 +10,4 @@
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::i
mem[2] [ bar ]

@ -6,13 +6,13 @@ Converted struct value to member variables (struct Point) main::p
Created struct value member variable (struct Point) main::c_center
Created struct value member variable (byte) main::c_radius
Converted struct value to member variables (struct Circle) main::c
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable default initializer (byte) main::p_x ← (byte) 0
Adding struct value member variable default initializer (byte) main::p_y ← (byte) 0
Adding struct value member variable default initializer (struct Point) main::c_center ← {}
Adding struct value member variable default initializer (byte) main::c_radius ← (byte) 0
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable default initializer (byte) main::c_center_x ← (byte) 0
Adding struct value member variable default initializer (byte) main::c_center_y ← (byte) 0
Identified constant variable (byte) main::p_x

@ -0,0 +1,24 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
__bbegin:
lda #0
sta.z point
sta point+OFFSET_STRUCT_POINT_Y
jsr main
rts
main: {
lda #2
sta.z point
lda #3
sta point+OFFSET_STRUCT_POINT_Y
lda.z point
sta SCREEN
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}

@ -0,0 +1,21 @@
@begin: scope:[] from
[0] *((byte*)&(struct Point) point) ← (byte) 0
[1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
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] *((byte*)&(struct Point) point) ← (byte) 2
[6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point)
[8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[9] return
to:@return

366
src/test/ref/struct-13.log Normal file

@ -0,0 +1,366 @@
Adding struct value member variable default initializer *((byte*~) $0) ← (byte) 0
Adding struct value member variable default initializer *((byte*~) $1) ← (byte) 0
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*~) main::$0)
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*~) main::$1)
Replacing struct member reference (struct Point) point.x with member unwinding reference *((byte*~) main::$2)
Replacing struct member reference (struct Point) point.y with member unwinding reference *((byte*~) main::$3)
Adding versioned struct unwinding for (struct Point) point
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*~) $0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) $0) ← (byte) 0
(byte*~) $1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) $1) ← (byte) 0
(struct Point) point ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
to:@1
(void()) main()
main: scope:[main] from @1
*((byte*~) main::$0) ← (number) 2
(byte*~) main::$0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$1) ← (number) 3
(byte*~) main::$1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
(byte*~) main::$2 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
(byte*~) main::$3 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
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
(byte*~) $0
(byte*~) $1
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(label) main::@return
(struct Point) point loadstore
Adding number conversion cast (unumber) 2 in *((byte*~) main::$0) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*~) main::$1) ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*~) main::$0) ← (unumber)(number) 2
Inlining cast *((byte*~) main::$1) ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) point ← struct-unwound {*((byte*~) $0), *((byte*~) $1)}
Constant right-side identified [0] (byte*~) $0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) $1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [6] (byte*~) main::$0 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [8] (byte*~) main::$1 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [10] (byte*~) main::$2 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [12] (byte*~) main::$3 ← (byte*)&(struct Point) point + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) $0 = (byte*)&point+OFFSET_STRUCT_POINT_X
Constant (const byte*) $1 = (byte*)&point+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$0 = (byte*)&point+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&point+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)&point+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&point+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&point in
Simplifying expression containing zero (byte*)&point in
Simplifying expression containing zero (byte*)&point in
Simplifying expression containing zero SCREEN in [9] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)&(struct Point) point
Constant inlined main::$0 = (byte*)&(struct Point) point
Constant inlined main::$3 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined $0 = (byte*)&(struct Point) point
Constant inlined $1 = (byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
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*)&(struct Point) point) ← (byte) 0
[1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
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] *((byte*)&(struct Point) point) ← (byte) 2
[6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point)
[8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[9] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) point loadstore
Initial phi equivalence classes
Added variable point to live range equivalence class [ point ]
Complete equivalence classes
[ point ]
Allocated zp[2]:2 [ point ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
// @begin
__bbegin:
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta point+OFFSET_STRUCT_POINT_Y
// [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: {
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
sta SCREEN
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [9] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *((byte*)&(struct Point) point) ← (byte) 0 [ point ] ( [ point ] ) always clobbers reg byte a
Statement [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ point ] ( [ point ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) point) ← (byte) 2 [ point ] ( main:3 [ point ] ) always clobbers reg byte a
Statement [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ point ] ( main:3 [ point ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) [ point ] ( main:3 [ point ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ point ] : zp[2]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope [] 0: zp[2]:2 [ point ]
Uplifting [Point] best 58 combination
Uplifting [main] best 58 combination
Uplifting [] best 58 combination zp[2]:2 [ point ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
// @begin
__bbegin:
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta point+OFFSET_STRUCT_POINT_Y
// [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: {
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
sta SCREEN
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [9] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
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
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) point loadstore zp[2]:2
zp[2]:2 [ point ]
FINAL ASSEMBLER
Score: 53
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.label point = 2
// @begin
__bbegin:
// point
// [0] *((byte*)&(struct Point) point) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point
// [1] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta point+OFFSET_STRUCT_POINT_Y
// [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: {
// point.x = 2
// [5] *((byte*)&(struct Point) point) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point
// point.y = 3
// [6] *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point.x
// [7] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point) -- _deref_pbuc1=_deref_pbuc2
lda.z point
sta SCREEN
// SCREEN[1] = point.y
// [8] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [9] return
rts
}
// File Data

@ -0,0 +1,12 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) point loadstore zp[2]:2
zp[2]:2 [ point ]

@ -0,0 +1,18 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
lda #2
sta points
lda #3
sta points+OFFSET_STRUCT_POINT_Y
lda points
sta SCREEN
lda points+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}
points: .fill 2*1, 0

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(const struct Point*) points) ← (byte) 2
[5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return

377
src/test/ref/struct-14.log Normal file

@ -0,0 +1,377 @@
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
Fixing pointer array-indexing *((const struct Point*) points + (number) 0)
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$0).x
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$1).y
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$2).x
Rewriting struct pointer member access *((const struct Point*) points + (number~) main::$3).y
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
(byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$4 + (number~) main::$0) ← (number) 2
(number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
(byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$5 + (number~) main::$1) ← (number) 3
(number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
(byte*~) main::$6 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6 + (number~) main::$2)
(number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
(byte*~) main::$7 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7 + (number~) main::$3)
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(void()) main()
(number~) main::$0
(number~) main::$1
(number~) main::$2
(number~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(byte*~) main::$6
(byte*~) main::$7
(label) main::@return
(const struct Point*) points[(number) 1] = { fill( 1, 0) }
Adding number conversion cast (unumber) 0 in (number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 2 in *((byte*~) main::$4 + (unumber~) main::$0) ← (number) 2
Adding number conversion cast (unumber) 0 in (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 3 in *((byte*~) main::$5 + (unumber~) main::$1) ← (number) 3
Adding number conversion cast (unumber) 0 in (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$2 in (number~) main::$2 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6 + (unumber~) main::$2)
Adding number conversion cast (unumber) 0 in (number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$3 in (number~) main::$3 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7 + (unumber~) main::$3)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*~) main::$4 + (unumber~) main::$0) ← (unumber)(number) 2
Inlining cast *((byte*~) main::$5 + (unumber~) main::$1) ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 2
Simplifying constant integer cast 0
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Inferred type updated to byte in (unumber~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Inferred type updated to byte in (unumber~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Constant right-side identified [0] (byte~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Constant right-side identified [1] (byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Constant right-side identified [4] (byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [6] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Constant right-side identified [7] (byte*~) main::$6 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [9] (byte~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_POINT
Constant right-side identified [10] (byte*~) main::$7 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::$0 = 0*SIZEOF_STRUCT_POINT
Constant (const byte*) main::$4 = (byte*)points+OFFSET_STRUCT_POINT_X
Constant (const byte) main::$1 = 0*SIZEOF_STRUCT_POINT
Constant (const byte*) main::$5 = (byte*)points+OFFSET_STRUCT_POINT_Y
Constant (const byte) main::$2 = 0*SIZEOF_STRUCT_POINT
Constant (const byte*) main::$6 = (byte*)points+OFFSET_STRUCT_POINT_X
Constant (const byte) main::$3 = 0*SIZEOF_STRUCT_POINT
Constant (const byte*) main::$7 = (byte*)points+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_POINT in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero (byte*)points in
Simplifying expression containing zero (byte*)points in
Simplifying expression containing zero main::$4 in [2] *((const byte*) main::$4 + (const byte) main::$0) ← (byte) 2
Simplifying expression containing zero main::$5 in [5] *((const byte*) main::$5 + (const byte) main::$1) ← (byte) 3
Simplifying expression containing zero main::$6 in [8] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6 + (const byte) main::$2)
Simplifying expression containing zero SCREEN in [8] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6)
Simplifying expression containing zero main::$7 in [11] *((const byte*) SCREEN + (byte) 1) ← *((const byte*) main::$7 + (const byte) main::$3)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) main::$0
Eliminating unused constant (const byte) main::$1
Eliminating unused constant (const byte) main::$2
Eliminating unused constant (const byte) main::$3
Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$5 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$6 = (byte*)(const struct Point*) points
Constant inlined main::$4 = (byte*)(const struct Point*) points
Constant inlined main::$7 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(const struct Point*) points) ← (byte) 2
[5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta points
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta points+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
lda points
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda points+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
points: .fill 2*1, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)(const struct Point*) points) ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplifting [Point] best 49 combination
Uplifting [main] best 49 combination
Uplifting [] best 49 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta points
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta points+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
lda points
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda points+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
points: .fill 2*1, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(const struct Point*) points[(number) 1] = { fill( 1, 0) }
FINAL ASSEMBLER
Score: 34
// File Comments
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
// points[0].x = 2
// [4] *((byte*)(const struct Point*) points) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta points
// points[0].y = 3
// [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta points+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = points[0].x
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2
lda points
sta SCREEN
// SCREEN[1] = points[0].y
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda points+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [8] return
rts
}
// File Data
points: .fill 2*1, 0

@ -0,0 +1,11 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(const struct Point*) points[(number) 1] = { fill( 1, 0) }

@ -0,0 +1,26 @@
// Minimal struct with C-Standard behavior - copying
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label point1 = 2
.label point2 = 4
lda #0
sta.z point1
sta point1+OFFSET_STRUCT_POINT_Y
lda #2
sta.z point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
lda.z point1
sta.z point2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2+OFFSET_STRUCT_POINT_Y
lda.z point2
sta SCREEN
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}

@ -0,0 +1,24 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 0
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)&(struct Point) main::point1) ← (byte) 2
[7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1)
[9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2)
[11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[12] return
to:@return

433
src/test/ref/struct-15.log Normal file

@ -0,0 +1,433 @@
Adding struct value member variable default initializer *((byte*~) main::$0) ← (byte) 0
Adding struct value member variable default initializer *((byte*~) main::$1) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$2) ← *((byte*~) main::$3)
Adding struct value member variable copy *((byte*~) main::$4) ← *((byte*~) main::$5)
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$6)
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$7)
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*~) main::$8)
Replacing struct member reference (struct Point) main::point2.y with member unwinding reference *((byte*~) main::$9)
Adding versioned struct unwinding for (struct Point) main::point1
Adding versioned struct unwinding for (struct Point) main::point2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$0) ← (byte) 0
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$1) ← (byte) 0
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
*((byte*~) main::$6) ← (number) 2
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$7) ← (number) 3
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$2 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$2) ← *((byte*~) main::$3)
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$5 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$4) ← *((byte*~) main::$5)
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$4)}
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$8)
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$9)
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(byte*~) main::$6
(byte*~) main::$7
(byte*~) main::$8
(byte*~) main::$9
(label) main::@return
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
Adding number conversion cast (unumber) 2 in *((byte*~) main::$6) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*~) main::$7) ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$8)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$9)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*~) main::$6) ← (unumber)(number) 2
Inlining cast *((byte*~) main::$7) ← (unumber)(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
Removing C-classic struct-unwound assignment [15] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$4)}
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [6] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [8] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [9] (byte*~) main::$2 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [10] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [12] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [13] (byte*~) main::$5 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [17] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [19] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$5 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero SCREEN in [16] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$8)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)&(struct Point) main::point2
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
Constant inlined main::$5 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
Constant inlined main::$3 = (byte*)&(struct Point) main::point1
Constant inlined main::$4 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 0
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)&(struct Point) main::point1) ← (byte) 2
[7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1)
[9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2)
[11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[12] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
Initial phi equivalence classes
Added variable main::point1 to live range equivalence class [ main::point1 ]
Added variable main::point2 to live range equivalence class [ main::point2 ]
Complete equivalence classes
[ main::point1 ]
[ main::point2 ]
Allocated zp[2]:2 [ main::point1 ]
Allocated zp[2]:4 [ main::point2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - copying
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
.label point2 = 4
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta.z point2
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2+OFFSET_STRUCT_POINT_Y
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
lda.z point2
sta SCREEN
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [12] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
Statement [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
Statement [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ main::point2 ] : zp[2]:4 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ] 0: zp[2]:4 [ main::point2 ]
Uplift Scope []
Uplifting [Point] best 72 combination
Uplifting [main] best 72 combination zp[2]:2 [ main::point1 ] zp[2]:4 [ main::point2 ]
Uplifting [] best 72 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - copying
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
.label point2 = 4
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta.z point2
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2+OFFSET_STRUCT_POINT_Y
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
lda.z point2
sta SCREEN
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [12] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]
FINAL ASSEMBLER
Score: 55
// File Comments
// Minimal struct with C-Standard behavior - copying
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label point1 = 2
.label point2 = 4
// point1
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta point1+OFFSET_STRUCT_POINT_Y
// point1.x = 2
// [6] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// point1.y = 3
// [7] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// point2 = point1
// [8] *((byte*)&(struct Point) main::point2) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta.z point2
// [9] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta point2+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point2.x
// [10] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
lda.z point2
sta SCREEN
// SCREEN[1] = point2.y
// [11] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [12] return
rts
}
// File Data

@ -0,0 +1,14 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]

@ -0,0 +1,18 @@
// Minimal struct with C-Standard behavior - initializer
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label point1 = 2
lda #2
sta.z point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
lda.z point1
sta SCREEN
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return

323
src/test/ref/struct-16.log Normal file

@ -0,0 +1,323 @@
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$2)
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$3)
Adding versioned struct unwinding for (struct Point) main::point1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$0) ← (byte)(number) 2
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$1) ← (byte)(number) 3
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(label) main::@return
(struct Point) main::point1 loadstore
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [6] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [8] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero SCREEN in [5] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) main::point1 loadstore
Initial phi equivalence classes
Added variable main::point1 to live range equivalence class [ main::point1 ]
Complete equivalence classes
[ main::point1 ]
Allocated zp[2]:2 [ main::point1 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ]
Uplift Scope []
Uplifting [Point] best 47 combination
Uplifting [main] best 47 combination zp[2]:2 [ main::point1 ]
Uplifting [] best 47 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
zp[2]:2 [ main::point1 ]
FINAL ASSEMBLER
Score: 32
// File Comments
// Minimal struct with C-Standard behavior - initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label point1 = 2
// point1 = { 2, 3 }
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point1.x
// [6] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta SCREEN
// SCREEN[1] = point1.y
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [8] return
rts
}
// File Data

@ -0,0 +1,12 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
zp[2]:2 [ main::point1 ]

@ -0,0 +1,32 @@
// Minimal struct with C-Standard behavior - struct containing struct
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label v = 2
lda #0
sta.z v
sta v+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda #2
sta.z v
lda #3
sta v+OFFSET_STRUCT_POINT_Y
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda.z v
sta SCREEN
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}

@ -0,0 +1,28 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return

595
src/test/ref/struct-17.log Normal file

@ -0,0 +1,595 @@
Adding struct value member variable default initializer *((struct Point*~) main::$0) ← {}
Adding struct value member variable default initializer *((struct Point*~) main::$1) ← {}
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$2)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$3)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$4)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$5)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$7)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$8)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$9)
Adding struct value member variable copy *((byte*~) main::$10) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$11) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$12) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$13) ← (byte) 0
Rewriting struct pointer member access *((struct Point*~) main::$2).x
Rewriting struct pointer member access *((struct Point*~) main::$3).y
Rewriting struct pointer member access *((struct Point*~) main::$4).x
Rewriting struct pointer member access *((struct Point*~) main::$5).y
Rewriting struct pointer member access *((struct Point*~) main::$6).x
Rewriting struct pointer member access *((struct Point*~) main::$7).y
Rewriting struct pointer member access *((struct Point*~) main::$8).x
Rewriting struct pointer member access *((struct Point*~) main::$9).y
Adding versioned struct unwinding for (struct Vector) main::v
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$10) ← (byte) 0
(byte*~) main::$11 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$11) ← (byte) 0
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$12) ← (byte) 0
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$13) ← (byte) 0
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$14) ← (number) 2
(struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$15 ← (byte*)(struct Point*~) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$15) ← (number) 3
(struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$16) ← (number) 4
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$17 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$17) ← (number) 5
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$19 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$21 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Point*~) main::$0
(struct Point*~) main::$1
(byte*~) main::$10
(byte*~) main::$11
(byte*~) main::$12
(byte*~) main::$13
(byte*~) main::$14
(byte*~) main::$15
(byte*~) main::$16
(byte*~) main::$17
(byte*~) main::$18
(byte*~) main::$19
(struct Point*~) main::$2
(byte*~) main::$20
(byte*~) main::$21
(struct Point*~) main::$3
(struct Point*~) main::$4
(struct Point*~) main::$5
(struct Point*~) main::$6
(struct Point*~) main::$7
(struct Point*~) main::$8
(struct Point*~) main::$9
(label) main::@return
(struct Vector) main::v loadstore
Adding number conversion cast (unumber) 2 in *((byte*~) main::$14) ← (number) 2
Adding number conversion cast (unumber) 3 in *((byte*~) main::$15) ← (number) 3
Adding number conversion cast (unumber) 4 in *((byte*~) main::$16) ← (number) 4
Adding number conversion cast (unumber) 5 in *((byte*~) main::$17) ← (number) 5
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*~) main::$14) ← (unumber)(number) 2
Inlining cast *((byte*~) main::$15) ← (unumber)(number) 3
Inlining cast *((byte*~) main::$16) ← (unumber)(number) 4
Inlining cast *((byte*~) main::$17) ← (unumber)(number) 5
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 4
Finalized unsigned number type (byte) 5
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [13] (struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [16] (struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [19] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [22] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [25] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [28] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [31] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [34] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$2 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$3 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$2 in [11] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$3 in [14] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$4 in [17] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$5 in [20] (byte*~) main::$17 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$6 in [23] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$7 in [26] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$8 in [29] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$9 in [32] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$10) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$11) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$12) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$13) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [12] *((byte*~) main::$14) ← (byte) 2 -- *((byte*)main::$2 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [15] *((byte*~) main::$15) ← (byte) 3 -- *((byte*)main::$3 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [18] *((byte*~) main::$16) ← (byte) 4 -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [21] *((byte*~) main::$17) ← (byte) 5 -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$18) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [27] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$19) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [30] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$20) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [33] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$21) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
Simplifying expression containing zero (byte*)main::$2 in [11] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$2 in [12] *((byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)main::$4 in [17] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$4 in [18] *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero (byte*)main::$6 in [23] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$6 in [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [24] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6)
Simplifying expression containing zero (byte*)main::$8 in [29] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$8 in [30] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*~) main::$10 and assignment [0] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$0
Eliminating unused variable (byte*~) main::$11 and assignment [2] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$12 and assignment [4] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$1
Eliminating unused variable (byte*~) main::$13 and assignment [6] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$14 and assignment [8] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$2
Eliminating unused variable (byte*~) main::$15 and assignment [10] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$16 and assignment [12] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$4
Eliminating unused variable (byte*~) main::$17 and assignment [14] (byte*~) main::$17 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$18 and assignment [16] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6
Eliminating unused variable (byte*~) main::$19 and assignment [18] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$20 and assignment [20] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8
Eliminating unused variable (byte*~) main::$21 and assignment [22] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$2 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$3 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *(SCREEN+2)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Vector) main::v loadstore
Initial phi equivalence classes
Added variable main::v to live range equivalence class [ main::v ]
Complete equivalence classes
[ main::v ]
Allocated zp[4]:2 [ main::v ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [Vector]
Uplift Scope [main] 0: zp[4]:2 [ main::v ]
Uplift Scope []
Uplifting [Point] best 98 combination
Uplifting [Vector] best 98 combination
Uplifting [main] best 98 combination zp[4]:2 [ main::v ]
Uplifting [] best 98 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #0
Removing instruction lda #0
Removing instruction lda #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]
FINAL ASSEMBLER
Score: 77
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label v = 2
// v
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// v.p.x = 2
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// v.p.y = 3
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// v.q.x = 4
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// v.q.y = 5
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = v.p.x
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// SCREEN[1] = v.p.y
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// SCREEN[2] = v.q.x
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// SCREEN[3] = v.q.y
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [16] return
rts
}
// File Data

@ -0,0 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]

@ -0,0 +1,27 @@
// Minimal struct with C-Standard behavior - struct containing struct with initializer
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label v = 2
lda #2
sta.z v
lda #3
sta v+OFFSET_STRUCT_POINT_Y
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda.z v
sta SCREEN
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}

@ -0,0 +1,24 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[12] return
to:@return

473
src/test/ref/struct-18.log Normal file

@ -0,0 +1,473 @@
Adding struct value member variable copy *((struct Point*~) main::$0) ← { x: (byte)(number) 2, y: (byte)(number) 3 }
Adding struct value member variable copy *((struct Point*~) main::$1) ← { x: (byte)(number) 4, y: (byte)(number) 5 }
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$2)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$3)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$4)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$5)
Adding struct value member variable copy *((byte*~) main::$6) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$7) ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$8) ← (byte)(number) 4
Adding struct value member variable copy *((byte*~) main::$9) ← (byte)(number) 5
Rewriting struct pointer member access *((struct Point*~) main::$2).x
Rewriting struct pointer member access *((struct Point*~) main::$3).y
Rewriting struct pointer member access *((struct Point*~) main::$4).x
Rewriting struct pointer member access *((struct Point*~) main::$5).y
Adding versioned struct unwinding for (struct Vector) main::v
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$6 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$6) ← (byte)(number) 2
(byte*~) main::$7 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$7) ← (byte)(number) 3
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$8 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$8) ← (byte)(number) 4
(byte*~) main::$9 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$9) ← (byte)(number) 5
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$10)
(struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$11 ← (byte*)(struct Point*~) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$11)
(struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$12)
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$13)
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Point*~) main::$0
(struct Point*~) main::$1
(byte*~) main::$10
(byte*~) main::$11
(byte*~) main::$12
(byte*~) main::$13
(struct Point*~) main::$2
(struct Point*~) main::$3
(struct Point*~) main::$4
(struct Point*~) main::$5
(byte*~) main::$6
(byte*~) main::$7
(byte*~) main::$8
(byte*~) main::$9
(label) main::@return
(struct Vector) main::v loadstore
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$10)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$11)
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$12)
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$13)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [13] (struct Point*~) main::$2 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [16] (struct Point*~) main::$3 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [19] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [22] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$2 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$3 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$7 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$9 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$2 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$3 in [14] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$4 in [17] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$5 in [20] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$6) ← (byte) 2 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$7) ← (byte) 3 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$8) ← (byte) 4 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$9) ← (byte) 5 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$10) -- *((byte*)main::$2 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [15] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$11) -- *((byte*)main::$3 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [18] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$12) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [21] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$13) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 2
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero (byte*)main::$2 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$2 in [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [12] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$2)
Simplifying expression containing zero (byte*)main::$4 in [17] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$4 in [18] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*~) main::$6 and assignment [0] (byte*~) main::$6 ← (byte*)(const struct Point*) main::$0
Eliminating unused variable (byte*~) main::$7 and assignment [2] (byte*~) main::$7 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$8 and assignment [4] (byte*~) main::$8 ← (byte*)(const struct Point*) main::$1
Eliminating unused variable (byte*~) main::$9 and assignment [6] (byte*~) main::$9 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$10 and assignment [8] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$2
Eliminating unused variable (byte*~) main::$11 and assignment [10] (byte*~) main::$11 ← (byte*)(const struct Point*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$12 and assignment [12] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4
Eliminating unused variable (byte*~) main::$13 and assignment [14] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$2 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$3 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *(SCREEN+2)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[12] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Vector) main::v loadstore
Initial phi equivalence classes
Added variable main::v to live range equivalence class [ main::v ]
Complete equivalence classes
[ main::v ]
Allocated zp[4]:2 [ main::v ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [12] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [Vector]
Uplift Scope [main] 0: zp[4]:2 [ main::v ]
Uplift Scope []
Uplifting [Point] best 75 combination
Uplifting [Vector] best 75 combination
Uplifting [main] best 75 combination zp[4]:2 [ main::v ]
Uplifting [] best 75 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [12] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]
FINAL ASSEMBLER
Score: 60
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label v = 2
// v = { {2, 3}, {4, 5} }
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = v.p.x
// [8] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// SCREEN[1] = v.p.y
// [9] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// SCREEN[2] = v.q.x
// [10] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// SCREEN[3] = v.q.y
// [11] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [12] return
rts
}
// File Data

@ -0,0 +1,15 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]

@ -0,0 +1,42 @@
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label v = 2
.label p1 = 6
.label p2 = 8
lda #0
sta.z v
sta v+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda #2
sta.z p1
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
lda #4
sta.z p2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
lda.z p1
sta.z v
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda.z v
sta SCREEN
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}

@ -0,0 +1,32 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[8] *((byte*)&(struct Point) main::p1) ← (byte) 2
[9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[10] *((byte*)&(struct Point) main::p2) ← (byte) 4
[11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
[13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
[15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
[16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[20] return
to:@return

693
src/test/ref/struct-19.log Normal file

@ -0,0 +1,693 @@
Adding struct value member variable default initializer *((struct Point*~) main::$0) ← {}
Adding struct value member variable default initializer *((struct Point*~) main::$1) ← {}
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$4) ← (byte)(number) 4
Adding struct value member variable copy *((byte*~) main::$5) ← (byte)(number) 5
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$7)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$8)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$9)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$10)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$11)
Adding struct value member variable copy *((byte*~) main::$12) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$13) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$14) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$15) ← (byte) 0
Adding struct value member variable copy *((byte*~) main::$16) ← *((byte*~) main::$17)
Adding struct value member variable copy *((byte*~) main::$18) ← *((byte*~) main::$19)
Adding struct value member variable copy *((byte*~) main::$20) ← *((byte*~) main::$21)
Adding struct value member variable copy *((byte*~) main::$22) ← *((byte*~) main::$23)
Rewriting struct pointer member access *((struct Point*~) main::$8).x
Rewriting struct pointer member access *((struct Point*~) main::$9).y
Rewriting struct pointer member access *((struct Point*~) main::$10).x
Rewriting struct pointer member access *((struct Point*~) main::$11).y
Adding versioned struct unwinding for (struct Vector) main::v
Adding versioned struct unwinding for (struct Point) main::p1
Adding versioned struct unwinding for (struct Point) main::p2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$12) ← (byte) 0
(byte*~) main::$13 ← (byte*)(struct Point*~) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$13) ← (byte) 0
(struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$14) ← (byte) 0
(byte*~) main::$15 ← (byte*)(struct Point*~) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$15) ← (byte) 0
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
(byte*~) main::$2 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$2) ← (byte)(number) 2
(byte*~) main::$3 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$3) ← (byte)(number) 3
(struct Point) main::p1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
(byte*~) main::$4 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$4) ← (byte)(number) 4
(byte*~) main::$5 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$5) ← (byte)(number) 5
(struct Point) main::p2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$17 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$16) ← *((byte*~) main::$17)
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$19 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$18) ← *((byte*~) main::$19)
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$21 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$20) ← *((byte*~) main::$21)
(byte*~) main::$22 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$23 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$22) ← *((byte*~) main::$23)
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$24 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$24)
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$25 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$25)
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$26 ← (byte*)(struct Point*~) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$26)
(struct Point*~) main::$10 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$27 ← (byte*)(struct Point*~) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$27)
(struct Point*~) main::$11 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Point*~) main::$0
(struct Point*~) main::$1
(struct Point*~) main::$10
(struct Point*~) main::$11
(byte*~) main::$12
(byte*~) main::$13
(byte*~) main::$14
(byte*~) main::$15
(byte*~) main::$16
(byte*~) main::$17
(byte*~) main::$18
(byte*~) main::$19
(byte*~) main::$2
(byte*~) main::$20
(byte*~) main::$21
(byte*~) main::$22
(byte*~) main::$23
(byte*~) main::$24
(byte*~) main::$25
(byte*~) main::$26
(byte*~) main::$27
(byte*~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(struct Point*~) main::$6
(struct Point*~) main::$7
(struct Point*~) main::$8
(struct Point*~) main::$9
(label) main::@return
(struct Point) main::p1 loadstore
(struct Point) main::p2 loadstore
(struct Vector) main::v loadstore
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$24)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$25)
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$26)
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$27)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [10] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$0), *((struct Point*~) main::$1)}
Removing C-classic struct-unwound assignment [15] (struct Point) main::p1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
Removing C-classic struct-unwound assignment [20] (struct Point) main::p2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
Constant right-side identified [0] (struct Point*~) main::$0 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [5] (struct Point*~) main::$1 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [11] (byte*~) main::$2 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [13] (byte*~) main::$3 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [16] (byte*~) main::$4 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [18] (byte*~) main::$5 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [22] (byte*~) main::$17 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [25] (byte*~) main::$19 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [27] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [29] (byte*~) main::$21 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [32] (byte*~) main::$23 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [34] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [37] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [40] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [43] (struct Point*~) main::$10 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [46] (struct Point*~) main::$11 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const struct Point*) main::$0 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$1 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const byte*) main::$2 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$4 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$5 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$17 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$19 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const byte*) main::$21 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$23 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$10 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$11 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)main::$0 in [1] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$0 in [3] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$1 in [6] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$1 in [8] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$6 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$6 in [24] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$7 in [28] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$7 in [31] (byte*~) main::$22 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$8 in [35] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$9 in [38] (byte*~) main::$25 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$10 in [41] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$11 in [44] (byte*~) main::$27 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [2] *((byte*~) main::$12) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$13) ← (byte) 0 -- *((byte*)main::$0 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [7] *((byte*~) main::$14) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [9] *((byte*~) main::$15) ← (byte) 0 -- *((byte*)main::$1 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [23] *((byte*~) main::$16) ← *((const byte*) main::$17) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [26] *((byte*~) main::$18) ← *((const byte*) main::$19) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [30] *((byte*~) main::$20) ← *((const byte*) main::$21) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [33] *((byte*~) main::$22) ← *((const byte*) main::$23) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$24) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [39] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$25) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [42] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$26) -- *((byte*)main::$10 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [45] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$27) -- *((byte*)main::$11 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)&main::p1 in
Simplifying expression containing zero (byte*)&main::p2 in
Simplifying expression containing zero (byte*)&main::p1 in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)&main::p2 in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)main::$0 in [1] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$0 in [2] *((byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
Simplifying expression containing zero (byte*)main::$1 in [6] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$1 in [7] *((byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 0
Simplifying expression containing zero (byte*)main::$6 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$6 in [23] *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$17)
Simplifying expression containing zero (byte*)main::$7 in [28] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$7 in [30] *((byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$21)
Simplifying expression containing zero (byte*)main::$8 in [35] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$8 in [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [36] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$8)
Simplifying expression containing zero (byte*)main::$10 in [41] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$10 in [42] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*~) main::$12 and assignment [0] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$0
Eliminating unused variable (byte*~) main::$13 and assignment [2] (byte*~) main::$13 ← (byte*)(const struct Point*) main::$0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$14 and assignment [4] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$1
Eliminating unused variable (byte*~) main::$15 and assignment [6] (byte*~) main::$15 ← (byte*)(const struct Point*) main::$1 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$16 and assignment [12] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$6
Eliminating unused variable (byte*~) main::$18 and assignment [14] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$20 and assignment [16] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$7
Eliminating unused variable (byte*~) main::$22 and assignment [18] (byte*~) main::$22 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$24 and assignment [20] (byte*~) main::$24 ← (byte*)(const struct Point*) main::$8
Eliminating unused variable (byte*~) main::$25 and assignment [22] (byte*~) main::$25 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$26 and assignment [24] (byte*~) main::$26 ← (byte*)(const struct Point*) main::$10
Eliminating unused variable (byte*~) main::$27 and assignment [26] (byte*~) main::$27 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$23 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$21 = (byte*)&(struct Point) main::p2
Constant inlined main::$10 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$11 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$1 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$2 = (byte*)&(struct Point) main::p1
Constant inlined main::$17 = (byte*)&(struct Point) main::p1
Constant inlined main::$0 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$19 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$5 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$3 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$4 = (byte*)&(struct Point) main::p2
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *(SCREEN+2)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0
[5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0
[7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0
[8] *((byte*)&(struct Point) main::p1) ← (byte) 2
[9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[10] *((byte*)&(struct Point) main::p2) ← (byte) 4
[11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
[13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
[15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
[16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[20] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Point) main::p1 loadstore
(struct Point) main::p2 loadstore
(struct Vector) main::v loadstore
Initial phi equivalence classes
Added variable main::v to live range equivalence class [ main::v ]
Added variable main::p1 to live range equivalence class [ main::p1 ]
Added variable main::p2 to live range equivalence class [ main::p2 ]
Complete equivalence classes
[ main::v ]
[ main::p1 ]
[ main::p2 ]
Allocated zp[4]:2 [ main::v ]
Allocated zp[2]:6 [ main::p1 ]
Allocated zp[2]:8 [ main::p2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
.label p1 = 6
.label p2 = 8
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [20] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) [ main::v main::p1 main::p2 ] ( main:2 [ main::v main::p1 main::p2 ] ) always clobbers reg byte a
Statement [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v main::p2 ] ( main:2 [ main::v main::p2 ] ) always clobbers reg byte a
Statement [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) [ main::v main::p2 ] ( main:2 [ main::v main::p2 ] ) always clobbers reg byte a
Statement [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[4]:2 [ main::v ] : zp[4]:2 ,
Potential registers zp[2]:6 [ main::p1 ] : zp[2]:6 ,
Potential registers zp[2]:8 [ main::p2 ] : zp[2]:8 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [Vector]
Uplift Scope [main] 0: zp[4]:2 [ main::v ] 0: zp[2]:6 [ main::p1 ] 0: zp[2]:8 [ main::p2 ]
Uplift Scope []
Uplifting [Point] best 126 combination
Uplifting [Vector] best 126 combination
Uplifting [main] best 126 combination zp[4]:2 [ main::v ] zp[2]:6 [ main::p1 ] zp[2]:8 [ main::p2 ]
Uplifting [] best 126 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label v = 2
.label p1 = 6
.label p2 = 8
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [20] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #0
Removing instruction lda #0
Removing instruction lda #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Point) main::p1 loadstore zp[2]:6
(struct Point) main::p2 loadstore zp[2]:8
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]
zp[2]:6 [ main::p1 ]
zp[2]:8 [ main::p2 ]
FINAL ASSEMBLER
Score: 105
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with assignment of sub-struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_VECTOR_Q = 2
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label v = 2
.label p1 = 6
.label p2 = 8
// v
// [4] *((byte*)(struct Point*)&(struct Vector) main::v) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta.z v
// [5] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_VECTOR_Q
// [7] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 0 -- _deref_pbuc1=vbuc2
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// p1 = { 2, 3 }
// [8] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [9] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// p2 = { 4, 5 }
// [10] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [11] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// v.p = p1
// [12] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [13] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// v.q = p2
// [14] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [15] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = v.p.x
// [16] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// SCREEN[1] = v.p.y
// [17] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// SCREEN[2] = v.q.x
// [18] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// SCREEN[3] = v.q.y
// [19] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [20] return
rts
}
// File Data

@ -0,0 +1,19 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Point) main::p1 loadstore zp[2]:6
(struct Point) main::p2 loadstore zp[2]:8
(struct Vector) main::v loadstore zp[4]:2
zp[4]:2 [ main::v ]
zp[2]:6 [ main::p1 ]
zp[2]:8 [ main::p2 ]

@ -0,0 +1,37 @@
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const OFFSET_STRUCT_VECTOR_Q = 2
main: {
.label p1 = 2
.label p2 = 4
.label v = 6
lda #2
sta.z p1
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
lda #4
sta.z p2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
lda.z p1
sta.z v
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
lda.z v
sta SCREEN
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}

@ -0,0 +1,28 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::p1) ← (byte) 2
[5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) main::p2) ← (byte) 4
[7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return

599
src/test/ref/struct-20.log Normal file

@ -0,0 +1,599 @@
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 4
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 5
Adding struct value list initializer *((struct Point*~) main::$4) ← (struct Point) main::p1
Adding struct value list initializer *((struct Point*~) main::$5) ← (struct Point) main::p2
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$6)
Replacing struct member reference (struct Vector) main::v.p with member unwinding reference *((struct Point*~) main::$7)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$8)
Replacing struct member reference (struct Vector) main::v.q with member unwinding reference *((struct Point*~) main::$9)
Adding struct value member variable copy *((byte*~) main::$10) ← *((byte*~) main::$11)
Adding struct value member variable copy *((byte*~) main::$12) ← *((byte*~) main::$13)
Adding struct value member variable copy *((byte*~) main::$14) ← *((byte*~) main::$15)
Adding struct value member variable copy *((byte*~) main::$16) ← *((byte*~) main::$17)
Rewriting struct pointer member access *((struct Point*~) main::$6).x
Rewriting struct pointer member access *((struct Point*~) main::$7).y
Rewriting struct pointer member access *((struct Point*~) main::$8).x
Rewriting struct pointer member access *((struct Point*~) main::$9).y
Adding versioned struct unwinding for (struct Point) main::p1
Adding versioned struct unwinding for (struct Point) main::p2
Adding versioned struct unwinding for (struct Vector) main::v
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(byte*~) main::$0 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$0) ← (byte)(number) 2
(byte*~) main::$1 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$1) ← (byte)(number) 3
(struct Point) main::p1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
(byte*~) main::$2 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$2) ← (byte)(number) 4
(byte*~) main::$3 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$3) ← (byte)(number) 5
(struct Point) main::p2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
(struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$10 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$11 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$10) ← *((byte*~) main::$11)
(byte*~) main::$12 ← (byte*)(struct Point*~) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$13 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$12) ← *((byte*~) main::$13)
(struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$14 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$15 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$14) ← *((byte*~) main::$15)
(byte*~) main::$16 ← (byte*)(struct Point*~) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
(byte*~) main::$17 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$16) ← *((byte*~) main::$17)
(struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$4), *((struct Point*~) main::$5)}
(byte*~) main::$18 ← (byte*)(struct Point*~) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
(struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$19 ← (byte*)(struct Point*~) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
(struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
(byte*~) main::$20 ← (byte*)(struct Point*~) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
(struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
(byte*~) main::$21 ← (byte*)(struct Point*~) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
(struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$10
(byte*~) main::$11
(byte*~) main::$12
(byte*~) main::$13
(byte*~) main::$14
(byte*~) main::$15
(byte*~) main::$16
(byte*~) main::$17
(byte*~) main::$18
(byte*~) main::$19
(byte*~) main::$2
(byte*~) main::$20
(byte*~) main::$21
(byte*~) main::$3
(struct Point*~) main::$4
(struct Point*~) main::$5
(struct Point*~) main::$6
(struct Point*~) main::$7
(struct Point*~) main::$8
(struct Point*~) main::$9
(label) main::@return
(struct Point) main::p1 loadstore
(struct Point) main::p2 loadstore
(struct Vector) main::v loadstore
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$18)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$19)
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$20)
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$21)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) main::p1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
Removing C-classic struct-unwound assignment [9] (struct Point) main::p2 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
Removing C-classic struct-unwound assignment [24] (struct Vector) main::v ← struct-unwound {*((struct Point*~) main::$4), *((struct Point*~) main::$5)}
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [10] (struct Point*~) main::$4 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [12] (byte*~) main::$11 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [15] (byte*~) main::$13 ← (byte*)&(struct Point) main::p1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [17] (struct Point*~) main::$5 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [19] (byte*~) main::$15 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [22] (byte*~) main::$17 ← (byte*)&(struct Point) main::p2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [27] (struct Point*~) main::$6 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [30] (struct Point*~) main::$7 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_P
Constant right-side identified [33] (struct Point*~) main::$8 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Constant right-side identified [36] (struct Point*~) main::$9 ← (struct Point*)&(struct Vector) main::v + (const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$0 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) main::$4 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const byte*) main::$11 = (byte*)&main::p1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$13 = (byte*)&main::p1+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) main::$5 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const byte*) main::$15 = (byte*)&main::p2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$17 = (byte*)&main::p2+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) main::$6 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$7 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_P
Constant (const struct Point*) main::$8 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Constant (const struct Point*) main::$9 = (struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)main::$4 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$4 in [14] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$5 in [18] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$5 in [21] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$6 in [25] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$7 in [28] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)main::$8 in [31] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)main::$9 in [34] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [13] *((byte*~) main::$10) ← *((const byte*) main::$11) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [16] *((byte*~) main::$12) ← *((const byte*) main::$13) -- *((byte*)main::$4 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [20] *((byte*~) main::$14) ← *((const byte*) main::$15) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [23] *((byte*~) main::$16) ← *((const byte*) main::$17) -- *((byte*)main::$5 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*~) main::$18) -- *((byte*)main::$6 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [29] *((const byte*) SCREEN + (byte) 1) ← *((byte*~) main::$19) -- *((byte*)main::$7 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [32] *((const byte*) SCREEN + (byte) 2) ← *((byte*~) main::$20) -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [35] *((const byte*) SCREEN + (byte) 3) ← *((byte*~) main::$21) -- *((byte*)main::$9 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (byte*)&main::p1 in
Simplifying expression containing zero (byte*)&main::p2 in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)&main::p1 in
Simplifying expression containing zero (byte*)&main::p2 in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (struct Point*)&main::v in
Simplifying expression containing zero (byte*)main::$4 in [11] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$4 in [13] *((byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$11)
Simplifying expression containing zero (byte*)main::$5 in [18] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$5 in [20] *((byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_X) ← *((const byte*) main::$15)
Simplifying expression containing zero (byte*)main::$6 in [25] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$6 in [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6 + (const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [26] *((const byte*) SCREEN + (byte) 0) ← *((byte*)(const struct Point*) main::$6)
Simplifying expression containing zero (byte*)main::$8 in [31] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)main::$8 in [32] *((const byte*) SCREEN + (byte) 2) ← *((byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_X)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*~) main::$10 and assignment [4] (byte*~) main::$10 ← (byte*)(const struct Point*) main::$4
Eliminating unused variable (byte*~) main::$12 and assignment [6] (byte*~) main::$12 ← (byte*)(const struct Point*) main::$4 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$14 and assignment [8] (byte*~) main::$14 ← (byte*)(const struct Point*) main::$5
Eliminating unused variable (byte*~) main::$16 and assignment [10] (byte*~) main::$16 ← (byte*)(const struct Point*) main::$5 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$18 and assignment [12] (byte*~) main::$18 ← (byte*)(const struct Point*) main::$6
Eliminating unused variable (byte*~) main::$19 and assignment [14] (byte*~) main::$19 ← (byte*)(const struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) main::$20 and assignment [16] (byte*~) main::$20 ← (byte*)(const struct Point*) main::$8
Eliminating unused variable (byte*~) main::$21 and assignment [18] (byte*~) main::$21 ← (byte*)(const struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$13 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$15 = (byte*)&(struct Point) main::p2
Constant inlined main::$11 = (byte*)&(struct Point) main::p1
Constant inlined main::$1 = (byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)&(struct Point) main::p2
Constant inlined main::$17 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$0 = (byte*)&(struct Point) main::p1
Constant inlined main::$5 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$6 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$3 = (byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$4 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$9 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Constant inlined main::$7 = (struct Point*)&(struct Vector) main::v
Constant inlined main::$8 = (struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *(SCREEN+2)
Consolidated array index constant in *((byte*)(struct Point*)&main::v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::p1) ← (byte) 2
[5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) main::p2) ← (byte) 4
[7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1)
[9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2)
[11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y)
[12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y)
[14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q)
[15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[16] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(struct Point) main::p1 loadstore
(struct Point) main::p2 loadstore
(struct Vector) main::v loadstore
Initial phi equivalence classes
Added variable main::p1 to live range equivalence class [ main::p1 ]
Added variable main::p2 to live range equivalence class [ main::p2 ]
Added variable main::v to live range equivalence class [ main::v ]
Complete equivalence classes
[ main::p1 ]
[ main::p2 ]
[ main::v ]
Allocated zp[2]:2 [ main::p1 ]
Allocated zp[2]:4 [ main::p2 ]
Allocated zp[4]:6 [ main::v ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const OFFSET_STRUCT_VECTOR_Q = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label p1 = 2
.label p2 = 4
.label v = 6
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
Statement [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
Statement [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
Statement [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) [ main::p1 main::p2 main::v ] ( main:2 [ main::p1 main::p2 main::v ] ) always clobbers reg byte a
Statement [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::p2 main::v ] ( main:2 [ main::p2 main::v ] ) always clobbers reg byte a
Statement [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) [ main::p2 main::v ] ( main:2 [ main::p2 main::v ] ) always clobbers reg byte a
Statement [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v ] ( main:2 [ main::v ] ) always clobbers reg byte a
Statement [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ main::p1 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ main::p2 ] : zp[2]:4 ,
Potential registers zp[4]:6 [ main::v ] : zp[4]:6 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [Vector]
Uplift Scope [main] 0: zp[2]:2 [ main::p1 ] 0: zp[2]:4 [ main::p2 ] 0: zp[4]:6 [ main::v ]
Uplift Scope []
Uplifting [Point] best 103 combination
Uplifting [Vector] best 103 combination
Uplifting [main] best 103 combination zp[2]:2 [ main::p1 ] zp[2]:4 [ main::p2 ] zp[4]:6 [ main::v ]
Uplifting [] best 103 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const OFFSET_STRUCT_VECTOR_Q = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label p1 = 2
.label p2 = 4
.label v = 6
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [16] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Point) main::p1 loadstore zp[2]:2
(struct Point) main::p2 loadstore zp[2]:4
(struct Vector) main::v loadstore zp[4]:6
zp[2]:2 [ main::p1 ]
zp[2]:4 [ main::p2 ]
zp[4]:6 [ main::v ]
FINAL ASSEMBLER
Score: 88
// File Comments
// Minimal struct with C-Standard behavior - struct containing struct with initializer using sub-struct value
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
.const OFFSET_STRUCT_VECTOR_Q = 2
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label p1 = 2
.label p2 = 4
.label v = 6
// p1 = { 2, 3 }
// [4] *((byte*)&(struct Point) main::p1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p1
// [5] *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta p1+OFFSET_STRUCT_POINT_Y
// p2 = { 4, 5 }
// [6] *((byte*)&(struct Point) main::p2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p2
// [7] *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta p2+OFFSET_STRUCT_POINT_Y
// v = { p1, p2 }
// [8] *((byte*)(struct Point*)&(struct Vector) main::v) ← *((byte*)&(struct Point) main::p1) -- _deref_pbuc1=_deref_pbuc2
lda.z p1
sta.z v
// [9] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p1+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) ← *((byte*)&(struct Point) main::p2) -- _deref_pbuc1=_deref_pbuc2
lda.z p2
sta v+OFFSET_STRUCT_VECTOR_Q
// [11] *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)&(struct Point) main::p2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda p2+OFFSET_STRUCT_POINT_Y
sta v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = v.p.x
// [12] *((const byte*) SCREEN) ← *((byte*)(struct Point*)&(struct Vector) main::v) -- _deref_pbuc1=_deref_pbuc2
lda.z v
sta SCREEN
// SCREEN[1] = v.p.y
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// SCREEN[2] = v.q.x
// [14] *((const byte*) SCREEN+(byte) 2) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q
sta SCREEN+2
// SCREEN[3] = v.q.y
// [15] *((const byte*) SCREEN+(byte) 3) ← *((byte*)(struct Point*)&(struct Vector) main::v+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda v+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [16] return
rts
}
// File Data

@ -0,0 +1,19 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point) Vector::p
(struct Point) Vector::q
(void()) main()
(label) main::@return
(struct Point) main::p1 loadstore zp[2]:2
(struct Point) main::p2 loadstore zp[2]:4
(struct Vector) main::v loadstore zp[4]:6
zp[2]:2 [ main::p1 ]
zp[2]:4 [ main::p2 ]
zp[4]:6 [ main::v ]

@ -0,0 +1,19 @@
// Minimal struct with C-Standard behavior - address-of
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label ptr = point1
.label point1 = 2
lda #2
sta.z point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
lda.z ptr
sta SCREEN
lda ptr+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
rts
}

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return

330
src/test/ref/struct-21.log Normal file

@ -0,0 +1,330 @@
Setting inferred volatile on symbol affected by address-of (struct Point*) main::ptr ← &(struct Point) main::point1
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
Rewriting struct pointer member access *((struct Point*) main::ptr).x
Rewriting struct pointer member access *((struct Point*) main::ptr).y
Identified constant variable (struct Point*) main::ptr
Adding versioned struct unwinding for (struct Point) main::point1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
(byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$0) ← (byte)(number) 2
(byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$1) ← (byte)(number) 3
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
(byte*~) main::$2 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
(byte*~) main::$3 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
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
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(label) main::@return
(struct Point) main::point1 loadstore
(const struct Point*) main::ptr = &(struct Point) main::point1
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$2)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$3)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::ptr + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$0 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)main::ptr+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)main::ptr+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)main::ptr in
Simplifying expression containing zero SCREEN in [6] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$3 = (byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$1 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)(const struct Point*) main::ptr
Constant inlined main::$0 = (byte*)&(struct Point) main::point1
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
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:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr)
[7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) main::point1 loadstore
Initial phi equivalence classes
Added variable main::point1 to live range equivalence class [ main::point1 ]
Complete equivalence classes
[ main::point1 ]
Allocated zp[2]:2 [ main::point1 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - address-of
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label ptr = point1
.label point1 = 2
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
lda.z ptr
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda ptr+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 ] ( main:2 [ main::point1 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[2]:2 [ main::point1 ] : zp[2]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:2 [ main::point1 ]
Uplift Scope []
Uplifting [Point] best 47 combination
Uplifting [main] best 47 combination zp[2]:2 [ main::point1 ]
Uplifting [] best 47 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - address-of
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label ptr = point1
.label point1 = 2
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
lda.z ptr
sta SCREEN
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda ptr+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(const struct Point*) main::ptr = &(struct Point) main::point1
zp[2]:2 [ main::point1 ]
FINAL ASSEMBLER
Score: 32
// File Comments
// Minimal struct with C-Standard behavior - address-of
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label ptr = point1
.label point1 = 2
// point1 = { 2, 3 }
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = ptr->x
// [6] *((const byte*) SCREEN) ← *((byte*)(const struct Point*) main::ptr) -- _deref_pbuc1=_deref_pbuc2
lda.z ptr
sta SCREEN
// SCREEN[1] = ptr->y
// [7] *((const byte*) SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::ptr+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda ptr+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// main::@return
// }
// [8] return
rts
}
// File Data

@ -0,0 +1,13 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(const struct Point*) main::ptr = &(struct Point) main::point1
zp[2]:2 [ main::point1 ]

@ -0,0 +1,31 @@
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label point1 = 2
.label point2 = 4
lda #2
sta.z point1
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
lda #4
sta.z point2
lda #5
sta point2+OFFSET_STRUCT_POINT_Y
lda.z point1
ldx point1+OFFSET_STRUCT_POINT_Y
jsr print
lda.z point2
ldx point2+OFFSET_STRUCT_POINT_Y
jsr print
rts
}
// print(byte register(A) p_x, byte register(X) p_y)
print: {
sta SCREEN
stx SCREEN+1
rts
}

@ -0,0 +1,39 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) main::point2) ← (byte) 4
[7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1)
[9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] call print
to:main::@1
main::@1: scope:[main] from main
[11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2)
[12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
[13] call print
to:main::@return
main::@return: scope:[main] from main::@1
[14] return
to:@return
(void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from main main::@1
[15] (byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
[15] (byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
[16] *((const byte*) SCREEN) ← (byte) print::p_x#2
[17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2
to:print::@return
print::@return: scope:[print] from print
[18] return
to:@return

587
src/test/ref/struct-22.log Normal file

@ -0,0 +1,587 @@
Created struct value member variable (byte) print::p_x
Created struct value member variable (byte) print::p_y
Converted struct value to member variables (struct Point) print::p
Converted procedure struct value parameter to member unwinding (void()) print((byte) print::p_x , (byte) print::p_y)
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$3) ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$4) ← (byte)(number) 4
Adding struct value member variable copy *((byte*~) main::$5) ← (byte)(number) 5
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print *((byte*~) main::$6) *((byte*~) main::$7)
Converted procedure struct value parameter to member unwinding in call (void~) main::$1 ← call print *((byte*~) main::$8) *((byte*~) main::$9)
Replacing struct member reference (struct Point) print::p.x with member unwinding reference (byte) print::p_x
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (byte) print::p_y
Culled Empty Block (label) @1
Adding versioned struct unwinding for (struct Point) main::point1
Adding versioned struct unwinding for (struct Point) main::point2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@2
(void()) main()
main: scope:[main] from @2
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$2) ← (byte)(number) 2
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$3) ← (byte)(number) 3
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$4) ← (byte)(number) 4
(byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$5) ← (byte)(number) 5
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
(byte) print::p_x#0 ← *((byte*~) main::$6)
(byte) print::p_y#0 ← *((byte*~) main::$7)
call print
to:main::@1
main::@1: scope:[main] from main
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
(byte) print::p_x#1 ← *((byte*~) main::$8)
(byte) print::p_y#1 ← *((byte*~) main::$9)
call print
to:main::@2
main::@2: scope:[main] from main::@1
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
(void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from main main::@1
(byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
(byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
*((const byte*) SCREEN + (number) 0) ← (byte) print::p_x#2
*((const byte*) SCREEN + (number) 1) ← (byte) print::p_y#2
to:print::@return
print::@return: scope:[print] from print
return
to:@return
@2: scope:[] from @begin
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(void()) main()
(byte*~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(byte*~) main::$6
(byte*~) main::$7
(byte*~) main::$8
(byte*~) main::$9
(label) main::@1
(label) main::@2
(label) main::@return
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
(void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0
(byte) print::p_x#1
(byte) print::p_x#2
(byte) print::p_y
(byte) print::p_y#0
(byte) print::p_y#1
(byte) print::p_y#2
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← (byte) print::p_x#2
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← (byte) print::p_y#2
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [4] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
Removing C-classic struct-unwound assignment [9] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
Constant right-side identified [0] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [5] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [13] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [14] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [18] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [19] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$5 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero SCREEN in [22] *((const byte*) SCREEN + (byte) 0) ← (byte) print::p_x#2
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
Constant inlined main::$5 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$4 = (byte*)&(struct Point) main::point2
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main::@2
CALL GRAPH
Calls in [] to main:2
Calls in [main] to print:13 print:18
Created 2 initial phi equivalence classes
Coalesced [11] print::p_x#3 ← print::p_x#0
Coalesced [12] print::p_y#3 ← print::p_y#0
Coalesced [16] print::p_x#4 ← print::p_x#1
Coalesced [17] print::p_y#4 ← print::p_y#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@2
Renumbering block @2 to @1
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((byte*)&(struct Point) main::point1) ← (byte) 2
[5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((byte*)&(struct Point) main::point2) ← (byte) 4
[7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5
[8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1)
[9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[10] call print
to:main::@1
main::@1: scope:[main] from main
[11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2)
[12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
[13] call print
to:main::@return
main::@return: scope:[main] from main::@1
[14] return
to:@return
(void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from main main::@1
[15] (byte) print::p_y#2 ← phi( main/(byte) print::p_y#0 main::@1/(byte) print::p_y#1 )
[15] (byte) print::p_x#2 ← phi( main/(byte) print::p_x#0 main::@1/(byte) print::p_x#1 )
[16] *((const byte*) SCREEN) ← (byte) print::p_x#2
[17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2
to:print::@return
print::@return: scope:[print] from print
[18] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
(void()) print((byte) print::p_x , (byte) print::p_y)
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0 2.0
(byte) print::p_x#1 2.0
(byte) print::p_x#2 6.0
(byte) print::p_y
(byte) print::p_y#0 4.0
(byte) print::p_y#1 4.0
(byte) print::p_y#2 3.0
Initial phi equivalence classes
[ print::p_x#2 print::p_x#0 print::p_x#1 ]
[ print::p_y#2 print::p_y#0 print::p_y#1 ]
Added variable main::point1 to live range equivalence class [ main::point1 ]
Added variable main::point2 to live range equivalence class [ main::point2 ]
Complete equivalence classes
[ print::p_x#2 print::p_x#0 print::p_x#1 ]
[ print::p_y#2 print::p_y#0 print::p_y#1 ]
[ main::point1 ]
[ main::point2 ]
Allocated zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ]
Allocated zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ]
Allocated zp[2]:4 [ main::point1 ]
Allocated zp[2]:6 [ main::point2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 4
.label point2 = 6
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z point2
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta point2+OFFSET_STRUCT_POINT_Y
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuz1=_deref_pbuc1
lda.z point1
sta.z print.p_x
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
lda point1+OFFSET_STRUCT_POINT_Y
sta.z print.p_y
// [10] call print
// [15] phi from main to print [phi:main->print]
print_from_main:
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
jsr print
jmp __b1
// main::@1
__b1:
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuz1=_deref_pbuc1
lda.z point2
sta.z print.p_x
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1
lda point2+OFFSET_STRUCT_POINT_Y
sta.z print.p_y
// [13] call print
// [15] phi from main::@1 to print [phi:main::@1->print]
print_from___b1:
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
jsr print
jmp __breturn
// main::@return
__breturn:
// [14] return
rts
}
// print
// print(byte zp(2) p_x, byte zp(3) p_y)
print: {
.label p_x = 2
.label p_y = 3
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuz1
lda.z p_x
sta SCREEN
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuz1
lda.z p_y
sta SCREEN+1
jmp __breturn
// print::@return
__breturn:
// [18] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[2]:4 [ main::point1 ] : zp[2]:4 ,
Potential registers zp[2]:6 [ main::point2 ] : zp[2]:6 ,
REGISTER UPLIFT SCOPES
Uplift Scope [print] 11: zp[1]:3 [ print::p_y#2 print::p_y#0 print::p_y#1 ] 10: zp[1]:2 [ print::p_x#2 print::p_x#0 print::p_x#1 ]
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:4 [ main::point1 ] 0: zp[2]:6 [ main::point2 ]
Uplift Scope []
Uplifting [print] best 89 combination reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ] reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
Uplifting [Point] best 89 combination
Uplifting [main] best 89 combination zp[2]:4 [ main::point1 ] zp[2]:6 [ main::point2 ]
Uplifting [] best 89 combination
Allocated (was zp[2]:4) zp[2]:2 [ main::point1 ]
Allocated (was zp[2]:6) zp[2]:4 [ main::point2 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
.label point2 = 4
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z point2
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta point2+OFFSET_STRUCT_POINT_Y
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuaa=_deref_pbuc1
lda.z point1
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx point1+OFFSET_STRUCT_POINT_Y
// [10] call print
// [15] phi from main to print [phi:main->print]
print_from_main:
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
jsr print
jmp __b1
// main::@1
__b1:
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuaa=_deref_pbuc1
lda.z point2
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx point2+OFFSET_STRUCT_POINT_Y
// [13] call print
// [15] phi from main::@1 to print [phi:main::@1->print]
print_from___b1:
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
jsr print
jmp __breturn
// main::@return
__breturn:
// [14] return
rts
}
// print
// print(byte register(A) p_x, byte register(X) p_y)
print: {
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuaa
sta SCREEN
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuxx
stx SCREEN+1
jmp __breturn
// print::@return
__breturn:
// [18] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction print_from_main:
Removing instruction __b1:
Removing instruction print_from___b1:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@1
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
(void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0 reg byte a 2.0
(byte) print::p_x#1 reg byte a 2.0
(byte) print::p_x#2 reg byte a 6.0
(byte) print::p_y
(byte) print::p_y#0 reg byte x 4.0
(byte) print::p_y#1 reg byte x 4.0
(byte) print::p_y#2 reg byte x 3.0
reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ]
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]
FINAL ASSEMBLER
Score: 68
// File Comments
// Minimal struct with C-Standard behavior - call parameter (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label point1 = 2
.label point2 = 4
// point1 = { 2, 3 }
// [4] *((byte*)&(struct Point) main::point1) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z point1
// [5] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta point1+OFFSET_STRUCT_POINT_Y
// point2 = { 4, 5 }
// [6] *((byte*)&(struct Point) main::point2) ← (byte) 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z point2
// [7] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2
lda #5
sta point2+OFFSET_STRUCT_POINT_Y
// print(point1)
// [8] (byte) print::p_x#0 ← *((byte*)&(struct Point) main::point1) -- vbuaa=_deref_pbuc1
lda.z point1
// [9] (byte) print::p_y#0 ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx point1+OFFSET_STRUCT_POINT_Y
// [10] call print
// [15] phi from main to print [phi:main->print]
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#0 [phi:main->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#0 [phi:main->print#1] -- register_copy
jsr print
// main::@1
// print(point2)
// [11] (byte) print::p_x#1 ← *((byte*)&(struct Point) main::point2) -- vbuaa=_deref_pbuc1
lda.z point2
// [12] (byte) print::p_y#1 ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx point2+OFFSET_STRUCT_POINT_Y
// [13] call print
// [15] phi from main::@1 to print [phi:main::@1->print]
// [15] phi (byte) print::p_y#2 = (byte) print::p_y#1 [phi:main::@1->print#0] -- register_copy
// [15] phi (byte) print::p_x#2 = (byte) print::p_x#1 [phi:main::@1->print#1] -- register_copy
jsr print
// main::@return
// }
// [14] return
rts
}
// print
// print(byte register(A) p_x, byte register(X) p_y)
print: {
// SCREEN[0] = p.x
// [16] *((const byte*) SCREEN) ← (byte) print::p_x#2 -- _deref_pbuc1=vbuaa
sta SCREEN
// SCREEN[1] = p.y
// [17] *((const byte*) SCREEN+(byte) 1) ← (byte) print::p_y#2 -- _deref_pbuc1=vbuxx
stx SCREEN+1
// print::@return
// }
// [18] return
rts
}
// File Data

@ -0,0 +1,28 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@1
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
(void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0 reg byte a 2.0
(byte) print::p_x#1 reg byte a 2.0
(byte) print::p_x#2 reg byte a 6.0
(byte) print::p_y
(byte) print::p_y#0 reg byte x 4.0
(byte) print::p_y#1 reg byte x 4.0
(byte) print::p_y#2 reg byte x 3.0
reg byte a [ print::p_x#2 print::p_x#0 print::p_x#1 ]
reg byte x [ print::p_y#2 print::p_y#0 print::p_y#1 ]
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]

@ -0,0 +1,32 @@
// Minimal struct with C-Standard behavior - call return value (not supported yet)
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label point1 = 2
.label point2 = 4
lda #3
ldx #2
jsr getPoint
stx.z point1
sta point1+OFFSET_STRUCT_POINT_Y
txa
sta SCREEN
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
lda #5
ldx #4
jsr getPoint
stx.z point2
sta point2+OFFSET_STRUCT_POINT_Y
txa
sta SCREEN+2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
rts
}
getPoint: {
rts
}

@ -0,0 +1,48 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] phi()
[5] call getPoint
[6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
[7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
to:main::@1
main::@1: scope:[main] from main
[8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
[9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
[10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x
[11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y
[12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[14] call getPoint
[15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
[16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
to:main::@2
main::@2: scope:[main] from main::@1
[17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
[18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
[19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x
[20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2)
[22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main::@2
[23] return
to:@return
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
getPoint: scope:[getPoint] from main main::@1
[24] (byte) getPoint::return_y#2 ← phi( main/(byte) 3 main::@1/(byte) 5 )
[24] (byte) getPoint::return_x#2 ← phi( main/(byte) 2 main::@1/(byte) 4 )
to:getPoint::@return
getPoint::@return: scope:[getPoint] from getPoint
[25] return
to:@return

848
src/test/ref/struct-23.log Normal file

@ -0,0 +1,848 @@
Created struct value member variable (byte~) main::$0_x
Created struct value member variable (byte~) main::$0_y
Converted struct value to member variables (struct Point~) main::$0
Created struct value member variable (byte~) main::$1_x
Created struct value member variable (byte~) main::$1_y
Converted struct value to member variables (struct Point~) main::$1
Created struct value member variable (byte) getPoint::return_x
Created struct value member variable (byte) getPoint::return_y
Converted struct value to member variables (struct Point) getPoint::return
Created struct value member variable (byte) getPoint::p_x
Created struct value member variable (byte) getPoint::p_y
Converted struct value to member variables (struct Point) getPoint::p
Converted procedure call LValue to member unwinding { (byte~) main::$0_x, (byte~) main::$0_y } ← call getPoint (number) 2 (number) 3
Adding struct value member variable copy *((byte*~) main::$2) ← (byte~) main::$0_x
Adding struct value member variable copy *((byte*~) main::$3) ← (byte~) main::$0_y
Converted procedure call LValue to member unwinding { (byte~) main::$1_x, (byte~) main::$1_y } ← call getPoint (number) 4 (number) 5
Adding struct value member variable copy *((byte*~) main::$4) ← (byte~) main::$1_x
Adding struct value member variable copy *((byte*~) main::$5) ← (byte~) main::$1_y
Adding struct value list initializer (byte) getPoint::p_x ← (byte) getPoint::x
Adding struct value list initializer (byte) getPoint::p_y ← (byte) getPoint::y
Adding struct value member variable copy (byte) getPoint::return_x ← (byte) getPoint::p_x
Adding struct value member variable copy (byte) getPoint::return_y ← (byte) getPoint::p_y
Adding struct value member variable copy (byte) getPoint::return_x ← (byte) getPoint::return_x
Adding struct value member variable copy (byte) getPoint::return_y ← (byte) getPoint::return_y
Converted procedure struct return value to member unwinding return { (byte) getPoint::return_x, (byte) getPoint::return_y }
Replacing struct member reference (struct Point) main::point1.x with member unwinding reference *((byte*~) main::$6)
Replacing struct member reference (struct Point) main::point1.y with member unwinding reference *((byte*~) main::$7)
Replacing struct member reference (struct Point) main::point2.x with member unwinding reference *((byte*~) main::$8)
Replacing struct member reference (struct Point) main::point2.y with member unwinding reference *((byte*~) main::$9)
Culled Empty Block (label) @1
Culled Empty Block (label) getPoint::@1
Unwinding list assignment { (byte~) main::$0_x, (byte~) main::$0_y } ← { (byte) getPoint::return_x, (byte) getPoint::return_y }
Unwinding list assignment { (byte~) main::$1_x, (byte~) main::$1_y } ← { (byte) getPoint::return_x, (byte) getPoint::return_y }
Unwinding list assignment { (byte) getPoint::return_x#0, (byte) getPoint::return_y#0 } ← { (byte) getPoint::return_x#3, (byte) getPoint::return_y#3 }
Unwinding list assignment { (byte) getPoint::return_x#1, (byte) getPoint::return_y#1 } ← { (byte) getPoint::return_x#3, (byte) getPoint::return_y#3 }
Adding versioned struct unwinding for (struct Point) main::point1
Adding versioned struct unwinding for (struct Point) main::point2
Adding versioned struct unwinding for (struct Point) getPoint::return#0
Adding versioned struct unwinding for (struct Point) getPoint::return#1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@2
(void()) main()
main: scope:[main] from @2
(byte) getPoint::x#0 ← (number) 2
(byte) getPoint::y#0 ← (number) 3
call getPoint
(byte) getPoint::return_x#0 ← (byte) getPoint::return_x#3
(byte) getPoint::return_y#0 ← (byte) getPoint::return_y#3
to:main::@1
main::@1: scope:[main] from main
(byte) getPoint::return_y#4 ← phi( main/(byte) getPoint::return_y#0 )
(byte) getPoint::return_x#4 ← phi( main/(byte) getPoint::return_x#0 )
(byte~) main::$0_x ← (byte) getPoint::return_x#4
(byte~) main::$0_y ← (byte) getPoint::return_y#4
(byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$2) ← (byte~) main::$0_x
(byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$3) ← (byte~) main::$0_y
(struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
*((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6)
(byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7)
(byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
(byte) getPoint::x#1 ← (number) 4
(byte) getPoint::y#1 ← (number) 5
call getPoint
(byte) getPoint::return_x#1 ← (byte) getPoint::return_x#3
(byte) getPoint::return_y#1 ← (byte) getPoint::return_y#3
to:main::@2
main::@2: scope:[main] from main::@1
(byte) getPoint::return_y#5 ← phi( main::@1/(byte) getPoint::return_y#1 )
(byte) getPoint::return_x#5 ← phi( main::@1/(byte) getPoint::return_x#1 )
(byte~) main::$1_x ← (byte) getPoint::return_x#5
(byte~) main::$1_y ← (byte) getPoint::return_y#5
(byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$4) ← (byte~) main::$1_x
(byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$5) ← (byte~) main::$1_y
(struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
*((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$8)
(byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$9)
(byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
getPoint: scope:[getPoint] from main main::@1
(byte) getPoint::y#2 ← phi( main/(byte) getPoint::y#0 main::@1/(byte) getPoint::y#1 )
(byte) getPoint::x#2 ← phi( main/(byte) getPoint::x#0 main::@1/(byte) getPoint::x#1 )
(byte) getPoint::p_x#0 ← (byte) getPoint::x#2
(byte) getPoint::p_y#0 ← (byte) getPoint::y#2
(byte) getPoint::return_x#2 ← (byte) getPoint::p_x#0
(byte) getPoint::return_y#2 ← (byte) getPoint::p_y#0
(struct Point) getPoint::return#0 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
to:getPoint::@return
getPoint::@return: scope:[getPoint] from getPoint
(byte) getPoint::return_y#6 ← phi( getPoint/(byte) getPoint::return_y#2 )
(byte) getPoint::return_x#6 ← phi( getPoint/(byte) getPoint::return_x#2 )
(byte) getPoint::return_x#3 ← (byte) getPoint::return_x#6
(byte) getPoint::return_y#3 ← (byte) getPoint::return_y#6
(struct Point) getPoint::return#1 ← struct-unwound {(byte) getPoint::return_x#3, (byte) getPoint::return_y#3}
return
to:@return
@2: scope:[] from @begin
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*)(number) $400
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
(label) getPoint::@return
(byte) getPoint::p_x
(byte) getPoint::p_x#0
(byte) getPoint::p_y
(byte) getPoint::p_y#0
(struct Point) getPoint::return
(struct Point) getPoint::return#0
(struct Point) getPoint::return#1
(byte) getPoint::return_x
(byte) getPoint::return_x#0
(byte) getPoint::return_x#1
(byte) getPoint::return_x#2
(byte) getPoint::return_x#3
(byte) getPoint::return_x#4
(byte) getPoint::return_x#5
(byte) getPoint::return_x#6
(byte) getPoint::return_y
(byte) getPoint::return_y#0
(byte) getPoint::return_y#1
(byte) getPoint::return_y#2
(byte) getPoint::return_y#3
(byte) getPoint::return_y#4
(byte) getPoint::return_y#5
(byte) getPoint::return_y#6
(byte) getPoint::x
(byte) getPoint::x#0
(byte) getPoint::x#1
(byte) getPoint::x#2
(byte) getPoint::y
(byte) getPoint::y#0
(byte) getPoint::y#1
(byte) getPoint::y#2
(void()) main()
(struct Point~) main::$0
(byte~) main::$0_x
(byte~) main::$0_y
(struct Point~) main::$1
(byte~) main::$1_x
(byte~) main::$1_y
(byte*~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(byte*~) main::$6
(byte*~) main::$7
(byte*~) main::$8
(byte*~) main::$9
(label) main::@1
(label) main::@2
(label) main::@return
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
Adding number conversion cast (unumber) 2 in (byte) getPoint::x#0 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) getPoint::y#0 ← (number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*~) main::$6)
Adding number conversion cast (unumber) 1 in *((const byte*) SCREEN + (number) 1) ← *((byte*~) main::$7)
Adding number conversion cast (unumber) 4 in (byte) getPoint::x#1 ← (number) 4
Adding number conversion cast (unumber) 5 in (byte) getPoint::y#1 ← (number) 5
Adding number conversion cast (unumber) 2 in *((const byte*) SCREEN + (number) 2) ← *((byte*~) main::$8)
Adding number conversion cast (unumber) 3 in *((const byte*) SCREEN + (number) 3) ← *((byte*~) main::$9)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) getPoint::x#0 ← (unumber)(number) 2
Inlining cast (byte) getPoint::y#0 ← (unumber)(number) 3
Inlining cast (byte) getPoint::x#1 ← (unumber)(number) 4
Inlining cast (byte) getPoint::y#1 ← (unumber)(number) 5
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 4
Simplifying constant integer cast 5
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 4
Finalized unsigned number type (byte) 5
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) getPoint::return_x#0 = (byte) getPoint::return_x#4
Alias (byte) getPoint::return_y#0 = (byte) getPoint::return_y#4
Alias (byte) getPoint::return_x#1 = (byte) getPoint::return_x#5
Alias (byte) getPoint::return_y#1 = (byte) getPoint::return_y#5
Alias (byte) getPoint::return_x#2 = (byte) getPoint::p_x#0 (byte) getPoint::x#2 (byte) getPoint::return_x#6 (byte) getPoint::return_x#3
Alias (byte) getPoint::return_y#2 = (byte) getPoint::p_y#0 (byte) getPoint::y#2 (byte) getPoint::return_y#6 (byte) getPoint::return_y#3
Successful SSA optimization Pass2AliasElimination
Removing C-classic struct-unwound assignment [12] (struct Point) main::point1 ← struct-unwound {*((byte*~) main::$2), *((byte*~) main::$3)}
Removing C-classic struct-unwound assignment [29] (struct Point) main::point2 ← struct-unwound {*((byte*~) main::$4), *((byte*~) main::$5)}
Constant right-side identified [8] (byte*~) main::$2 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [10] (byte*~) main::$3 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [14] (byte*~) main::$6 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [16] (byte*~) main::$7 ← (byte*)&(struct Point) main::point1 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [25] (byte*~) main::$4 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [27] (byte*~) main::$5 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [31] (byte*~) main::$8 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [33] (byte*~) main::$9 ← (byte*)&(struct Point) main::point2 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) getPoint::x#0 = 2
Constant (const byte) getPoint::y#0 = 3
Constant (const byte*) main::$2 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$6 = (byte*)&main::point1+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$7 = (byte*)&main::point1+OFFSET_STRUCT_POINT_Y
Constant (const byte) getPoint::x#1 = 4
Constant (const byte) getPoint::y#1 = 5
Constant (const byte*) main::$4 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$5 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$8 = (byte*)&main::point2+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$9 = (byte*)&main::point2+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point1 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero (byte*)&main::point2 in
Simplifying expression containing zero SCREEN in [13] *((const byte*) SCREEN + (byte) 0) ← *((const byte*) main::$6)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct Point) getPoint::return#0 and assignment [20] (struct Point) getPoint::return#0 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
Eliminating unused variable (struct Point) getPoint::return#1 and assignment [21] (struct Point) getPoint::return#1 ← struct-unwound {(byte) getPoint::return_x#2, (byte) getPoint::return_y#2}
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Inlining constant with different constant siblings (const byte) getPoint::x#0
Inlining constant with different constant siblings (const byte) getPoint::y#0
Inlining constant with different constant siblings (const byte) getPoint::x#1
Inlining constant with different constant siblings (const byte) getPoint::y#1
Constant inlined main::$2 = (byte*)&(struct Point) main::point1
Constant inlined main::$5 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$6 = (byte*)&(struct Point) main::point1
Constant inlined main::$3 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined getPoint::y#0 = (byte) 3
Constant inlined getPoint::x#1 = (byte) 4
Constant inlined main::$4 = (byte*)&(struct Point) main::point2
Constant inlined getPoint::y#1 = (byte) 5
Constant inlined main::$9 = (byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined getPoint::x#0 = (byte) 2
Constant inlined main::$7 = (byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$8 = (byte*)&(struct Point) main::point2
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *(SCREEN+2)
Consolidated array index constant in *(SCREEN+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Calls in [main] to getPoint:6 getPoint:15
Created 2 initial phi equivalence classes
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @3
Renumbering block @2 to @1
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] phi()
[5] call getPoint
[6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
[7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
to:main::@1
main::@1: scope:[main] from main
[8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
[9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
[10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x
[11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y
[12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1)
[13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y)
[14] call getPoint
[15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
[16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
to:main::@2
main::@2: scope:[main] from main::@1
[17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
[18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
[19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x
[20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2)
[22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
main::@return: scope:[main] from main::@2
[23] return
to:@return
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
getPoint: scope:[getPoint] from main main::@1
[24] (byte) getPoint::return_y#2 ← phi( main/(byte) 3 main::@1/(byte) 5 )
[24] (byte) getPoint::return_x#2 ← phi( main/(byte) 2 main::@1/(byte) 4 )
to:getPoint::@return
getPoint::@return: scope:[getPoint] from getPoint
[25] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
(byte) getPoint::p_x
(byte) getPoint::p_y
(struct Point) getPoint::return
(byte) getPoint::return_x
(byte) getPoint::return_x#0 2.0
(byte) getPoint::return_x#1 2.0
(byte) getPoint::return_x#2 1.0
(byte) getPoint::return_y
(byte) getPoint::return_y#0 2.0
(byte) getPoint::return_y#1 2.0
(byte) getPoint::return_y#2 0.6666666666666666
(byte) getPoint::x
(byte) getPoint::y
(void()) main()
(struct Point~) main::$0
(byte~) main::$0_x 2.0
(byte~) main::$0_y 2.0
(struct Point~) main::$1
(byte~) main::$1_x 2.0
(byte~) main::$1_y 2.0
(struct Point) main::point1 loadstore
(struct Point) main::point2 loadstore
Initial phi equivalence classes
[ getPoint::return_x#2 ]
[ getPoint::return_y#2 ]
Added variable getPoint::return_x#0 to live range equivalence class [ getPoint::return_x#0 ]
Added variable getPoint::return_y#0 to live range equivalence class [ getPoint::return_y#0 ]
Added variable main::$0_x to live range equivalence class [ main::$0_x ]
Added variable main::$0_y to live range equivalence class [ main::$0_y ]
Added variable getPoint::return_x#1 to live range equivalence class [ getPoint::return_x#1 ]
Added variable getPoint::return_y#1 to live range equivalence class [ getPoint::return_y#1 ]
Added variable main::$1_x to live range equivalence class [ main::$1_x ]
Added variable main::$1_y to live range equivalence class [ main::$1_y ]
Added variable main::point1 to live range equivalence class [ main::point1 ]
Added variable main::point2 to live range equivalence class [ main::point2 ]
Complete equivalence classes
[ getPoint::return_x#2 ]
[ getPoint::return_y#2 ]
[ getPoint::return_x#0 ]
[ getPoint::return_y#0 ]
[ main::$0_x ]
[ main::$0_y ]
[ getPoint::return_x#1 ]
[ getPoint::return_y#1 ]
[ main::$1_x ]
[ main::$1_y ]
[ main::point1 ]
[ main::point2 ]
Allocated zp[1]:2 [ getPoint::return_x#2 ]
Allocated zp[1]:3 [ getPoint::return_y#2 ]
Allocated zp[1]:4 [ getPoint::return_x#0 ]
Allocated zp[1]:5 [ getPoint::return_y#0 ]
Allocated zp[1]:6 [ main::$0_x ]
Allocated zp[1]:7 [ main::$0_y ]
Allocated zp[1]:8 [ getPoint::return_x#1 ]
Allocated zp[1]:9 [ getPoint::return_y#1 ]
Allocated zp[1]:10 [ main::$1_x ]
Allocated zp[1]:11 [ main::$1_y ]
Allocated zp[2]:12 [ main::point1 ]
Allocated zp[2]:14 [ main::point2 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Minimal struct with C-Standard behavior - call return value (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from___b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = $c
.label point2 = $e
.label __0_x = 6
.label __0_y = 7
.label __1_x = $a
.label __1_y = $b
// [5] call getPoint
// [24] phi from main to getPoint [phi:main->getPoint]
getPoint_from_main:
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuz1=vbuc1
lda #3
sta.z getPoint.return_y_2
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuz1=vbuc1
lda #2
sta.z getPoint.return_x_2
jsr getPoint
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2 -- vbuz1=vbuz2
lda.z getPoint.return_x_2
sta.z getPoint.return_x
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2 -- vbuz1=vbuz2
lda.z getPoint.return_y_2
sta.z getPoint.return_y
jmp __b1
// main::@1
__b1:
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0 -- vbuz1=vbuz2
lda.z getPoint.return_x
sta.z __0_x
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0 -- vbuz1=vbuz2
lda.z getPoint.return_y
sta.z __0_y
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuz1
lda.z __0_x
sta.z point1
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuz1
lda.z __0_y
sta point1+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] call getPoint
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
getPoint_from___b1:
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuz1=vbuc1
lda #5
sta.z getPoint.return_y_2
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuz1=vbuc1
lda #4
sta.z getPoint.return_x_2
jsr getPoint
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2 -- vbuz1=vbuz2
lda.z getPoint.return_x_2
sta.z getPoint.return_x_1
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2 -- vbuz1=vbuz2
lda.z getPoint.return_y_2
sta.z getPoint.return_y_1
jmp __b2
// main::@2
__b2:
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1 -- vbuz1=vbuz2
lda.z getPoint.return_x_1
sta.z __1_x
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1 -- vbuz1=vbuz2
lda.z getPoint.return_y_1
sta.z __1_y
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1
lda.z __1_x
sta.z point2
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1
lda.z __1_y
sta point2+OFFSET_STRUCT_POINT_Y
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
lda.z point2
sta SCREEN+2
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [23] return
rts
}
// getPoint
getPoint: {
.label return_x = 4
.label return_y = 5
.label return_x_1 = 8
.label return_y_1 = 9
.label return_x_2 = 2
.label return_y_2 = 3
jmp __breturn
// getPoint::@return
__breturn:
// [25] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) [ main::point1 main::point2 ] ( main:2 [ main::point1 main::point2 ] ) always clobbers reg byte a
Statement [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
Statement [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) [ main::point2 ] ( main:2 [ main::point2 ] ) always clobbers reg byte a
Statement [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ getPoint::return_x#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ getPoint::return_y#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:4 [ getPoint::return_x#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:5 [ getPoint::return_y#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:6 [ main::$0_x ] : zp[1]:6 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:7 [ main::$0_y ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:8 [ getPoint::return_x#1 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:9 [ getPoint::return_y#1 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[2]:12 [ main::point1 ] : zp[2]:12 ,
Potential registers zp[2]:14 [ main::point2 ] : zp[2]:14 ,
REGISTER UPLIFT SCOPES
Uplift Scope [getPoint] 2: zp[1]:4 [ getPoint::return_x#0 ] 2: zp[1]:5 [ getPoint::return_y#0 ] 2: zp[1]:8 [ getPoint::return_x#1 ] 2: zp[1]:9 [ getPoint::return_y#1 ] 1: zp[1]:2 [ getPoint::return_x#2 ] 0.67: zp[1]:3 [ getPoint::return_y#2 ]
Uplift Scope [main] 2: zp[1]:6 [ main::$0_x ] 2: zp[1]:7 [ main::$0_y ] 2: zp[1]:10 [ main::$1_x ] 2: zp[1]:11 [ main::$1_y ] 0: zp[2]:12 [ main::point1 ] 0: zp[2]:14 [ main::point2 ]
Uplift Scope [Point]
Uplift Scope []
Uplifting [getPoint] best 181 combination reg byte x [ getPoint::return_x#0 ] reg byte a [ getPoint::return_y#0 ] reg byte x [ getPoint::return_x#1 ] zp[1]:9 [ getPoint::return_y#1 ] zp[1]:2 [ getPoint::return_x#2 ] zp[1]:3 [ getPoint::return_y#2 ]
Limited combination testing to 100 combinations of 4096 possible.
Uplifting [main] best 163 combination reg byte x [ main::$0_x ] reg byte a [ main::$0_y ] reg byte x [ main::$1_x ] zp[1]:11 [ main::$1_y ] zp[2]:12 [ main::point1 ] zp[2]:14 [ main::point2 ]
Limited combination testing to 100 combinations of 256 possible.
Uplifting [Point] best 163 combination
Uplifting [] best 163 combination
Attempting to uplift remaining variables inzp[1]:9 [ getPoint::return_y#1 ]
Uplifting [getPoint] best 157 combination reg byte a [ getPoint::return_y#1 ]
Attempting to uplift remaining variables inzp[1]:11 [ main::$1_y ]
Uplifting [main] best 151 combination reg byte a [ main::$1_y ]
Attempting to uplift remaining variables inzp[1]:2 [ getPoint::return_x#2 ]
Uplifting [getPoint] best 139 combination reg byte x [ getPoint::return_x#2 ]
Attempting to uplift remaining variables inzp[1]:3 [ getPoint::return_y#2 ]
Uplifting [getPoint] best 127 combination reg byte a [ getPoint::return_y#2 ]
Allocated (was zp[2]:12) zp[2]:2 [ main::point1 ]
Allocated (was zp[2]:14) zp[2]:4 [ main::point2 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal struct with C-Standard behavior - call return value (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from___b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label point1 = 2
.label point2 = 4
// [5] call getPoint
// [24] phi from main to getPoint [phi:main->getPoint]
getPoint_from_main:
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuaa=vbuc1
lda #3
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuxx=vbuc1
ldx #2
jsr getPoint
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
jmp __b1
// main::@1
__b1:
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuxx
stx.z point1
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuaa
sta point1+OFFSET_STRUCT_POINT_Y
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
lda.z point1
sta SCREEN
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// [14] call getPoint
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
getPoint_from___b1:
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuaa=vbuc1
lda #5
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuxx=vbuc1
ldx #4
jsr getPoint
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
jmp __b2
// main::@2
__b2:
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
stx.z point2
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
sta point2+OFFSET_STRUCT_POINT_Y
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
lda.z point2
sta SCREEN+2
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
jmp __breturn
// main::@return
__breturn:
// [23] return
rts
}
// getPoint
getPoint: {
jmp __breturn
// getPoint::@return
__breturn:
// [25] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing instruction lda.z point1 with TXA
Replacing instruction lda.z point2 with TXA
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction getPoint_from_main:
Removing instruction __b1:
Removing instruction getPoint_from___b1:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
(label) getPoint::@return
(byte) getPoint::p_x
(byte) getPoint::p_y
(struct Point) getPoint::return
(byte) getPoint::return_x
(byte) getPoint::return_x#0 reg byte x 2.0
(byte) getPoint::return_x#1 reg byte x 2.0
(byte) getPoint::return_x#2 reg byte x 1.0
(byte) getPoint::return_y
(byte) getPoint::return_y#0 reg byte a 2.0
(byte) getPoint::return_y#1 reg byte a 2.0
(byte) getPoint::return_y#2 reg byte a 0.6666666666666666
(byte) getPoint::x
(byte) getPoint::y
(void()) main()
(struct Point~) main::$0
(byte~) main::$0_x reg byte x 2.0
(byte~) main::$0_y reg byte a 2.0
(struct Point~) main::$1
(byte~) main::$1_x reg byte x 2.0
(byte~) main::$1_y reg byte a 2.0
(label) main::@1
(label) main::@2
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
reg byte x [ getPoint::return_x#2 ]
reg byte a [ getPoint::return_y#2 ]
reg byte x [ getPoint::return_x#0 ]
reg byte a [ getPoint::return_y#0 ]
reg byte x [ main::$0_x ]
reg byte a [ main::$0_y ]
reg byte x [ getPoint::return_x#1 ]
reg byte a [ getPoint::return_y#1 ]
reg byte x [ main::$1_x ]
reg byte a [ main::$1_y ]
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]
FINAL ASSEMBLER
Score: 74
// File Comments
// Minimal struct with C-Standard behavior - call return value (not supported yet)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const OFFSET_STRUCT_POINT_Y = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label point1 = 2
.label point2 = 4
// getPoint(2, 3)
// [5] call getPoint
// [24] phi from main to getPoint [phi:main->getPoint]
// [24] phi (byte) getPoint::return_y#2 = (byte) 3 [phi:main->getPoint#0] -- vbuaa=vbuc1
lda #3
// [24] phi (byte) getPoint::return_x#2 = (byte) 2 [phi:main->getPoint#1] -- vbuxx=vbuc1
ldx #2
jsr getPoint
// getPoint(2, 3)
// [6] (byte) getPoint::return_x#0 ← (byte) getPoint::return_x#2
// [7] (byte) getPoint::return_y#0 ← (byte) getPoint::return_y#2
// main::@1
// [8] (byte~) main::$0_x ← (byte) getPoint::return_x#0
// [9] (byte~) main::$0_y ← (byte) getPoint::return_y#0
// point1 = getPoint(2, 3)
// [10] *((byte*)&(struct Point) main::point1) ← (byte~) main::$0_x -- _deref_pbuc1=vbuxx
stx.z point1
// [11] *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$0_y -- _deref_pbuc1=vbuaa
sta point1+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = point1.x
// [12] *((const byte*) SCREEN) ← *((byte*)&(struct Point) main::point1) -- _deref_pbuc1=_deref_pbuc2
txa
sta SCREEN
// SCREEN[1] = point1.y
// [13] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) main::point1+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point1+OFFSET_STRUCT_POINT_Y
sta SCREEN+1
// getPoint(4, 5)
// [14] call getPoint
// [24] phi from main::@1 to getPoint [phi:main::@1->getPoint]
// [24] phi (byte) getPoint::return_y#2 = (byte) 5 [phi:main::@1->getPoint#0] -- vbuaa=vbuc1
lda #5
// [24] phi (byte) getPoint::return_x#2 = (byte) 4 [phi:main::@1->getPoint#1] -- vbuxx=vbuc1
ldx #4
jsr getPoint
// getPoint(4, 5)
// [15] (byte) getPoint::return_x#1 ← (byte) getPoint::return_x#2
// [16] (byte) getPoint::return_y#1 ← (byte) getPoint::return_y#2
// main::@2
// [17] (byte~) main::$1_x ← (byte) getPoint::return_x#1
// [18] (byte~) main::$1_y ← (byte) getPoint::return_y#1
// point2 = getPoint(4, 5)
// [19] *((byte*)&(struct Point) main::point2) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx
stx.z point2
// [20] *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa
sta point2+OFFSET_STRUCT_POINT_Y
// SCREEN[2] = point2.x
// [21] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) main::point2) -- _deref_pbuc1=_deref_pbuc2
txa
sta SCREEN+2
// SCREEN[3] = point2.y
// [22] *((const byte*) SCREEN+(byte) 3) ← *((byte*)&(struct Point) main::point2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2
lda point2+OFFSET_STRUCT_POINT_Y
sta SCREEN+3
// main::@return
// }
// [23] return
rts
}
// getPoint
getPoint: {
// getPoint::@return
// [25] return
rts
}
// File Data

@ -0,0 +1,47 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(const byte*) SCREEN = (byte*) 1024
(struct Point()) getPoint((byte) getPoint::x , (byte) getPoint::y)
(label) getPoint::@return
(byte) getPoint::p_x
(byte) getPoint::p_y
(struct Point) getPoint::return
(byte) getPoint::return_x
(byte) getPoint::return_x#0 reg byte x 2.0
(byte) getPoint::return_x#1 reg byte x 2.0
(byte) getPoint::return_x#2 reg byte x 1.0
(byte) getPoint::return_y
(byte) getPoint::return_y#0 reg byte a 2.0
(byte) getPoint::return_y#1 reg byte a 2.0
(byte) getPoint::return_y#2 reg byte a 0.6666666666666666
(byte) getPoint::x
(byte) getPoint::y
(void()) main()
(struct Point~) main::$0
(byte~) main::$0_x reg byte x 2.0
(byte~) main::$0_y reg byte a 2.0
(struct Point~) main::$1
(byte~) main::$1_x reg byte x 2.0
(byte~) main::$1_y reg byte a 2.0
(label) main::@1
(label) main::@2
(label) main::@return
(struct Point) main::point1 loadstore zp[2]:2
(struct Point) main::point2 loadstore zp[2]:4
reg byte x [ getPoint::return_x#2 ]
reg byte a [ getPoint::return_y#2 ]
reg byte x [ getPoint::return_x#0 ]
reg byte a [ getPoint::return_y#0 ]
reg byte x [ main::$0_x ]
reg byte a [ main::$0_y ]
reg byte x [ getPoint::return_x#1 ]
reg byte a [ getPoint::return_y#1 ]
reg byte x [ main::$1_x ]
reg byte a [ main::$1_y ]
zp[2]:2 [ main::point1 ]
zp[2]:4 [ main::point2 ]

@ -4,6 +4,9 @@ Converted struct value to member variables (struct Point) main::p
Created struct value member variable (struct Point) main::c_center
Created struct value member variable (byte) main::c_radius
Converted struct value to member variables (struct Circle) main::c
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
Adding struct value list initializer (struct Point) main::c_center ← (struct Point) main::p
@ -11,9 +14,6 @@ Adding struct value list initializer (byte) main::c_radius ← (byte)(number) 5
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x
Adding struct value member variable copy (byte) main::c_center_y ← (byte) main::p_y
Replacing struct member reference (struct Point) main::c_center.x with member unwinding reference (byte) main::c_center_x

@ -1,6 +1,18 @@
Created struct value member variable (struct Circle) main::t_c1
Created struct value member variable (struct Circle) main::t_c2
Converted struct value to member variables (struct TwoCircles) main::t
Created struct value member variable (struct Point) main::t_c1_center
Created struct value member variable (byte) main::t_c1_radius
Converted struct value to member variables (struct Circle) main::t_c1
Created struct value member variable (struct Point) main::t_c2_center
Created struct value member variable (byte) main::t_c2_radius
Converted struct value to member variables (struct Circle) main::t_c2
Created struct value member variable (byte) main::t_c1_center_x
Created struct value member variable (byte) main::t_c1_center_y
Converted struct value to member variables (struct Point) main::t_c1_center
Created struct value member variable (byte) main::t_c2_center_x
Created struct value member variable (byte) main::t_c2_center_y
Converted struct value to member variables (struct Point) main::t_c2_center
Adding struct value member variable copy (struct Circle) main::t_c1 ← { center: { x: (byte)(number) 1, y: (byte)(number) 2 }, radius: (byte)(number) 3 }
Adding struct value member variable copy (struct Circle) main::t_c2 ← { center: { x: (byte)(number) 4, y: (byte)(number) 5 }, radius: (byte)(number) 6 }
Replacing struct member reference (struct TwoCircles) main::t.c1 with member unwinding reference (struct Circle) main::t_c1
@ -9,12 +21,6 @@ Replacing struct member reference (struct TwoCircles) main::t.c1 with member unw
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
Replacing struct member reference (struct TwoCircles) main::t.c2 with member unwinding reference (struct Circle) main::t_c2
Created struct value member variable (struct Point) main::t_c1_center
Created struct value member variable (byte) main::t_c1_radius
Converted struct value to member variables (struct Circle) main::t_c1
Created struct value member variable (struct Point) main::t_c2_center
Created struct value member variable (byte) main::t_c2_radius
Converted struct value to member variables (struct Circle) main::t_c2
Adding struct value member variable copy (struct Point) main::t_c1_center ← { x: (byte)(number) 1, y: (byte)(number) 2 }
Adding struct value member variable copy (byte) main::t_c1_radius ← (byte)(number) 3
Adding struct value member variable copy (struct Point) main::t_c2_center ← { x: (byte)(number) 4, y: (byte)(number) 5 }
@ -25,12 +31,6 @@ Replacing struct member reference (struct Circle) main::t_c1.radius with member
Replacing struct member reference (struct Circle) main::t_c2.center with member unwinding reference (struct Point) main::t_c2_center
Replacing struct member reference (struct Circle) main::t_c2.center with member unwinding reference (struct Point) main::t_c2_center
Replacing struct member reference (struct Circle) main::t_c2.radius with member unwinding reference (byte) main::t_c2_radius
Created struct value member variable (byte) main::t_c1_center_x
Created struct value member variable (byte) main::t_c1_center_y
Converted struct value to member variables (struct Point) main::t_c1_center
Created struct value member variable (byte) main::t_c2_center_x
Created struct value member variable (byte) main::t_c2_center_y
Converted struct value to member variables (struct Point) main::t_c2_center
Adding struct value member variable copy (byte) main::t_c1_center_x ← (byte)(number) 1
Adding struct value member variable copy (byte) main::t_c1_center_y ← (byte)(number) 2
Adding struct value member variable copy (byte) main::t_c2_center_x ← (byte)(number) 4

@ -7,6 +7,9 @@ Converted struct value to member variables (struct Circle) main::c
Created struct value member variable (byte) main::point_x
Created struct value member variable (byte) main::point_y
Converted struct value to member variables (struct Point) main::point
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
Adding struct value list initializer (struct Point) main::c_center ← (struct Point) main::p
@ -15,9 +18,6 @@ Replacing struct member reference (struct Circle) main::c.center with member unw
Replacing struct member reference (struct Point) main::point.x with member unwinding reference (byte) main::point_x
Replacing struct member reference (struct Point) main::point.y with member unwinding reference (byte) main::point_y
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x
Adding struct value member variable copy (byte) main::c_center_y ← (byte) main::p_y
Adding struct value member variable copy (byte) main::point_x ← (byte) main::c_center_x

@ -4,6 +4,9 @@ Converted struct value to member variables (struct Point) main::p
Created struct value member variable (struct Point) main::c_center
Created struct value member variable (byte) main::c_radius
Converted struct value to member variables (struct Circle) main::c
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) $a
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) $a
Adding struct value member variable default initializer (struct Point) main::c_center ← {}
@ -13,9 +16,6 @@ Replacing struct member reference (struct Circle) main::c.radius with member unw
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
Replacing struct member reference (struct Circle) main::c.center with member unwinding reference (struct Point) main::c_center
Replacing struct member reference (struct Circle) main::c.radius with member unwinding reference (byte) main::c_radius
Created struct value member variable (byte) main::c_center_x
Created struct value member variable (byte) main::c_center_y
Converted struct value to member variables (struct Point) main::c_center
Adding struct value member variable default initializer (byte) main::c_center_x ← (byte) 0
Adding struct value member variable default initializer (byte) main::c_center_y ← (byte) 0
Adding struct value member variable copy (byte) main::c_center_x ← (byte) main::p_x

@ -5,13 +5,12 @@
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
.label q = p
.label p = 2
lda #2
sta.z p_x
sta.z p
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
lda.z q
sta SCREEN
lda q+OFFSET_STRUCT_POINT_Y

@ -10,8 +10,8 @@
(void()) main()
main: scope:[main] from @1
[4] (byte) main::p_x ← (byte) 2
[5] (byte) main::p_y ← (byte) 3
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q)
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return

@ -1,12 +1,10 @@
Setting inferred volatile on symbol affected by address-of (struct Point*) main::q ← &(struct Point) main::p
Created struct value member variable (byte) main::p_x
Created struct value member variable (byte) main::p_y
Converted struct value to member variables (struct Point) main::p
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) 2
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$0) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 3
Rewriting struct pointer member access *((struct Point*) main::q).x
Rewriting struct pointer member access *((struct Point*) main::q).y
Identified constant variable (struct Point*) main::q
Adding versioned struct unwinding for (struct Point) main::p
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -14,13 +12,15 @@ CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from @1
(byte) main::p_x ← (byte)(number) 2
(byte) main::p_y ← (byte)(number) 3
(struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
(byte*~) main::$0 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0)
(byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$1)
(byte*~) main::$0 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$0) ← (byte)(number) 2
(byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$1) ← (byte)(number) 3
(struct Point) main::p ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
(byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$2)
(byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$3)
to:main::@return
main::@return: scope:[main] from main
return
@ -44,15 +44,15 @@ SYMBOL TABLE SSA
(void()) main()
(byte*~) main::$0
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(struct Point) main::p loadstore
(byte) main::p_x loadstore
(byte) main::p_y loadstore
(const struct Point*) main::q = &(struct Point) main::p
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$1)
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$2)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$3)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 2
@ -63,22 +63,27 @@ Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Rewriting struct address-of to first member &(struct Point) main::p
Successful SSA optimization PassNStructAddressOfRewriting
Constant right-side identified [3] (byte*~) main::$0 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
Removing C-classic struct-unwound assignment [4] (struct Point) main::p ← struct-unwound {*((byte*~) main::$0), *((byte*~) main::$1)}
Constant right-side identified [0] (byte*~) main::$0 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$0 = (byte*)main::q+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$0 = (byte*)&main::p+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$1 = (byte*)&main::p+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$2 = (byte*)main::q+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$3 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::p in
Simplifying expression containing zero (byte*)main::q in
Simplifying expression containing zero main::SCREEN in [4] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$0)
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$2)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct Point) main::p and assignment [2] (struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$0 = (byte*)(const struct Point*) main::q
Constant inlined main::$3 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$1 = (byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$2 = (byte*)(const struct Point*) main::q
Constant inlined main::$0 = (byte*)&(struct Point) main::p
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::SCREEN+1)
Successful SSA optimization Pass2ConstantAdditionElimination
@ -109,8 +114,8 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from @1
[4] (byte) main::p_x ← (byte) 2
[5] (byte) main::p_y ← (byte) 3
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q)
[7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y)
to:main::@return
@ -123,17 +128,13 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) main::p_x loadstore 20.0
(byte) main::p_y loadstore 20.0
(struct Point) main::p loadstore
Initial phi equivalence classes
Added variable main::p_x to live range equivalence class [ main::p_x ]
Added variable main::p_y to live range equivalence class [ main::p_y ]
Added variable main::p to live range equivalence class [ main::p ]
Complete equivalence classes
[ main::p_x ]
[ main::p_y ]
Allocated zp[1]:2 [ main::p_x ]
Allocated zp[1]:3 [ main::p_y ]
[ main::p ]
Allocated zp[2]:2 [ main::p ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -162,15 +163,14 @@ __bend:
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
.label q = p
.label p = 2
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
lda.z q
sta SCREEN
@ -186,25 +186,20 @@ main: {
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] (byte) main::p_x ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] (byte) main::p_y ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] *((byte*)&(struct Point) main::p) ← (byte) 2 [ main::p ] ( main:2 [ main::p ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::p_x ] : zp[1]:2 ,
Potential registers zp[1]:3 [ main::p_y ] : zp[1]:3 ,
Potential registers zp[2]:2 [ main::p ] : zp[2]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp[1]:2 [ main::p_x ] 20: zp[1]:3 [ main::p_y ]
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:2 [ main::p ]
Uplift Scope []
Uplifting [main] best 46 combination zp[1]:2 [ main::p_x ] zp[1]:3 [ main::p_y ]
Uplifting [Point] best 46 combination
Uplifting [] best 46 combination
Attempting to uplift remaining variables inzp[1]:2 [ main::p_x ]
Uplifting [main] best 46 combination zp[1]:2 [ main::p_x ]
Attempting to uplift remaining variables inzp[1]:3 [ main::p_y ]
Uplifting [main] best 46 combination zp[1]:3 [ main::p_y ]
Uplifting [Point] best 47 combination
Uplifting [main] best 47 combination zp[2]:2 [ main::p ]
Uplifting [] best 47 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -232,15 +227,14 @@ __bend:
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
.label q = p
.label p = 2
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
lda.z q
sta SCREEN
@ -284,16 +278,14 @@ FINAL SYMBOL TABLE
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::p_x loadstore zp[1]:2 20.0
(byte) main::p_y loadstore zp[1]:3 20.0
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
(struct Point) main::p loadstore zp[2]:2
(const struct Point*) main::q = &(struct Point) main::p
zp[1]:2 [ main::p_x ]
zp[1]:3 [ main::p_y ]
zp[2]:2 [ main::p ]
FINAL ASSEMBLER
Score: 31
Score: 32
// File Comments
// Minimal struct - using address-of
@ -312,16 +304,15 @@ Score: 31
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
.label q = p
.label p = 2
// p = { 2, 3 }
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// SCREEN[0] = q->x
// [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2
lda.z q

@ -7,9 +7,7 @@
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::p_x loadstore zp[1]:2 20.0
(byte) main::p_y loadstore zp[1]:3 20.0
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
(struct Point) main::p loadstore zp[2]:2
(const struct Point*) main::q = &(struct Point) main::p
zp[1]:2 [ main::p_x ]
zp[1]:3 [ main::p_y ]
zp[2]:2 [ main::p ]

@ -5,13 +5,12 @@
.const OFFSET_STRUCT_POINT_Y = 1
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
.label q = p
.label p = 2
lda #2
sta.z p_x
sta.z p
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
jsr set
lda.z q
sta SCREEN

@ -10,8 +10,8 @@
(void()) main()
main: scope:[main] from @1
[4] (byte) main::p_x ← (byte) 2
[5] (byte) main::p_y ← (byte) 3
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] call set
to:main::@1
main::@1: scope:[main] from main

@ -1,15 +1,13 @@
Setting inferred volatile on symbol affected by address-of (struct Point*) main::q ← &(struct Point) main::p
Created struct value member variable (byte) main::p_x
Created struct value member variable (byte) main::p_y
Converted struct value to member variables (struct Point) main::p
Adding struct value member variable copy (byte) main::p_x ← (byte)(number) 2
Adding struct value member variable copy (byte) main::p_y ← (byte)(number) 3
Adding struct value member variable copy *((byte*~) main::$1) ← (byte)(number) 2
Adding struct value member variable copy *((byte*~) main::$2) ← (byte)(number) 3
Rewriting struct pointer member access *((struct Point*) main::q).x
Rewriting struct pointer member access *((struct Point*) main::q).y
Rewriting struct pointer member access *((struct Point*) set::ptr).x
Rewriting struct pointer member access *((struct Point*) set::ptr).y
Identified constant variable (struct Point*) main::q
Culled Empty Block (label) @1
Adding versioned struct unwinding for (struct Point) main::p
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -17,17 +15,19 @@ CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from @2
(byte) main::p_x ← (byte)(number) 2
(byte) main::p_y ← (byte)(number) 3
(struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
(byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
*((byte*~) main::$1) ← (byte)(number) 2
(byte*~) main::$2 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*~) main::$2) ← (byte)(number) 3
(struct Point) main::p ← struct-unwound {*((byte*~) main::$1), *((byte*~) main::$2)}
(struct Point*) set::ptr#0 ← (const struct Point*) main::q
call set
to:main::@1
main::@1: scope:[main] from main
(byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$1)
(byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$2)
(byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
*((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$3)
(byte*~) main::$4 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
*((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$4)
to:main::@return
main::@return: scope:[main] from main::@1
return
@ -63,12 +63,12 @@ SYMBOL TABLE SSA
(void()) main()
(byte*~) main::$1
(byte*~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(label) main::@1
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(struct Point) main::p loadstore
(byte) main::p_x loadstore
(byte) main::p_y loadstore
(const struct Point*) main::q = &(struct Point) main::p
(void()) set((struct Point*) set::ptr)
(byte*~) set::$0
@ -78,8 +78,8 @@ SYMBOL TABLE SSA
(struct Point*) set::ptr#0
(struct Point*) set::ptr#1
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$1)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$2)
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$3)
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$4)
Adding number conversion cast (unumber) 4 in *((byte*~) set::$0) ← (number) 4
Adding number conversion cast (unumber) 5 in *((byte*~) set::$1) ← (number) 5
Successful SSA optimization PassNAddNumberTypeConversions
@ -101,34 +101,39 @@ Finalized unsigned number type (byte) 5
Successful SSA optimization PassNFinalizeNumberTypeConversions
Identical Phi Values (struct Point*) set::ptr#1 (struct Point*) set::ptr#0
Successful SSA optimization Pass2IdenticalPhiElimination
Rewriting struct address-of to first member &(struct Point) main::p
Successful SSA optimization PassNStructAddressOfRewriting
Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [7] (byte*~) main::$2 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
Removing C-classic struct-unwound assignment [4] (struct Point) main::p ← struct-unwound {*((byte*~) main::$1), *((byte*~) main::$2)}
Constant right-side identified [0] (byte*~) main::$1 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [2] (byte*~) main::$2 ← (byte*)&(struct Point) main::p + (const byte) OFFSET_STRUCT_POINT_Y
Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_X
Constant right-side identified [9] (byte*~) main::$4 ← (byte*)(const struct Point*) main::q + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$1 = (byte*)&main::p+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$2 = (byte*)&main::p+OFFSET_STRUCT_POINT_Y
Constant (const struct Point*) set::ptr#0 = main::q
Constant (const byte*) main::$1 = (byte*)main::q+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$2 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
Constant (const byte*) main::$3 = (byte*)main::q+OFFSET_STRUCT_POINT_X
Constant (const byte*) main::$4 = (byte*)main::q+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)set::ptr#0 in [11] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)set::ptr#0 in [13] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)set::ptr#0 in [13] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)set::ptr#0 in [15] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [12] *((byte*~) set::$0) ← (byte) 4 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [14] *((byte*~) set::$1) ← (byte) 5 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_Y)
Converting *(pointer+n) to pointer[n] [14] *((byte*~) set::$0) ← (byte) 4 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [16] *((byte*~) set::$1) ← (byte) 5 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (byte*)&main::p in
Simplifying expression containing zero (byte*)main::q in
Simplifying expression containing zero main::SCREEN in [6] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$1)
Simplifying expression containing zero (byte*)set::ptr#0 in [11] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)set::ptr#0 in [12] *((byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Simplifying expression containing zero main::SCREEN in [8] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$3)
Simplifying expression containing zero (byte*)set::ptr#0 in [13] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)set::ptr#0 in [14] *((byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct Point) main::p and assignment [2] (struct Point) main::p ← struct-unwound {(byte) main::p_x, (byte) main::p_y}
Eliminating unused variable (byte*~) set::$0 and assignment [7] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0
Eliminating unused variable (byte*~) set::$1 and assignment [9] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (byte*~) set::$0 and assignment [6] (byte*~) set::$0 ← (byte*)(const struct Point*) set::ptr#0
Eliminating unused variable (byte*~) set::$1 and assignment [8] (byte*~) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined set::ptr#0 = (const struct Point*) main::q
Constant inlined main::$1 = (byte*)(const struct Point*) main::q
Constant inlined main::$2 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$3 = (byte*)(const struct Point*) main::q
Constant inlined main::$4 = (byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined main::$1 = (byte*)&(struct Point) main::p
Constant inlined main::$2 = (byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::SCREEN+1)
Consolidated array index constant in *((byte*)main::q+OFFSET_STRUCT_POINT_Y)
@ -162,8 +167,8 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from @1
[4] (byte) main::p_x ← (byte) 2
[5] (byte) main::p_y ← (byte) 3
[4] *((byte*)&(struct Point) main::p) ← (byte) 2
[5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3
[6] call set
to:main::@1
main::@1: scope:[main] from main
@ -188,19 +193,15 @@ VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(void()) main()
(byte) main::p_x loadstore 20.0
(byte) main::p_y loadstore 20.0
(struct Point) main::p loadstore
(void()) set((struct Point*) set::ptr)
(struct Point*) set::ptr
Initial phi equivalence classes
Added variable main::p_x to live range equivalence class [ main::p_x ]
Added variable main::p_y to live range equivalence class [ main::p_y ]
Added variable main::p to live range equivalence class [ main::p ]
Complete equivalence classes
[ main::p_x ]
[ main::p_y ]
Allocated zp[1]:2 [ main::p_x ]
Allocated zp[1]:3 [ main::p_y ]
[ main::p ]
Allocated zp[2]:2 [ main::p ]
INITIAL ASM
Target platform is c64basic / MOS6502X
@ -229,15 +230,14 @@ __bend:
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
.label q = p
.label p = 2
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// [6] call set
jsr set
jmp __b1
@ -272,29 +272,24 @@ set: {
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] (byte) main::p_x ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] (byte) main::p_y ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [4] *((byte*)&(struct Point) main::p) ← (byte) 2 [ main::p ] ( main:2 [ main::p ] ) always clobbers reg byte a
Statement [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [8] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] *((byte*)(const struct Point*) main::q) ← (byte) 4 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a
Statement [11] *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::p_x ] : zp[1]:2 ,
Potential registers zp[1]:3 [ main::p_y ] : zp[1]:3 ,
Potential registers zp[2]:2 [ main::p ] : zp[2]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp[1]:2 [ main::p_x ] 20: zp[1]:3 [ main::p_y ]
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:2 [ main::p ]
Uplift Scope [set]
Uplift Scope []
Uplifting [main] best 75 combination zp[1]:2 [ main::p_x ] zp[1]:3 [ main::p_y ]
Uplifting [Point] best 75 combination
Uplifting [set] best 75 combination
Uplifting [] best 75 combination
Attempting to uplift remaining variables inzp[1]:2 [ main::p_x ]
Uplifting [main] best 75 combination zp[1]:2 [ main::p_x ]
Attempting to uplift remaining variables inzp[1]:3 [ main::p_y ]
Uplifting [main] best 75 combination zp[1]:3 [ main::p_y ]
Uplifting [Point] best 76 combination
Uplifting [main] best 76 combination zp[2]:2 [ main::p ]
Uplifting [set] best 76 combination
Uplifting [] best 76 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -322,15 +317,14 @@ __bend:
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
.label q = p
.label p = 2
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// [6] call set
jsr set
jmp __b1
@ -398,19 +392,17 @@ FINAL SYMBOL TABLE
(label) main::@1
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::p_x loadstore zp[1]:2 20.0
(byte) main::p_y loadstore zp[1]:3 20.0
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
(struct Point) main::p loadstore zp[2]:2
(const struct Point*) main::q = &(struct Point) main::p
(void()) set((struct Point*) set::ptr)
(label) set::@return
(struct Point*) set::ptr
zp[1]:2 [ main::p_x ]
zp[1]:3 [ main::p_y ]
zp[2]:2 [ main::p ]
FINAL ASSEMBLER
Score: 54
Score: 55
// File Comments
// Minimal struct - using address-of and passing it to a function
@ -429,16 +421,15 @@ Score: 54
// main
main: {
.label SCREEN = $400
.label q = p_x
.label p_x = 2
.label p_y = 3
.label q = p
.label p = 2
// p = { 2, 3 }
// [4] (byte) main::p_x ← (byte) 2 -- vbuz1=vbuc1
// [4] *((byte*)&(struct Point) main::p) ← (byte) 2 -- _deref_pbuc1=vbuc2
lda #2
sta.z p_x
// [5] (byte) main::p_y ← (byte) 3 -- vbuz1=vbuc1
sta.z p
// [5] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 -- _deref_pbuc1=vbuc2
lda #3
sta.z p_y
sta p+OFFSET_STRUCT_POINT_Y
// set(q)
// [6] call set
jsr set

@ -8,12 +8,10 @@
(label) main::@1
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(byte) main::p_x loadstore zp[1]:2 20.0
(byte) main::p_y loadstore zp[1]:3 20.0
(const struct Point*) main::q = (struct Point*)&(byte) main::p_x
(struct Point) main::p loadstore zp[2]:2
(const struct Point*) main::q = &(struct Point) main::p
(void()) set((struct Point*) set::ptr)
(label) set::@return
(struct Point*) set::ptr
zp[1]:2 [ main::p_x ]
zp[1]:3 [ main::p_y ]
zp[2]:2 [ main::p ]