1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-07-03 20:29:34 +00:00

Implemented struct value member-centric optimization (converting simple struct variables to each member.)

This commit is contained in:
jespergravgaard 2019-06-07 00:14:42 +02:00
parent 0bebae430d
commit c995a1bca1
16 changed files with 797 additions and 1000 deletions

View File

@ -165,6 +165,8 @@ public class Compiler {
new PassNTypeInference(program).execute();
new PassNTypeIdSimplification(program).execute();
new Pass1UnwindStructValues(program).execute();
if(getLog().isVerbosePass1CreateSsa()) {
getLog().append("SYMBOLS");
getLog().append(program.getScope().toString(program, null));

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.model.types;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Variable;
@ -32,6 +33,10 @@ public class SymbolTypeStruct implements SymbolType {
return name;
}
public StructDefinition getStructDefinition(ProgramScope programScope) {
return programScope.getStructDefinition(name);
}
@Override
public int getSizeBytes() {
return sizeBytes;

View File

@ -125,8 +125,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
try {
ConstantString.Encoding encoding = ConstantString.Encoding.valueOf(ctx.NAME().getText().toUpperCase());
this.currentEncoding = encoding;
} catch( IllegalArgumentException e) {
throw new CompileError("Unknown string encoding "+ctx.NAME().getText(), new StatementSource(ctx));
} catch(IllegalArgumentException e) {
throw new CompileError("Unknown string encoding " + ctx.NAME().getText(), new StatementSource(ctx));
}
return null;
}
@ -518,9 +518,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
// Add comments to constant
lValue.setComments(ensureUnusedComments(comments));
}
if(type instanceof SymbolTypeStruct) {
lValue.setDeclaredVolatile(true);
}
//if(type instanceof SymbolTypeStruct) {
// lValue.setDeclaredVolatile(true);
//}
KickCParser.ExprContext initializer = ctx.expr();
if(declVarStructMember) {
if(initializer != null) {
@ -530,40 +530,53 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
if(initializer != null) {
addInitialAssignment(initializer, lValue, comments);
} else {
if(type instanceof SymbolTypeIntegerFixed) {
// Add an zero value initializer
ConstantInteger zero = new ConstantInteger(0L, type);
Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments));
sequence.addStatement(stmt);
} else if(type instanceof SymbolTypeArray) {
// Add an zero-array initializer
SymbolTypeArray typeArray = (SymbolTypeArray) type;
RValue size = typeArray.getSize();
if(size == null) {
throw new CompileError("Error! Array has no declared size. " + lValue.toString(program), new StatementSource(ctx));
}
Statement stmt = new StatementAssignment(lValue.getRef(), new ArrayFilled(typeArray.getElementType(), size), new StatementSource(ctx), ensureUnusedComments(comments));
sequence.addStatement(stmt);
} else if(type instanceof SymbolTypePointer) {
// Add an zero value initializer
SymbolTypePointer typePointer = (SymbolTypePointer) type;
ConstantValue zero = new ConstantPointer(0L, typePointer.getElementType());
Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments));
sequence.addStatement(stmt);
} else if(type instanceof SymbolTypeStruct) {
// Add an zero-struct initializer
SymbolTypeStruct typeStruct = (SymbolTypeStruct) type;
Statement stmt = new StatementAssignment(lValue.getRef(), new StructZero(typeStruct), new StatementSource(ctx), ensureUnusedComments(comments));
sequence.addStatement(stmt);
} else {
throw new CompileError("Default initializer not implemented for type " + type.getTypeName(), new StatementSource(ctx));
}
Statement initStmt;
StatementSource statementSource = new StatementSource(ctx);
initStmt = createDefaultInitializationStatement(lValue.getRef(), type, statementSource, ensureUnusedComments(comments));
sequence.addStatement(initStmt);
}
}
return null;
}
/**
* Create a statement that initializes a variable with the default (zero) value. The statement has to be added to the program by the caller.
* @param lValue The variable to initialize
* @param type The type of the variable
* @param statementSource The source line
* @param comments Any comments to add to the output
* @return The new statement
*/
public static Statement createDefaultInitializationStatement(VariableRef varRef, SymbolType type, StatementSource statementSource, List<Comment> comments) {
Statement initStmt;
if(type instanceof SymbolTypeIntegerFixed) {
// Add an zero value initializer
ConstantInteger zero = new ConstantInteger(0L, type);
initStmt = new StatementAssignment(varRef, zero, statementSource, comments);
} else if(type instanceof SymbolTypeArray) {
// Add an zero-array initializer
SymbolTypeArray typeArray = (SymbolTypeArray) type;
RValue size = typeArray.getSize();
if(size == null) {
throw new CompileError("Error! Array has no declared size. " + varRef.toString(), statementSource);
}
initStmt = new StatementAssignment(varRef, new ArrayFilled(typeArray.getElementType(), size), statementSource, comments);
} else if(type instanceof SymbolTypePointer) {
// Add an zero value initializer
SymbolTypePointer typePointer = (SymbolTypePointer) type;
ConstantValue zero = new ConstantPointer(0L, typePointer.getElementType());
initStmt = new StatementAssignment(varRef, zero, statementSource, comments);
} else if(type instanceof SymbolTypeStruct) {
// Add an zero-struct initializer
SymbolTypeStruct typeStruct = (SymbolTypeStruct) type;
initStmt = new StatementAssignment(varRef, new StructZero(typeStruct), statementSource, comments);
} else {
throw new CompileError("Default initializer not implemented for type " + type.getTypeName(), statementSource);
}
return initStmt;
}
/**
* Add declared directives to an lValue (typically a variable).
*

View File

@ -0,0 +1,138 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
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.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.StructMemberRef;
import dk.camelot64.kickc.model.values.StructZero;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.LinkedHashMap;
import java.util.ListIterator;
import java.util.Map;
/** Convert all struct values that are not used as pointers (address-of used or declared volatile) */
public class Pass1UnwindStructValues extends Pass1Base {
public Pass1UnwindStructValues(Program program) {
super(program);
}
@Override
public boolean step() {
boolean modified = false;
// Maps struct variable to map from member name to the variable
Map<VariableRef, Map<String, VariableRef>> structMemberVariableMap = new LinkedHashMap<>();
// Iterate through all scopes generating member-variables for each struct
for(Variable variable : getScope().getAllVariables(true)) {
if(variable.getType() instanceof SymbolTypeStruct) {
if(!variable.isDeclaredVolatile() && !Pass2ConstantIdentification.isAddressOfUsed(variable.getRef(), getProgram())) {
// A non-volatile struct variable
Scope scope = variable.getScope();
StructDefinition structDefinition = ((SymbolTypeStruct) variable.getType()).getStructDefinition(getProgram().getScope());
LinkedHashMap<String, VariableRef> memberVariables = new LinkedHashMap<>();
for(Variable member : structDefinition.getAllVariables(false)) {
Variable memberVariable;
if(variable.getRef().isIntermediate()) {
memberVariable = scope.add(new VariableIntermediate(scope.allocateIntermediateVariableName() + "_" + member.getLocalName(), scope, member.getType()));
} else {
memberVariable = scope.addVariable(variable.getLocalName() + "_" + member.getLocalName(), member.getType());
}
memberVariables.put(member.getLocalName(), memberVariable.getRef());
getLog().append("Created struct value member variable " + memberVariable.toString(getProgram()));
}
structMemberVariableMap.put(variable.getRef(), memberVariables);
getLog().append("Converted struct value to member variables " + variable.toString(getProgram()));
}
}
}
// Unwind all references to full 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.getlValue() instanceof VariableRef) {
Variable assignedVar = getScope().getVariable((VariableRef) assignment.getlValue());
if(assignedVar.getType() instanceof SymbolTypeStruct) {
// Assigning a struct!
if(assignment.getOperator() == null && assignment.getrValue2() instanceof StructZero) {
// Initializing a struct - unwind to assigning zero to each member!
Map<String, VariableRef> memberVariables = structMemberVariableMap.get(assignedVar.getRef());
if(memberVariables != null) {
stmtIt.previous();
for(String memberName : memberVariables.keySet()) {
VariableRef memberVarRef = memberVariables.get(memberName);
Variable memberVar = getScope().getVariable(memberVarRef);
Statement initStmt = Pass0GenerateStatementSequence.createDefaultInitializationStatement(memberVarRef, memberVar.getType(), statement.getSource(), Comment.NO_COMMENTS);
stmtIt.add(initStmt);
getLog().append("Adding struct value member variable default initializer " + initStmt.toString(getProgram(), false));
}
stmtIt.next();
stmtIt.remove();
}
} else if(assignment.getOperator() == null && assignment.getrValue2() instanceof VariableRef) {
Variable sourceVar = getScope().getVariable((VariableRef) assignment.getrValue2());
if(sourceVar.getType().equals(assignedVar.getType())) {
// Copying a struct - unwind to assigning each member!
Map<String, VariableRef> assignedMemberVariables = structMemberVariableMap.get(assignedVar.getRef());
Map<String, VariableRef> sourceMemberVariables = structMemberVariableMap.get(sourceVar.getRef());
if(assignedMemberVariables != null && sourceMemberVariables!=null) {
stmtIt.previous();
for(String memberName : assignedMemberVariables.keySet()) {
VariableRef assignedMemberVarRef = assignedMemberVariables.get(memberName);
VariableRef sourceMemberVarRef = sourceMemberVariables.get(memberName);
Statement copyStmt = new StatementAssignment(assignedMemberVarRef, sourceMemberVarRef, statement.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt);
getLog().append("Adding struct value member variable copy " + copyStmt.toString(getProgram(), false));
}
stmtIt.next();
stmtIt.remove();
}
} else {
throw new RuntimeException("Struct assignment not implemented yet " + statement.toString(getProgram(), false));
}
}
}
}
}
}
}
// Change all usages of members in statements
ProgramValueIterator.execute(
getProgram(), (programValue,currentStmt,stmtIt,currentBlock)->
{
if(programValue.get() instanceof StructMemberRef) {
StructMemberRef structMemberRef = (StructMemberRef) programValue.get();
if(structMemberRef.getStruct() instanceof VariableRef) {
Variable structVariable = getScope().getVariable((VariableRef) structMemberRef.getStruct());
Map<String, VariableRef> memberVariables = structMemberVariableMap.get(structVariable.getRef());
if(memberVariables != null) {
VariableRef structMemberVariable = memberVariables.get(structMemberRef.getMemberName());
getLog().append("Replacing struct member reference " + structMemberRef.toString(getProgram()) + " with member variable reference " + structMemberVariable.toString(getProgram()));
programValue.set(structMemberVariable);
}
}
}
});
return modified;
}
}

View File

@ -36,6 +36,36 @@ public class TestPrograms {
}
@Test
public void testStruct5() throws IOException, URISyntaxException {
compileAndCompare("struct-5", log());
}
@Test
public void testStruct4() throws IOException, URISyntaxException {
compileAndCompare("struct-4", log());
}
@Test
public void testStruct3() throws IOException, URISyntaxException {
compileAndCompare("struct-3", log());
}
@Test
public void testStruct2() throws IOException, URISyntaxException {
compileAndCompare("struct-2", log());
}
@Test
public void testStruct1() throws IOException, URISyntaxException {
compileAndCompare("struct-1", log());
}
@Test
public void testStruct0() throws IOException, URISyntaxException {
compileAndCompare("struct-0", log());
}
@Test
public void testSequenceLocality1() throws IOException, URISyntaxException {
compileAndCompare("sequence-locality-1");
@ -115,36 +145,6 @@ public class TestPrograms {
compileAndCompare("signed-word-minus-byte-2");
}
@Test
public void testStruct5() throws IOException, URISyntaxException {
compileAndCompare("struct-5", log().verboseParse().verboseCreateSsa().verboseStatementSequence());
}
@Test
public void testStruct4() throws IOException, URISyntaxException {
compileAndCompare("struct-4", log().verboseParse().verboseCreateSsa().verboseStatementSequence());
}
@Test
public void testStruct3() throws IOException, URISyntaxException {
compileAndCompare("struct-3");
}
@Test
public void testStruct2() throws IOException, URISyntaxException {
compileAndCompare("struct-2");
}
@Test
public void testStruct1() throws IOException, URISyntaxException {
compileAndCompare("struct-1");
}
@Test
public void testStruct0() throws IOException, URISyntaxException {
compileAndCompare("struct-0");
}
@Test
public void testForTwoVars() throws IOException, URISyntaxException {
compileAndCompare("for-two-vars");

View File

@ -1,23 +1,14 @@
// Minimal struct - declaration, instantiation and usage
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label point = 2
bbegin:
lda #0
sta point
sta point+1
jsr main
rts
.const point_x = 2
.const point_y = 3
main: {
.label SCREEN = $400
lda #2
sta point+0
lda #3
sta point+1
lda point+0
lda #point_x
sta SCREEN
lda point+1
lda #point_y
sta SCREEN+1
rts
}

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] (struct Point) point#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -8,11 +8,9 @@
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] (struct Point) point#0.x ← (byte) 2
[5] (struct Point) point#0.y ← (byte) 3
[6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x
[7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
[8] return
[6] return
to:@return

View File

@ -1,25 +1,43 @@
Created struct value member variable (byte) point_x
Created struct value member variable (byte) point_y
Converted struct value to member variables (struct Point) point
Adding struct value member variable default initializer (byte) point_x ← (byte) 0
Adding struct value member variable default initializer (byte) point_y ← (byte) 0
Replacing struct member reference (struct Point) point.x with member variable reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member variable reference (byte) point_y
Replacing struct member reference (struct Point) point.x with member variable reference (byte) point_x
Replacing struct member reference (struct Point) point.y with member variable reference (byte) point_y
Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Point) point#0 ← {}
(byte) point_x#0 ← (byte) 0
(byte) point_y#0 ← (byte) 0
to:@1
main: scope:[main] from @1
(struct Point) point#1 ← phi( @1/(struct Point) point#2 )
(struct Point) point#1.x ← (number) 2
(struct Point) point#1.y ← (number) 3
(byte) point_x#1 ← (number) 2
(byte) point_y#1 ← (number) 3
(byte*) main::SCREEN#0 ← ((byte*)) (number) $400
*((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point#1.x
*((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point#1.y
*((byte*) main::SCREEN#0 + (number) 0) ← (byte) point_x#1
*((byte*) main::SCREEN#0 + (number) 1) ← (byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
(byte) point_y#4 ← phi( main/(byte) point_y#1 )
(byte) point_x#4 ← phi( main/(byte) point_x#1 )
(byte) point_x#2 ← (byte) point_x#4
(byte) point_y#2 ← (byte) point_y#4
return
to:@return
@1: scope:[] from @begin
(struct Point) point#2 ← phi( @begin/(struct Point) point#0 )
(byte) point_y#6 ← phi( @begin/(byte) point_y#0 )
(byte) point_x#6 ← phi( @begin/(byte) point_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point_y#5 ← phi( @1/(byte) point_y#2 )
(byte) point_x#5 ← phi( @1/(byte) point_x#2 )
(byte) point_x#3 ← (byte) point_x#5
(byte) point_y#3 ← (byte) point_y#5
to:@end
@end: scope:[] from @2
@ -35,17 +53,30 @@ SYMBOL TABLE SSA
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(struct Point) point
(struct Point) point#0
(struct Point) point#1
(struct Point) point#2
(byte) point_x
(byte) point_x#0
(byte) point_x#1
(byte) point_x#2
(byte) point_x#3
(byte) point_x#4
(byte) point_x#5
(byte) point_x#6
(byte) point_y
(byte) point_y#0
(byte) point_y#1
(byte) point_y#2
(byte) point_y#3
(byte) point_y#4
(byte) point_y#5
(byte) point_y#6
Adding number conversion cast (unumber) 2 in (struct Point) point#1.x ← (number) 2
Adding number conversion cast (unumber) 3 in (struct Point) point#1.y ← (number) 3
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point#1.x
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point#1.y
Adding number conversion cast (unumber) 2 in (byte) point_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point_y#1 ← (number) 3
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (byte) point_x#1
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (byte) point_y#1
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (struct Point) point#1.x ← (unumber)(number) 2
Inlining cast (struct Point) point#1.y ← (unumber)(number) 3
Inlining cast (byte) point_x#1 ← (unumber)(number) 2
Inlining cast (byte) point_y#1 ← (unumber)(number) 3
Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 2
@ -59,16 +90,30 @@ Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (struct Point) point#0 = (struct Point) point#2
Alias (byte) point_x#1 = (byte) point_x#4 (byte) point_x#2
Alias (byte) point_y#1 = (byte) point_y#4 (byte) point_y#2
Alias (byte) point_x#0 = (byte) point_x#6
Alias (byte) point_y#0 = (byte) point_y#6
Alias (byte) point_x#3 = (byte) point_x#5
Alias (byte) point_y#3 = (byte) point_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (struct Point) point#1 (struct Point) point#0
Identical Phi Values (byte) point_x#3 (byte) point_x#1
Identical Phi Values (byte) point_y#3 (byte) point_y#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point_x#0 = 0
Constant (const byte) point_y#0 = 0
Constant (const byte) point_x#1 = 2
Constant (const byte) point_y#1 = 3
Constant (const byte*) main::SCREEN#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN#0 in [5] *((const byte*) main::SCREEN#0 + (byte) 0) ← (struct Point) point#0.x
Simplifying expression containing zero main::SCREEN#0 in [5] *((const byte*) main::SCREEN#0 + (byte) 0) ← (const byte) point_x#1
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point_x#0
Eliminating unused constant (const byte) point_y#0
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN#0+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
@ -78,12 +123,13 @@ 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] (struct Point) point#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -92,13 +138,11 @@ FINAL CONTROL FLOW GRAPH
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] (struct Point) point#0.x ← (byte) 2
[5] (struct Point) point#0.y ← (byte) 3
[6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x
[7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1
to:main::@return
main::@return: scope:[main] from main
[8] return
[6] return
to:@return
@ -108,12 +152,11 @@ VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(struct Point) point
(struct Point) point#0 0.4
(byte) point_x
(byte) point_y
Initial phi equivalence classes
Complete equivalence classes
[ point#0 ]
Allocated zp ZP_STRUCT:2 [ point#0 ]
INITIAL ASM
//SEG0 File Comments
@ -123,63 +166,50 @@ INITIAL ASM
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point = 2
.const point_x = 2
.const point_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point#0 ← {} -- vssz1=vssf2
lda #0
sta point
sta point+1
//SEG5 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG6 @1
//SEG5 @1
b1:
//SEG7 [2] call main
//SEG6 [2] call main
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
//SEG8 @end
bend:
//SEG10 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG11 [4] (struct Point) point#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point+0
//SEG12 [5] (struct Point) point#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point+1
//SEG13 [6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x -- _deref_pbuc1=vbuz1
lda point+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
//SEG14 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y -- _deref_pbuc1=vbuz1
lda point+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
jmp breturn
//SEG15 main::@return
//SEG12 main::@return
breturn:
//SEG16 [8] return
//SEG13 [6] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (struct Point) point#0 ← {} [ point#0 ] ( ) always clobbers reg byte a
Statement [4] (struct Point) point#0.x ← (byte) 2 [ point#0 ] ( main:2 [ point#0 ] ) always clobbers reg byte a
Statement [5] (struct Point) point#0.y ← (byte) 3 [ point#0 ] ( main:2 [ point#0 ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x [ point#0 ] ( main:2 [ point#0 ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers zp ZP_STRUCT:2 [ point#0 ] : zp ZP_STRUCT:2 ,
Statement [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [] 0.4: zp ZP_STRUCT:2 [ point#0 ]
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplifting [] best 53 combination zp ZP_STRUCT:2 [ point#0 ]
Uplifting [Point] best 53 combination
Uplifting [main] best 53 combination
Uplifting [Point] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
@ -189,44 +219,35 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point = 2
.const point_x = 2
.const point_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point#0 ← {} -- vssz1=vssf2
lda #0
sta point
sta point+1
//SEG5 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG6 @1
//SEG5 @1
b1:
//SEG7 [2] call main
//SEG6 [2] call main
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
//SEG8 @end
bend:
//SEG10 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG11 [4] (struct Point) point#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point+0
//SEG12 [5] (struct Point) point#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point+1
//SEG13 [6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x -- _deref_pbuc1=vbuz1
lda point+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
//SEG14 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y -- _deref_pbuc1=vbuz1
lda point+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
jmp breturn
//SEG15 main::@return
//SEG12 main::@return
breturn:
//SEG16 [8] return
//SEG13 [6] return
rts
}
@ -236,14 +257,17 @@ Removing instruction jmp bend
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
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
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
@ -256,52 +280,42 @@ FINAL SYMBOL TABLE
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024
(struct Point) point
(struct Point) point#0 point zp ZP_STRUCT:2 0.4
(byte) point_x
(const byte) point_x#1 point_x = (byte) 2
(byte) point_y
(const byte) point_y#1 point_y = (byte) 3
zp ZP_STRUCT:2 [ point#0 ]
FINAL ASSEMBLER
Score: 50
Score: 18
//SEG0 File Comments
// Minimal struct - declaration, instantiation and usage
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point = 2
.const point_x = 2
.const point_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point#0 ← {} -- vssz1=vssf2
lda #0
sta point
sta point+1
//SEG5 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG6 @1
//SEG7 [2] call main
jsr main
rts
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG9 @end
//SEG10 main
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG11 [4] (struct Point) point#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point+0
//SEG12 [5] (struct Point) point#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point+1
//SEG13 [6] *((const byte*) main::SCREEN#0) ← (struct Point) point#0.x -- _deref_pbuc1=vbuz1
lda point+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2
lda #point_x
sta SCREEN
//SEG14 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point#0.y -- _deref_pbuc1=vbuz1
lda point+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2
lda #point_y
sta SCREEN+1
//SEG15 main::@return
//SEG16 [8] return
//SEG12 main::@return
//SEG13 [6] return
rts
}

View File

@ -1,29 +1,14 @@
// Minimal struct - two instances being used.
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label point1 = 2
.label point2 = 4
bbegin:
lda #0
sta point1
sta point1+1
sta point2
sta point2+1
jsr main
rts
.const point1_x = 2
.const point1_y = 3
main: {
.label SCREEN = $400
lda #2
sta point1+0
lda #3
sta point1+1
sta point2+0
lda point1+0
sta point2+1
lda point2+0
lda #point1_y
sta SCREEN
lda point2+1
lda #point1_x
sta SCREEN+1
rts
}

View File

@ -1,21 +1,16 @@
@begin: scope:[] from
[0] (struct Point) point1#0 ← {}
[1] (struct Point) point2#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[2] phi()
[3] call main
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
main: scope:[main] from @1
[5] (struct Point) point1#0.x ← (byte) 2
[6] (struct Point) point1#0.y ← (byte) 3
[7] (struct Point) point2#0.x ← (struct Point) point1#0.y
[8] (struct Point) point2#0.y ← (struct Point) point1#0.x
[9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x
[10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1
to:main::@return
main::@return: scope:[main] from main
[11] return
[6] return
to:@return

View File

@ -1,30 +1,66 @@
Created struct value member variable (byte) point1_x
Created struct value member variable (byte) point1_y
Converted struct value to member variables (struct Point) point1
Created struct value member variable (byte) point2_x
Created struct value member variable (byte) point2_y
Converted struct value to member variables (struct Point) point2
Adding struct value member variable default initializer (byte) point1_x ← (byte) 0
Adding struct value member variable default initializer (byte) point1_y ← (byte) 0
Adding struct value member variable default initializer (byte) point2_x ← (byte) 0
Adding struct value member variable default initializer (byte) point2_y ← (byte) 0
Replacing struct member reference (struct Point) point1.x with member variable reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member variable reference (byte) point1_y
Replacing struct member reference (struct Point) point1.y with member variable reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member variable reference (byte) point2_x
Replacing struct member reference (struct Point) point1.x with member variable reference (byte) point1_x
Replacing struct member reference (struct Point) point2.y with member variable reference (byte) point2_y
Replacing struct member reference (struct Point) point2.x with member variable reference (byte) point2_x
Replacing struct member reference (struct Point) point2.y with member variable reference (byte) point2_y
Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Point) point1#0 ← {}
(struct Point) point2#0 ← {}
(byte) point1_x#0 ← (byte) 0
(byte) point1_y#0 ← (byte) 0
(byte) point2_x#0 ← (byte) 0
(byte) point2_y#0 ← (byte) 0
to:@1
main: scope:[main] from @1
(struct Point) point2#1 ← phi( @1/(struct Point) point2#2 )
(struct Point) point1#1 ← phi( @1/(struct Point) point1#2 )
(struct Point) point1#1.x ← (number) 2
(struct Point) point1#1.y ← (number) 3
(struct Point) point2#1.x ← (struct Point) point1#1.y
(struct Point) point2#1.y ← (struct Point) point1#1.x
(byte) point1_x#1 ← (number) 2
(byte) point1_y#1 ← (number) 3
(byte) point2_x#1 ← (byte) point1_y#1
(byte) point2_y#1 ← (byte) point1_x#1
(byte*) main::SCREEN#0 ← ((byte*)) (number) $400
*((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point2#1.x
*((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point2#1.y
*((byte*) main::SCREEN#0 + (number) 0) ← (byte) point2_x#1
*((byte*) main::SCREEN#0 + (number) 1) ← (byte) point2_y#1
to:main::@return
main::@return: scope:[main] from main
(byte) point2_y#4 ← phi( main/(byte) point2_y#1 )
(byte) point2_x#4 ← phi( main/(byte) point2_x#1 )
(byte) point1_y#4 ← phi( main/(byte) point1_y#1 )
(byte) point1_x#4 ← phi( main/(byte) point1_x#1 )
(byte) point1_x#2 ← (byte) point1_x#4
(byte) point1_y#2 ← (byte) point1_y#4
(byte) point2_x#2 ← (byte) point2_x#4
(byte) point2_y#2 ← (byte) point2_y#4
return
to:@return
@1: scope:[] from @begin
(struct Point) point2#2 ← phi( @begin/(struct Point) point2#0 )
(struct Point) point1#2 ← phi( @begin/(struct Point) point1#0 )
(byte) point2_y#6 ← phi( @begin/(byte) point2_y#0 )
(byte) point2_x#6 ← phi( @begin/(byte) point2_x#0 )
(byte) point1_y#6 ← phi( @begin/(byte) point1_y#0 )
(byte) point1_x#6 ← phi( @begin/(byte) point1_x#0 )
call main
to:@2
@2: scope:[] from @1
(byte) point2_y#5 ← phi( @1/(byte) point2_y#2 )
(byte) point2_x#5 ← phi( @1/(byte) point2_x#2 )
(byte) point1_y#5 ← phi( @1/(byte) point1_y#2 )
(byte) point1_x#5 ← phi( @1/(byte) point1_x#2 )
(byte) point1_x#3 ← (byte) point1_x#5
(byte) point1_y#3 ← (byte) point1_y#5
(byte) point2_x#3 ← (byte) point2_x#5
(byte) point2_y#3 ← (byte) point2_y#5
to:@end
@end: scope:[] from @2
@ -40,21 +76,47 @@ SYMBOL TABLE SSA
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(struct Point) point1
(struct Point) point1#0
(struct Point) point1#1
(struct Point) point1#2
(byte) point1_x
(byte) point1_x#0
(byte) point1_x#1
(byte) point1_x#2
(byte) point1_x#3
(byte) point1_x#4
(byte) point1_x#5
(byte) point1_x#6
(byte) point1_y
(byte) point1_y#0
(byte) point1_y#1
(byte) point1_y#2
(byte) point1_y#3
(byte) point1_y#4
(byte) point1_y#5
(byte) point1_y#6
(struct Point) point2
(struct Point) point2#0
(struct Point) point2#1
(struct Point) point2#2
(byte) point2_x
(byte) point2_x#0
(byte) point2_x#1
(byte) point2_x#2
(byte) point2_x#3
(byte) point2_x#4
(byte) point2_x#5
(byte) point2_x#6
(byte) point2_y
(byte) point2_y#0
(byte) point2_y#1
(byte) point2_y#2
(byte) point2_y#3
(byte) point2_y#4
(byte) point2_y#5
(byte) point2_y#6
Adding number conversion cast (unumber) 2 in (struct Point) point1#1.x ← (number) 2
Adding number conversion cast (unumber) 3 in (struct Point) point1#1.y ← (number) 3
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point2#1.x
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point2#1.y
Adding number conversion cast (unumber) 2 in (byte) point1_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point1_y#1 ← (number) 3
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (byte) point2_x#1
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (byte) point2_y#1
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (struct Point) point1#1.x ← (unumber)(number) 2
Inlining cast (struct Point) point1#1.y ← (unumber)(number) 3
Inlining cast (byte) point1_x#1 ← (unumber)(number) 2
Inlining cast (byte) point1_y#1 ← (unumber)(number) 3
Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 2
@ -68,51 +130,69 @@ Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (struct Point) point1#0 = (struct Point) point1#2
Alias (struct Point) point2#0 = (struct Point) point2#2
Alias (byte) point1_y#1 = (byte) point2_x#1 (byte) point1_y#4 (byte) point2_x#4 (byte) point1_y#2 (byte) point2_x#2
Alias (byte) point1_x#1 = (byte) point2_y#1 (byte) point1_x#4 (byte) point2_y#4 (byte) point1_x#2 (byte) point2_y#2
Alias (byte) point1_x#0 = (byte) point1_x#6
Alias (byte) point1_y#0 = (byte) point1_y#6
Alias (byte) point2_x#0 = (byte) point2_x#6
Alias (byte) point2_y#0 = (byte) point2_y#6
Alias (byte) point1_x#3 = (byte) point1_x#5
Alias (byte) point1_y#3 = (byte) point1_y#5
Alias (byte) point2_x#3 = (byte) point2_x#5
Alias (byte) point2_y#3 = (byte) point2_y#5
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (struct Point) point1#1 (struct Point) point1#0
Identical Phi Values (struct Point) point2#1 (struct Point) point2#0
Identical Phi Values (byte) point1_x#3 (byte) point1_x#1
Identical Phi Values (byte) point1_y#3 (byte) point1_y#1
Identical Phi Values (byte) point2_x#3 (byte) point1_y#1
Identical Phi Values (byte) point2_y#3 (byte) point1_x#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point1_x#0 = 0
Constant (const byte) point1_y#0 = 0
Constant (const byte) point2_x#0 = 0
Constant (const byte) point2_y#0 = 0
Constant (const byte) point1_x#1 = 2
Constant (const byte) point1_y#1 = 3
Constant (const byte*) main::SCREEN#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN#0 in [8] *((const byte*) main::SCREEN#0 + (byte) 0) ← (struct Point) point2#0.x
Simplifying expression containing zero main::SCREEN#0 in [9] *((const byte*) main::SCREEN#0 + (byte) 0) ← (const byte) point1_y#1
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) point1_x#0
Eliminating unused constant (const byte) point1_y#0
Eliminating unused constant (const byte) point2_x#0
Eliminating unused constant (const byte) point2_y#0
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN#0+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:3
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] (struct Point) point1#0 ← {}
[1] (struct Point) point2#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[2] phi()
[3] call main
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
main: scope:[main] from @1
[5] (struct Point) point1#0.x ← (byte) 2
[6] (struct Point) point1#0.y ← (byte) 3
[7] (struct Point) point2#0.x ← (struct Point) point1#0.y
[8] (struct Point) point2#0.y ← (struct Point) point1#0.x
[9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x
[10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1
to:main::@return
main::@return: scope:[main] from main
[11] return
[6] return
to:@return
@ -122,16 +202,14 @@ VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(struct Point) point1
(struct Point) point1#0 0.3333333333333333
(byte) point1_x
(byte) point1_y
(struct Point) point2
(struct Point) point2#0 0.2857142857142857
(byte) point2_x
(byte) point2_y
Initial phi equivalence classes
Complete equivalence classes
[ point1#0 ]
[ point2#0 ]
Allocated zp ZP_STRUCT:2 [ point1#0 ]
Allocated zp ZP_STRUCT:4 [ point2#0 ]
INITIAL ASM
//SEG0 File Comments
@ -141,78 +219,50 @@ INITIAL ASM
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
lda #0
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG7 @1
//SEG5 @1
b1:
//SEG8 [3] call main
//SEG6 [2] call main
jsr main
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG10 @end
//SEG8 @end
bend:
//SEG11 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#0.x ← (struct Point) point1#0.y -- vbuz1=vbuz2
lda point1+1
sta point2+0
//SEG15 [8] (struct Point) point2#0.y ← (struct Point) point1#0.x -- vbuz1=vbuz2
lda point1+0
sta point2+1
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN+1
jmp breturn
//SEG18 main::@return
//SEG12 main::@return
breturn:
//SEG19 [11] return
//SEG13 [6] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (struct Point) point1#0 ← {} [ point1#0 ] ( ) always clobbers reg byte a
Statement [1] (struct Point) point2#0 ← {} [ point1#0 point2#0 ] ( ) always clobbers reg byte a
Statement [5] (struct Point) point1#0.x ← (byte) 2 [ point1#0 point2#0 ] ( main:3 [ point1#0 point2#0 ] ) always clobbers reg byte a
Statement [6] (struct Point) point1#0.y ← (byte) 3 [ point1#0 point2#0 ] ( main:3 [ point1#0 point2#0 ] ) always clobbers reg byte a
Statement [7] (struct Point) point2#0.x ← (struct Point) point1#0.y [ point1#0 point2#0 ] ( main:3 [ point1#0 point2#0 ] ) always clobbers reg byte a
Statement [8] (struct Point) point2#0.y ← (struct Point) point1#0.x [ point2#0 ] ( main:3 [ point2#0 ] ) always clobbers reg byte a
Statement [9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x [ point2#0 ] ( main:3 [ point2#0 ] ) always clobbers reg byte a
Statement [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers zp ZP_STRUCT:2 [ point1#0 ] : zp ZP_STRUCT:2 ,
Potential registers zp ZP_STRUCT:4 [ point2#0 ] : zp ZP_STRUCT:4 ,
Statement [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [] 0.33: zp ZP_STRUCT:2 [ point1#0 ] 0.29: zp ZP_STRUCT:4 [ point2#0 ]
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplifting [] best 73 combination zp ZP_STRUCT:2 [ point1#0 ] zp ZP_STRUCT:4 [ point2#0 ]
Uplifting [Point] best 73 combination
Uplifting [main] best 73 combination
Uplifting [Point] best 33 combination
Uplifting [main] best 33 combination
Uplifting [] best 33 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
@ -222,55 +272,35 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
lda #0
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG7 @1
//SEG5 @1
b1:
//SEG8 [3] call main
//SEG6 [2] call main
jsr main
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG10 @end
//SEG8 @end
bend:
//SEG11 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#0.x ← (struct Point) point1#0.y -- vbuz1=vbuz2
lda point1+1
sta point2+0
//SEG15 [8] (struct Point) point2#0.y ← (struct Point) point1#0.x -- vbuz1=vbuz2
lda point1+0
sta point2+1
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN+1
jmp breturn
//SEG18 main::@return
//SEG12 main::@return
breturn:
//SEG19 [11] return
//SEG13 [6] return
rts
}
@ -279,18 +309,18 @@ Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #0
Removing instruction lda point1+1
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
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
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
@ -303,64 +333,45 @@ FINAL SYMBOL TABLE
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024
(struct Point) point1
(struct Point) point1#0 point1 zp ZP_STRUCT:2 0.3333333333333333
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(struct Point) point2
(struct Point) point2#0 point2 zp ZP_STRUCT:4 0.2857142857142857
(byte) point2_x
(byte) point2_y
zp ZP_STRUCT:2 [ point1#0 ]
zp ZP_STRUCT:4 [ point2#0 ]
FINAL ASSEMBLER
Score: 65
Score: 18
//SEG0 File Comments
// Minimal struct - two instances being used.
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG7 @1
//SEG8 [3] call main
jsr main
rts
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG10 @end
//SEG11 main
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#0.x ← (struct Point) point1#0.y -- vbuz1=vbuz2
sta point2+0
//SEG15 [8] (struct Point) point2#0.y ← (struct Point) point1#0.x -- vbuz1=vbuz2
lda point1+0
sta point2+1
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point2#0.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point2#0.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN+1
//SEG18 main::@return
//SEG19 [11] return
//SEG12 main::@return
//SEG13 [6] return
rts
}

View File

@ -1,36 +1,19 @@
// Minimal struct - different instances and copying
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label point1 = 2
.label point2 = 4
bbegin:
lda #0
sta point1
sta point1+1
sta point2
sta point2+1
jsr main
rts
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
main: {
.label SCREEN = $400
lda #2
sta point1+0
lda #3
sta point1+1
lda point1
sta point2
lda point1+1
sta point2+1
lda #4
sta point2+0
lda point1+0
lda #point1_x
sta SCREEN
lda point1+1
lda #point1_y
sta SCREEN+1
lda point2+0
lda #point2_x
sta SCREEN+2
lda point2+1
lda #point1_y
sta SCREEN+3
rts
}

View File

@ -1,23 +1,18 @@
@begin: scope:[] from
[0] (struct Point) point1#0 ← {}
[1] (struct Point) point2#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[2] phi()
[3] call main
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
main: scope:[main] from @1
[5] (struct Point) point1#0.x ← (byte) 2
[6] (struct Point) point1#0.y ← (byte) 3
[7] (struct Point) point2#1 ← (struct Point) point1#0
[8] (struct Point) point2#1.x ← (byte) 4
[9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x
[10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y
[11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x
[12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1
[6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2
[7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1
to:main::@return
main::@return: scope:[main] from main
[13] return
[8] return
to:@return

View File

@ -1,35 +1,70 @@
Created struct value member variable (byte) point1_x
Created struct value member variable (byte) point1_y
Converted struct value to member variables (struct Point) point1
Created struct value member variable (byte) point2_x
Created struct value member variable (byte) point2_y
Converted struct value to member variables (struct Point) point2
Adding struct value member variable default initializer (byte) point1_x ← (byte) 0
Adding struct value member variable default initializer (byte) point1_y ← (byte) 0
Adding struct value member variable default initializer (byte) point2_x ← (byte) 0
Adding struct value member variable default initializer (byte) point2_y ← (byte) 0
Adding struct value member variable copy (byte) point2_x ← (byte) point1_x
Adding struct value member variable copy (byte) point2_y ← (byte) point1_y
Replacing struct member reference (struct Point) point1.x with member variable reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member variable reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member variable reference (byte) point2_x
Replacing struct member reference (struct Point) point1.x with member variable reference (byte) point1_x
Replacing struct member reference (struct Point) point1.y with member variable reference (byte) point1_y
Replacing struct member reference (struct Point) point2.x with member variable reference (byte) point2_x
Replacing struct member reference (struct Point) point2.y with member variable reference (byte) point2_y
Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Point) point1#0 ← {}
(struct Point) point2#0 ← {}
(byte) point1_x#0 ← (byte) 0
(byte) point1_y#0 ← (byte) 0
(byte) point2_x#0 ← (byte) 0
(byte) point2_y#0 ← (byte) 0
to:@1
main: scope:[main] from @1
(struct Point) point1#1 ← phi( @1/(struct Point) point1#2 )
(struct Point) point1#1.x ← (number) 2
(struct Point) point1#1.y ← (number) 3
(struct Point) point2#1 ← (struct Point) point1#1
(struct Point) point2#1.x ← (number) 4
(byte) point1_x#1 ← (number) 2
(byte) point1_y#1 ← (number) 3
(byte) point2_x#1 ← (byte) point1_x#1
(byte) point2_y#1 ← (byte) point1_y#1
(byte) point2_x#2 ← (number) 4
(byte*) main::SCREEN#0 ← ((byte*)) (number) $400
*((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point1#1.x
*((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point1#1.y
*((byte*) main::SCREEN#0 + (number) 2) ← (struct Point) point2#1.x
*((byte*) main::SCREEN#0 + (number) 3) ← (struct Point) point2#1.y
*((byte*) main::SCREEN#0 + (number) 0) ← (byte) point1_x#1
*((byte*) main::SCREEN#0 + (number) 1) ← (byte) point1_y#1
*((byte*) main::SCREEN#0 + (number) 2) ← (byte) point2_x#2
*((byte*) main::SCREEN#0 + (number) 3) ← (byte) point2_y#1
to:main::@return
main::@return: scope:[main] from main
(struct Point) point2#4 ← phi( main/(struct Point) point2#1 )
(struct Point) point2#2 ← (struct Point) point2#4
(byte) point2_y#4 ← phi( main/(byte) point2_y#1 )
(byte) point2_x#5 ← phi( main/(byte) point2_x#2 )
(byte) point1_y#4 ← phi( main/(byte) point1_y#1 )
(byte) point1_x#4 ← phi( main/(byte) point1_x#1 )
(byte) point1_x#2 ← (byte) point1_x#4
(byte) point1_y#2 ← (byte) point1_y#4
(byte) point2_x#3 ← (byte) point2_x#5
(byte) point2_y#2 ← (byte) point2_y#4
return
to:@return
@1: scope:[] from @begin
(struct Point) point2#6 ← phi( @begin/(struct Point) point2#0 )
(struct Point) point1#2 ← phi( @begin/(struct Point) point1#0 )
(byte) point2_y#6 ← phi( @begin/(byte) point2_y#0 )
(byte) point2_x#7 ← phi( @begin/(byte) point2_x#0 )
(byte) point1_y#6 ← phi( @begin/(byte) point1_y#0 )
(byte) point1_x#6 ← phi( @begin/(byte) point1_x#0 )
call main
to:@2
@2: scope:[] from @1
(struct Point) point2#5 ← phi( @1/(struct Point) point2#2 )
(struct Point) point2#3 ← (struct Point) point2#5
(byte) point2_y#5 ← phi( @1/(byte) point2_y#2 )
(byte) point2_x#6 ← phi( @1/(byte) point2_x#3 )
(byte) point1_y#5 ← phi( @1/(byte) point1_y#2 )
(byte) point1_x#5 ← phi( @1/(byte) point1_x#2 )
(byte) point1_x#3 ← (byte) point1_x#5
(byte) point1_y#3 ← (byte) point1_y#5
(byte) point2_x#4 ← (byte) point2_x#6
(byte) point2_y#3 ← (byte) point2_y#5
to:@end
@end: scope:[] from @2
@ -45,29 +80,52 @@ SYMBOL TABLE SSA
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(struct Point) point1
(struct Point) point1#0
(struct Point) point1#1
(struct Point) point1#2
(byte) point1_x
(byte) point1_x#0
(byte) point1_x#1
(byte) point1_x#2
(byte) point1_x#3
(byte) point1_x#4
(byte) point1_x#5
(byte) point1_x#6
(byte) point1_y
(byte) point1_y#0
(byte) point1_y#1
(byte) point1_y#2
(byte) point1_y#3
(byte) point1_y#4
(byte) point1_y#5
(byte) point1_y#6
(struct Point) point2
(struct Point) point2#0
(struct Point) point2#1
(struct Point) point2#2
(struct Point) point2#3
(struct Point) point2#4
(struct Point) point2#5
(struct Point) point2#6
(byte) point2_x
(byte) point2_x#0
(byte) point2_x#1
(byte) point2_x#2
(byte) point2_x#3
(byte) point2_x#4
(byte) point2_x#5
(byte) point2_x#6
(byte) point2_x#7
(byte) point2_y
(byte) point2_y#0
(byte) point2_y#1
(byte) point2_y#2
(byte) point2_y#3
(byte) point2_y#4
(byte) point2_y#5
(byte) point2_y#6
Adding number conversion cast (unumber) 2 in (struct Point) point1#1.x ← (number) 2
Adding number conversion cast (unumber) 3 in (struct Point) point1#1.y ← (number) 3
Adding number conversion cast (unumber) 4 in (struct Point) point2#1.x ← (number) 4
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (struct Point) point1#1.x
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (struct Point) point1#1.y
Adding number conversion cast (unumber) 2 in *((byte*) main::SCREEN#0 + (number) 2) ← (struct Point) point2#1.x
Adding number conversion cast (unumber) 3 in *((byte*) main::SCREEN#0 + (number) 3) ← (struct Point) point2#1.y
Adding number conversion cast (unumber) 2 in (byte) point1_x#1 ← (number) 2
Adding number conversion cast (unumber) 3 in (byte) point1_y#1 ← (number) 3
Adding number conversion cast (unumber) 4 in (byte) point2_x#2 ← (number) 4
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (byte) point1_x#1
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (byte) point1_y#1
Adding number conversion cast (unumber) 2 in *((byte*) main::SCREEN#0 + (number) 2) ← (byte) point2_x#2
Adding number conversion cast (unumber) 3 in *((byte*) main::SCREEN#0 + (number) 3) ← (byte) point2_y#1
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (struct Point) point1#1.x ← (unumber)(number) 2
Inlining cast (struct Point) point1#1.y ← (unumber)(number) 3
Inlining cast (struct Point) point2#1.x ← (unumber)(number) 4
Inlining cast (byte) point1_x#1 ← (unumber)(number) 2
Inlining cast (byte) point1_y#1 ← (unumber)(number) 3
Inlining cast (byte) point2_x#2 ← (unumber)(number) 4
Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 2
@ -87,61 +145,75 @@ Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias candidate removed (volatile)(struct Point) point2#1 = (struct Point) point1#1 (struct Point) point2#4 (struct Point) point2#2
Alias (struct Point) point1#0 = (struct Point) point1#2
Alias (struct Point) point2#0 = (struct Point) point2#6
Alias (struct Point) point2#3 = (struct Point) point2#5
Alias (byte) point1_x#1 = (byte) point2_x#1 (byte) point1_x#4 (byte) point1_x#2
Alias (byte) point1_y#1 = (byte) point2_y#1 (byte) point1_y#4 (byte) point2_y#4 (byte) point1_y#2 (byte) point2_y#2
Alias (byte) point2_x#2 = (byte) point2_x#5 (byte) point2_x#3
Alias (byte) point1_x#0 = (byte) point1_x#6
Alias (byte) point1_y#0 = (byte) point1_y#6
Alias (byte) point2_x#0 = (byte) point2_x#7
Alias (byte) point2_y#0 = (byte) point2_y#6
Alias (byte) point1_x#3 = (byte) point1_x#5
Alias (byte) point1_y#3 = (byte) point1_y#5
Alias (byte) point2_x#4 = (byte) point2_x#6
Alias (byte) point2_y#3 = (byte) point2_y#5
Successful SSA optimization Pass2AliasElimination
Alias candidate removed (volatile)(struct Point) point2#1 = (struct Point) point1#1 (struct Point) point2#4 (struct Point) point2#2
Identical Phi Values (struct Point) point1#1 (struct Point) point1#0
Identical Phi Values (struct Point) point2#4 (struct Point) point2#1
Identical Phi Values (struct Point) point2#3 (struct Point) point2#2
Identical Phi Values (byte) point1_x#3 (byte) point1_x#1
Identical Phi Values (byte) point1_y#3 (byte) point1_y#1
Identical Phi Values (byte) point2_x#4 (byte) point2_x#2
Identical Phi Values (byte) point2_y#3 (byte) point1_y#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant (const byte) point1_x#0 = 0
Constant (const byte) point1_y#0 = 0
Constant (const byte) point2_x#0 = 0
Constant (const byte) point2_y#0 = 0
Constant (const byte) point1_x#1 = 2
Constant (const byte) point1_y#1 = 3
Constant (const byte) point2_x#2 = 4
Constant (const byte*) main::SCREEN#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero main::SCREEN#0 in [8] *((const byte*) main::SCREEN#0 + (byte) 0) ← (struct Point) point1#0.x
Simplifying expression containing zero main::SCREEN#0 in [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← (const byte) point1_x#1
Successful SSA optimization PassNSimplifyExpressionWithZero
Alias (struct Point) point2#1 = (struct Point) point2#2
Successful SSA optimization Pass2AliasElimination
Eliminating unused constant (const byte) point1_x#0
Eliminating unused constant (const byte) point1_y#0
Eliminating unused constant (const byte) point2_x#0
Eliminating unused constant (const byte) point2_y#0
Successful SSA optimization PassNEliminateUnusedVars
Consolidated array index constant in *(main::SCREEN#0+1)
Consolidated array index constant in *(main::SCREEN#0+2)
Consolidated array index constant in *(main::SCREEN#0+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:3
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] (struct Point) point1#0 ← {}
[1] (struct Point) point2#0 ← {}
[0] phi()
to:@1
@1: scope:[] from @begin
[2] phi()
[3] call main
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[4] phi()
[3] phi()
main: scope:[main] from @1
[5] (struct Point) point1#0.x ← (byte) 2
[6] (struct Point) point1#0.y ← (byte) 3
[7] (struct Point) point2#1 ← (struct Point) point1#0
[8] (struct Point) point2#1.x ← (byte) 4
[9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x
[10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y
[11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x
[12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y
[4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1
[5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1
[6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2
[7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1
to:main::@return
main::@return: scope:[main] from main
[13] return
[8] return
to:@return
@ -151,18 +223,14 @@ VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(struct Point) point1
(struct Point) point1#0 0.5
(byte) point1_x
(byte) point1_y
(struct Point) point2
(struct Point) point2#0 20.0
(struct Point) point2#1 0.4
(byte) point2_x
(byte) point2_y
Initial phi equivalence classes
Coalescing volatile variable equivalence classes [ point2#0 ] and [ point2#1 ]
Complete equivalence classes
[ point1#0 ]
[ point2#0 point2#1 ]
Allocated zp ZP_STRUCT:2 [ point1#0 ]
Allocated zp ZP_STRUCT:4 [ point2#0 point2#1 ]
INITIAL ASM
//SEG0 File Comments
@ -172,88 +240,59 @@ INITIAL ASM
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
lda #0
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG7 @1
//SEG5 @1
b1:
//SEG8 [3] call main
//SEG6 [2] call main
jsr main
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG10 @end
//SEG8 @end
bend:
//SEG11 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#1 ← (struct Point) point1#0 -- vssz1=vssz2
lda point1
sta point2
lda point1+1
sta point2+1
//SEG15 [8] (struct Point) point2#1.x ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta point2+0
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x -- _deref_pbuc1=vbuz1
lda point1+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y -- _deref_pbuc1=vbuz1
lda point1+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+1
//SEG18 [11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
sta SCREEN+2
//SEG19 [12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+3
jmp breturn
//SEG20 main::@return
//SEG14 main::@return
breturn:
//SEG21 [13] return
//SEG15 [8] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (struct Point) point1#0 ← {} [ point1#0 ] ( ) always clobbers reg byte a
Statement [1] (struct Point) point2#0 ← {} [ point1#0 ] ( ) always clobbers reg byte a
Statement [5] (struct Point) point1#0.x ← (byte) 2 [ point1#0 ] ( main:3 [ point1#0 ] ) always clobbers reg byte a
Statement [6] (struct Point) point1#0.y ← (byte) 3 [ point1#0 ] ( main:3 [ point1#0 ] ) always clobbers reg byte a
Statement [7] (struct Point) point2#1 ← (struct Point) point1#0 [ point1#0 point2#1 ] ( main:3 [ point1#0 point2#1 ] ) always clobbers reg byte a
Statement [8] (struct Point) point2#1.x ← (byte) 4 [ point1#0 point2#1 ] ( main:3 [ point1#0 point2#1 ] ) always clobbers reg byte a
Statement [9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x [ point1#0 point2#1 ] ( main:3 [ point1#0 point2#1 ] ) always clobbers reg byte a
Statement [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y [ point2#1 ] ( main:3 [ point2#1 ] ) always clobbers reg byte a
Statement [11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x [ point2#1 ] ( main:3 [ point2#1 ] ) always clobbers reg byte a
Statement [12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y [ ] ( main:3 [ ] ) always clobbers reg byte a
Potential registers zp ZP_STRUCT:2 [ point1#0 ] : zp ZP_STRUCT:2 ,
Potential registers zp ZP_STRUCT:4 [ point2#0 point2#1 ] : zp ZP_STRUCT:4 ,
Statement [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [] 20.4: zp ZP_STRUCT:4 [ point2#0 point2#1 ] 0.5: zp ZP_STRUCT:2 [ point1#0 ]
Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope []
Uplifting [] best 92 combination zp ZP_STRUCT:4 [ point2#0 point2#1 ] zp ZP_STRUCT:2 [ point1#0 ]
Uplifting [Point] best 92 combination
Uplifting [main] best 92 combination
Uplifting [Point] best 45 combination
Uplifting [main] best 45 combination
Uplifting [] best 45 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
@ -263,63 +302,42 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
lda #0
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG7 @1
//SEG5 @1
b1:
//SEG8 [3] call main
//SEG6 [2] call main
jsr main
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG10 @end
//SEG8 @end
bend:
//SEG11 main
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#1 ← (struct Point) point1#0 -- vssz1=vssz2
lda point1
sta point2
lda point1+1
sta point2+1
//SEG15 [8] (struct Point) point2#1.x ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta point2+0
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x -- _deref_pbuc1=vbuz1
lda point1+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y -- _deref_pbuc1=vbuz1
lda point1+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+1
//SEG18 [11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
sta SCREEN+2
//SEG19 [12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+3
jmp breturn
//SEG20 main::@return
//SEG14 main::@return
breturn:
//SEG21 [13] return
//SEG15 [8] return
rts
}
@ -328,17 +346,18 @@ 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 b1:
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
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
@ -351,74 +370,53 @@ FINAL SYMBOL TABLE
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024
(struct Point) point1
(struct Point) point1#0 point1 zp ZP_STRUCT:2 0.5
(byte) point1_x
(const byte) point1_x#1 point1_x = (byte) 2
(byte) point1_y
(const byte) point1_y#1 point1_y = (byte) 3
(struct Point) point2
(struct Point) point2#0 point2 zp ZP_STRUCT:4 20.0
(struct Point) point2#1 point2 zp ZP_STRUCT:4 0.4
(byte) point2_x
(const byte) point2_x#2 point2_x = (byte) 4
(byte) point2_y
zp ZP_STRUCT:2 [ point1#0 ]
zp ZP_STRUCT:4 [ point2#0 point2#1 ]
FINAL ASSEMBLER
Score: 87
Score: 30
//SEG0 File Comments
// Minimal struct - different instances and copying
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.label point1 = 2
.label point2 = 4
.const point1_x = 2
.const point1_y = 3
.const point2_x = 4
//SEG3 @begin
bbegin:
//SEG4 [0] (struct Point) point1#0 ← {} -- vssz1=vssf2
lda #0
sta point1
sta point1+1
//SEG5 [1] (struct Point) point2#0 ← {} -- vssz1=vssf2
sta point2
sta point2+1
//SEG6 [2] phi from @begin to @1 [phi:@begin->@1]
//SEG7 @1
//SEG8 [3] call main
jsr main
rts
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
//SEG10 @end
//SEG11 main
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG12 [5] (struct Point) point1#0.x ← (byte) 2 -- vbuz1=vbuc1
lda #2
sta point1+0
//SEG13 [6] (struct Point) point1#0.y ← (byte) 3 -- vbuz1=vbuc1
lda #3
sta point1+1
//SEG14 [7] (struct Point) point2#1 ← (struct Point) point1#0 -- vssz1=vssz2
lda point1
sta point2
lda point1+1
sta point2+1
//SEG15 [8] (struct Point) point2#1.x ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta point2+0
//SEG16 [9] *((const byte*) main::SCREEN#0) ← (struct Point) point1#0.x -- _deref_pbuc1=vbuz1
lda point1+0
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point1_x#1 -- _deref_pbuc1=vbuc2
lda #point1_x
sta SCREEN
//SEG17 [10] *((const byte*) main::SCREEN#0+(byte) 1) ← (struct Point) point1#0.y -- _deref_pbuc1=vbuz1
lda point1+1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+1
//SEG18 [11] *((const byte*) main::SCREEN#0+(byte) 2) ← (struct Point) point2#1.x -- _deref_pbuc1=vbuz1
lda point2+0
//SEG12 [6] *((const byte*) main::SCREEN#0+(byte) 2) ← (const byte) point2_x#2 -- _deref_pbuc1=vbuc2
lda #point2_x
sta SCREEN+2
//SEG19 [12] *((const byte*) main::SCREEN#0+(byte) 3) ← (struct Point) point2#1.y -- _deref_pbuc1=vbuz1
lda point2+1
//SEG13 [7] *((const byte*) main::SCREEN#0+(byte) 3) ← (const byte) point1_y#1 -- _deref_pbuc1=vbuc2
lda #point1_y
sta SCREEN+3
//SEG20 main::@return
//SEG21 [13] return
//SEG14 main::@return
//SEG15 [8] return
rts
}

View File

@ -1,174 +1,5 @@
PARSING src/test/kc/struct-4.kc
// Minimal struct - array of struct - near pointer math indexing
struct Point {
byte x;
byte y;
};
struct Point[4] points;
const byte SIZEOF_POINT = 2;
const byte OFFS_X = 0;
const byte OFFS_Y = 1;
void main() {
for( byte i: 0..3) {
*((byte*)points+OFFS_X+i*SIZEOF_POINT) = i; // points[i].x = i;
*((byte*)points+OFFS_Y+i*SIZEOF_POINT) = i+4; // points[i].y = i+4;
}
const byte* SCREEN = 0x0400;
for( byte i: 0..3) {
SCREEN[i] = *((byte*)points+OFFS_X+i*SIZEOF_POINT); // SCREEN[i] = points[i].x;
(SCREEN+40)[i] = *((byte*)points+OFFS_Y+i*SIZEOF_POINT); // (SCREEN+40)[i] = points[i].y;
}
}
STATEMENTS
(struct Point[4]) points ← { fill( 4, 0) }
(byte) SIZEOF_POINT ← (number) 2
(byte) OFFS_X ← (number) 0
(byte) OFFS_Y ← (number) 1
proc (void()) main()
(byte) main:::1::i ← (byte) 0
main:::1::@1:
(var) main:::1::$0 ← ((byte*)) (struct Point[4]) points
(var) main:::1::$1 ← (var) main:::1::$0 + (byte) OFFS_X
(var) main:::1::$2 ← (byte) main:::1::i * (byte) SIZEOF_POINT
(var) main:::1::$3 ← (var) main:::1::$1 + (var) main:::1::$2
*((var) main:::1::$3) ← (byte) main:::1::i
(var) main:::1::$4 ← ((byte*)) (struct Point[4]) points
(var) main:::1::$5 ← (var) main:::1::$4 + (byte) OFFS_Y
(var) main:::1::$6 ← (byte) main:::1::i * (byte) SIZEOF_POINT
(var) main:::1::$7 ← (var) main:::1::$5 + (var) main:::1::$6
(var) main:::1::$8 ← (byte) main:::1::i + (number) 4
*((var) main:::1::$7) ← (var) main:::1::$8
(byte) main:::1::i ← (byte) main:::1::i + rangenext(0,3)
(var) main:::1::$9 ← (byte) main:::1::i != rangelast(0,3)
if((var) main:::1::$9) goto main:::1::@1
(byte*) main::SCREEN ← (number) $400
(byte) main:::2::i ← (byte) 0
main:::2::@1:
(var) main:::2::$0 ← ((byte*)) (struct Point[4]) points
(var) main:::2::$1 ← (var) main:::2::$0 + (byte) OFFS_X
(var) main:::2::$2 ← (byte) main:::2::i * (byte) SIZEOF_POINT
(var) main:::2::$3 ← (var) main:::2::$1 + (var) main:::2::$2
*((byte*) main::SCREEN + (byte) main:::2::i) ← *((var) main:::2::$3)
(var) main:::2::$4 ← (byte*) main::SCREEN + (number) $28
(var) main:::2::$5 ← ((byte*)) (struct Point[4]) points
(var) main:::2::$6 ← (var) main:::2::$5 + (byte) OFFS_Y
(var) main:::2::$7 ← (byte) main:::2::i * (byte) SIZEOF_POINT
(var) main:::2::$8 ← (var) main:::2::$6 + (var) main:::2::$7
*((var) main:::2::$4 + (byte) main:::2::i) ← *((var) main:::2::$8)
(byte) main:::2::i ← (byte) main:::2::i + rangenext(0,3)
(var) main:::2::$9 ← (byte) main:::2::i != rangelast(0,3)
if((var) main:::2::$9) goto main:::2::@1
main::@return:
return
endproc // main()
call main
SYMBOLS
(label) @1
(label) @begin
(label) @end
(byte) OFFS_X
(byte) OFFS_Y
(byte) Point::x
(byte) Point::y
(byte) SIZEOF_POINT
(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
(bool~) main::$19
(byte~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(byte*~) main::$5
(byte~) main::$6
(byte*~) main::$7
(number~) main::$8
(bool~) main::$9
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte*) main::SCREEN
(byte) main::i
(byte) main::i1
(struct Point[4]) points
Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] (struct Point[4]) points ← { fill( 4, 0) }
[1] (byte) SIZEOF_POINT ← (number) 2
[2] (byte) OFFS_X ← (number) 0
[3] (byte) OFFS_Y ← (number) 1
to:@1
main: scope:[main] from
[4] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
[5] (byte*~) main::$0 ← ((byte*)) (struct Point[4]) points
[6] (byte*~) main::$1 ← (byte*~) main::$0 + (byte) OFFS_X
[7] (byte~) main::$2 ← (byte) main::i * (byte) SIZEOF_POINT
[8] (byte*~) main::$3 ← (byte*~) main::$1 + (byte~) main::$2
[9] *((byte*~) main::$3) ← (byte) main::i
[10] (byte*~) main::$4 ← ((byte*)) (struct Point[4]) points
[11] (byte*~) main::$5 ← (byte*~) main::$4 + (byte) OFFS_Y
[12] (byte~) main::$6 ← (byte) main::i * (byte) SIZEOF_POINT
[13] (byte*~) main::$7 ← (byte*~) main::$5 + (byte~) main::$6
[14] (number~) main::$8 ← (byte) main::i + (number) 4
[15] *((byte*~) main::$7) ← (number~) main::$8
[16] (byte) main::i ← (byte) main::i + rangenext(0,3)
[17] (bool~) main::$9 ← (byte) main::i != rangelast(0,3)
[18] if((bool~) main::$9) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
[19] (byte*) main::SCREEN ← ((byte*)) (number) $400
[20] (byte) main::i1 ← (byte) 0
to:main::@3
main::@3: scope:[main] from main::@2 main::@3
[21] (byte*~) main::$10 ← ((byte*)) (struct Point[4]) points
[22] (byte*~) main::$11 ← (byte*~) main::$10 + (byte) OFFS_X
[23] (byte~) main::$12 ← (byte) main::i1 * (byte) SIZEOF_POINT
[24] (byte*~) main::$13 ← (byte*~) main::$11 + (byte~) main::$12
[25] *((byte*) main::SCREEN + (byte) main::i1) ← *((byte*~) main::$13)
[26] (byte*~) main::$14 ← (byte*) main::SCREEN + (number) $28
[27] (byte*~) main::$15 ← ((byte*)) (struct Point[4]) points
[28] (byte*~) main::$16 ← (byte*~) main::$15 + (byte) OFFS_Y
[29] (byte~) main::$17 ← (byte) main::i1 * (byte) SIZEOF_POINT
[30] (byte*~) main::$18 ← (byte*~) main::$16 + (byte~) main::$17
[31] *((byte*~) main::$14 + (byte) main::i1) ← *((byte*~) main::$18)
[32] (byte) main::i1 ← (byte) main::i1 + rangenext(0,3)
[33] (bool~) main::$19 ← (byte) main::i1 != rangelast(0,3)
[34] if((bool~) main::$19) goto main::@3
to:main::@4
main::@4: scope:[main] from main::@3
to:main::@return
main::@return: scope:[main] from main::@4
[35] return
to:@return
@1: scope:[] from @begin
[36] call main
to:@end
@end: scope:[] from @1
Culled Empty Block (label) main::@4
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@begin: scope:[] from

View File

@ -1,169 +1,7 @@
PARSING src/test/kc/struct-5.kc
// Minimal struct - array of struct - far pointer math indexing
struct Point {
byte x;
byte y;
};
struct Point[4] points;
const byte SIZEOF_POINT = 2;
const byte OFFS_X = 0;
const byte OFFS_Y = 1;
void main() {
for( byte i: 0..3) {
struct Point* point_i = points+i;
*((byte*)point_i+OFFS_X) = i; // points[i].x = i;
*((byte*)point_i+OFFS_Y) = i+4; // points[i].y = i+4;
}
const byte* SCREEN = 0x0400;
for( byte i: 0..3) {
struct Point* point_i = points+i;
SCREEN[i] = *((byte*)point_i+OFFS_X); // SCREEN[i] = points[i].x;
(SCREEN+40)[i] = *((byte*)point_i+OFFS_Y); // (SCREEN+40)[i] = points[i].y;
}
}
STATEMENTS
(struct Point[4]) points ← { fill( 4, 0) }
(byte) SIZEOF_POINT ← (number) 2
(byte) OFFS_X ← (number) 0
(byte) OFFS_Y ← (number) 1
proc (void()) main()
(byte) main:::1::i ← (byte) 0
main:::1::@1:
(var) main:::1::$0 ← (struct Point[4]) points + (byte) main:::1::i
(struct Point*) main:::1::point_i ← (var) main:::1::$0
(var) main:::1::$1 ← ((byte*)) (struct Point*) main:::1::point_i
(var) main:::1::$2 ← (var) main:::1::$1 + (byte) OFFS_X
*((var) main:::1::$2) ← (byte) main:::1::i
(var) main:::1::$3 ← ((byte*)) (struct Point*) main:::1::point_i
(var) main:::1::$4 ← (var) main:::1::$3 + (byte) OFFS_Y
(var) main:::1::$5 ← (byte) main:::1::i + (number) 4
*((var) main:::1::$4) ← (var) main:::1::$5
(byte) main:::1::i ← (byte) main:::1::i + rangenext(0,3)
(var) main:::1::$6 ← (byte) main:::1::i != rangelast(0,3)
if((var) main:::1::$6) goto main:::1::@1
(byte*) main::SCREEN ← (number) $400
(byte) main:::2::i ← (byte) 0
main:::2::@1:
(var) main:::2::$0 ← (struct Point[4]) points + (byte) main:::2::i
(struct Point*) main:::2::point_i ← (var) main:::2::$0
(var) main:::2::$1 ← ((byte*)) (struct Point*) main:::2::point_i
(var) main:::2::$2 ← (var) main:::2::$1 + (byte) OFFS_X
*((byte*) main::SCREEN + (byte) main:::2::i) ← *((var) main:::2::$2)
(var) main:::2::$3 ← (byte*) main::SCREEN + (number) $28
(var) main:::2::$4 ← ((byte*)) (struct Point*) main:::2::point_i
(var) main:::2::$5 ← (var) main:::2::$4 + (byte) OFFS_Y
*((var) main:::2::$3 + (byte) main:::2::i) ← *((var) main:::2::$5)
(byte) main:::2::i ← (byte) main:::2::i + rangenext(0,3)
(var) main:::2::$6 ← (byte) main:::2::i != rangelast(0,3)
if((var) main:::2::$6) goto main:::2::@1
main::@return:
return
endproc // main()
call main
SYMBOLS
(label) @1
(label) @begin
(label) @end
(byte) OFFS_X
(byte) OFFS_Y
(byte) Point::x
(byte) Point::y
(byte) SIZEOF_POINT
(void()) main()
(struct Point*~) main::$0
(byte*~) main::$1
(byte*~) main::$10
(byte*~) main::$11
(byte*~) main::$12
(bool~) main::$13
(byte*~) main::$2
(byte*~) main::$3
(byte*~) main::$4
(number~) main::$5
(bool~) main::$6
(struct Point*~) main::$7
(byte*~) main::$8
(byte*~) main::$9
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte*) main::SCREEN
(byte) main::i
(byte) main::i1
(struct Point*) main::point_i
(struct Point*) main::point_i1
(struct Point[4]) points
Fixing pointer addition (struct Point*~) main::$0 ← (struct Point[4]) points + (byte) main::i
Fixing pointer addition (struct Point*~) main::$7 ← (struct Point[4]) points + (byte) main::i1
Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] (struct Point[4]) points ← { fill( 4, 0) }
[1] (byte) SIZEOF_POINT ← (number) 2
[2] (byte) OFFS_X ← (number) 0
[3] (byte) OFFS_Y ← (number) 1
to:@1
main: scope:[main] from
[4] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
[5] (byte~) main::$14 ← (byte) main::i * (const byte) SIZEOF_STRUCT_POINT
[6] (struct Point*~) main::$0 ← (struct Point[4]) points + (byte~) main::$14
[7] (struct Point*) main::point_i ← (struct Point*~) main::$0
[8] (byte*~) main::$1 ← ((byte*)) (struct Point*) main::point_i
[9] (byte*~) main::$2 ← (byte*~) main::$1 + (byte) OFFS_X
[10] *((byte*~) main::$2) ← (byte) main::i
[11] (byte*~) main::$3 ← ((byte*)) (struct Point*) main::point_i
[12] (byte*~) main::$4 ← (byte*~) main::$3 + (byte) OFFS_Y
[13] (number~) main::$5 ← (byte) main::i + (number) 4
[14] *((byte*~) main::$4) ← (number~) main::$5
[15] (byte) main::i ← (byte) main::i + rangenext(0,3)
[16] (bool~) main::$6 ← (byte) main::i != rangelast(0,3)
[17] if((bool~) main::$6) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
[18] (byte*) main::SCREEN ← ((byte*)) (number) $400
[19] (byte) main::i1 ← (byte) 0
to:main::@3
main::@3: scope:[main] from main::@2 main::@3
[20] (byte~) main::$15 ← (byte) main::i1 * (const byte) SIZEOF_STRUCT_POINT
[21] (struct Point*~) main::$7 ← (struct Point[4]) points + (byte~) main::$15
[22] (struct Point*) main::point_i1 ← (struct Point*~) main::$7
[23] (byte*~) main::$8 ← ((byte*)) (struct Point*) main::point_i1
[24] (byte*~) main::$9 ← (byte*~) main::$8 + (byte) OFFS_X
[25] *((byte*) main::SCREEN + (byte) main::i1) ← *((byte*~) main::$9)
[26] (byte*~) main::$10 ← (byte*) main::SCREEN + (number) $28
[27] (byte*~) main::$11 ← ((byte*)) (struct Point*) main::point_i1
[28] (byte*~) main::$12 ← (byte*~) main::$11 + (byte) OFFS_Y
[29] *((byte*~) main::$10 + (byte) main::i1) ← *((byte*~) main::$12)
[30] (byte) main::i1 ← (byte) main::i1 + rangenext(0,3)
[31] (bool~) main::$13 ← (byte) main::i1 != rangelast(0,3)
[32] if((bool~) main::$13) goto main::@3
to:main::@4
main::@4: scope:[main] from main::@3
to:main::@return
main::@return: scope:[main] from main::@4
[33] return
to:@return
@1: scope:[] from @begin
[34] call main
to:@end
@end: scope:[] from @1
Eliminating unused variable (byte) SIZEOF_POINT and assignment [1] (byte) SIZEOF_POINT ← (number) 2
Culled Empty Block (label) main::@4
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@begin: scope:[] from