From 869ce161be03bb8626bcec1f457cdeca8adc5bca Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 10 Jun 2019 01:01:36 +0200 Subject: [PATCH] Struct return values working! --- .../java/dk/camelot64/kickc/Compiler.java | 1 + ...ss1GenerateSingleStaticAssignmentForm.java | 40 +- .../kickc/passes/Pass2AssertSymbols.java | 8 +- .../dk/camelot64/kickc/test/TestPrograms.java | 2 +- src/test/ref/struct-5.asm | 60 +- src/test/ref/struct-5.cfg | 32 +- src/test/ref/struct-5.log | 823 ++++++------------ 7 files changed, 320 insertions(+), 646 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 606df498f..d07dd7ac2 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -218,6 +218,7 @@ public class Compiler { //getLog().append(program.getGraph().toString(program)); program.setGraph(new Pass1ProcedureCallsReturnValue(program).generate()); + new PassNUnwindLValueLists(program).execute(); getLog().append("\nCONTROL FLOW GRAPH SSA"); getLog().append(program.getGraph().toString(program)); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index fdae2075d..febaed25a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -35,9 +35,9 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { do { if(getLog().isVerbosePass1CreateSsa()) { getLog().append("Completing Phi functions..."); + //getLog().append(getGraph().toString(getProgram())); } done = completePhiFunctions(); - //log.append(this.controlFlowGraph.toString(symbols)); } while(!done); return false; } @@ -110,15 +110,17 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { programValue.set(version.getRef()); } // Update map of versions encountered in the block - if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.ProgramValueLValue) { - StatementAssignment assignment = (StatementAssignment) currentStmt; - LValue lValue = assignment.getlValue(); + if(currentStmt instanceof StatementLValue && programValue instanceof ProgramValue.ProgramValueLValue) { + StatementLValue statementLValue = (StatementLValue) currentStmt; + LValue lValue = statementLValue.getlValue(); if(lValue instanceof VariableRef) { - VariableRef lValueRef = (VariableRef) lValue; - Variable variable = Pass1GenerateSingleStaticAssignmentForm.this.getScope().getVariable(lValueRef); - if(variable instanceof VariableVersion) { - VariableVersion versioned = (VariableVersion) variable; - blockVersions.put(versioned.getVersionOf(), versioned); + updateBlockVersions((VariableRef) lValue, blockVersions); + } else if(lValue instanceof ValueList) { + List lValueList = ((ValueList) lValue).getList(); + for(RValue lValueElement : lValueList) { + if(lValueElement instanceof VariableRef) { + updateBlockVersions((VariableRef) lValueElement, blockVersions); + } } } } @@ -146,6 +148,15 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { } } + private void updateBlockVersions(VariableRef lValue, Map blockVersions) { + VariableRef lValueRef = lValue; + Variable variable = Pass1GenerateSingleStaticAssignmentForm.this.getScope().getVariable(lValueRef); + if(variable instanceof VariableVersion) { + VariableVersion versioned = (VariableVersion) variable; + blockVersions.put(versioned.getVersionOf(), versioned); + } + } + /** * Find and return the latest version of an rValue (if it is a non-versioned symbol). * If a version is needed and no version is found a new version is created as a phi-function. @@ -289,11 +300,11 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { for(Statement statement : block.getStatements()) { if(statement instanceof StatementLValue) { StatementLValue assignment = (StatementLValue) statement; - addSymbolToMap(symbolMap, block, assignment.getlValue()); + addSymbolToMap(assignment.getlValue(), block, symbolMap); } else if(statement instanceof StatementPhiBlock) { StatementPhiBlock phiBlock = (StatementPhiBlock) statement; for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) { - addSymbolToMap(symbolMap, block, phiVariable.getVariable()); + addSymbolToMap(phiVariable.getVariable(), block, symbolMap); } } } @@ -301,7 +312,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { return symbolMap; } - private void addSymbolToMap(Map> symbolMap, ControlFlowBlock block, dk.camelot64.kickc.model.values.LValue lValue) { + private void addSymbolToMap(LValue lValue, ControlFlowBlock block, Map> symbolMap) { if(lValue instanceof VariableRef) { Variable lValueVar = getScope().getVariable((VariableRef) lValue); if(lValueVar instanceof VariableVersion) { @@ -315,6 +326,11 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { } blockMap.put(unversioned, versioned); } + } else if(lValue instanceof ValueList) { + for(RValue lValueElement : ((ValueList) lValue).getList()) { + addSymbolToMap((LValue) lValueElement, block, symbolMap); + } + } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java index 55f1a9cd0..c6594bdaf 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.StructDefinition; import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.VariableUnversioned; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; import dk.camelot64.kickc.model.values.SymbolRef; import java.util.Collection; @@ -44,6 +45,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { if(tableSymbol instanceof VariableUnversioned) continue; if(tableSymbol instanceof ConstantVar) continue; if(tableSymbol instanceof StructDefinition) continue; + if(tableSymbol.getType() instanceof SymbolTypeStruct) continue; Symbol codeSymbol = null; String codeSymbolFullName = tableSymbol.getFullName(); for(Symbol symbol : codeSymbols) { @@ -53,7 +55,11 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { } } if(codeSymbol == null) { - throw new AssertionFailed("Compile process error. Symbol found in symbol table, but not in code. " + codeSymbolFullName); + if(tableSymbol.getType() instanceof SymbolTypeStruct) { + getLog().append("Struct no longer used in code "+codeSymbolFullName); + } else { + throw new AssertionFailed("Compile process error. Symbol found in symbol table, but not in code. " + codeSymbolFullName); + } } } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 313f0447b..78878cf7b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -82,7 +82,7 @@ public class TestPrograms { @Test public void testStruct5() throws IOException, URISyntaxException { - compileAndCompare("struct-5", log().verboseParse().verboseCreateSsa()); + compileAndCompare("struct-5"); } @Test diff --git a/src/test/ref/struct-5.asm b/src/test/ref/struct-5.asm index f63b1f446..be5881974 100644 --- a/src/test/ref/struct-5.asm +++ b/src/test/ref/struct-5.asm @@ -1,56 +1,18 @@ -// Minimal struct - array of struct - far pointer math indexing +// Minimal struct - struct return value .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" - .const OFFS_Y = 1 main: { .label SCREEN = $400 - .label point_i = 2 - .label point_i1 = 4 - ldx #0 - b1: - txa - asl - tay - tya - clc - adc #points - adc #0 - sta point_i+1 - txa - sta points,y - txa - clc - adc #4 - // points[i].x = i; - ldy #OFFS_Y - sta (point_i),y - inx - cpx #4 - bne b1 - ldx #0 - b2: - txa - asl - tay - tya - clc - adc #points - adc #0 - sta point_i1+1 - lda points,y - sta SCREEN,x - // SCREEN[i] = points[i].x; - ldy #OFFS_Y - lda (point_i1),y - sta SCREEN+$28,x - inx - cpx #4 - bne b2 + jsr point + lda #point.p_x + sta SCREEN + lda #point.p_y + sta SCREEN+1 + rts +} +point: { + .label p_x = 2 + .label p_y = 3 rts } - points: .fill 2*4, 0 diff --git a/src/test/ref/struct-5.cfg b/src/test/ref/struct-5.cfg index 6b2d4a012..d05eee137 100644 --- a/src/test/ref/struct-5.cfg +++ b/src/test/ref/struct-5.cfg @@ -9,26 +9,18 @@ [3] phi() main: scope:[main] from @1 [4] phi() + [5] call point to:main::@1 -main::@1: scope:[main] from main main::@1 - [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) - [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 - [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 - [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 - [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 - [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 - [11] (byte) main::i#1 ← ++ (byte) main::i#2 - [12] if((byte) main::i#1!=(byte) 4) goto main::@1 - to:main::@2 -main::@2: scope:[main] from main::@1 main::@2 - [13] (byte) main::i1#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::i1#1 ) - [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 - [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 - [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) - [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) - [18] (byte) main::i1#1 ← ++ (byte) main::i1#2 - [19] if((byte) main::i1#1!=(byte) 4) goto main::@2 +main::@1: scope:[main] from main + [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 + [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 to:main::@return -main::@return: scope:[main] from main::@2 - [20] return +main::@return: scope:[main] from main::@1 + [8] return + to:@return +point: scope:[point] from main + [9] phi() + to:point::@return +point::@return: scope:[point] from point + [10] return to:@return diff --git a/src/test/ref/struct-5.log b/src/test/ref/struct-5.log index 39fb49656..52e20b748 100644 --- a/src/test/ref/struct-5.log +++ b/src/test/ref/struct-5.log @@ -1,234 +1,194 @@ -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 +Created struct value member variable (byte) main::q_x +Created struct value member variable (byte) main::q_y +Converted struct value to member variables (struct Point) main::q +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) point::return_x +Created struct value member variable (byte) point::return_y +Converted struct value to member variables (struct Point) point::return +Created struct value member variable (byte) point::p_x +Created struct value member variable (byte) point::p_y +Converted struct value to member variables (struct Point) point::p +Adding struct value member variable default initializer (byte) main::q_x ← (byte) 0 +Adding struct value member variable default initializer (byte) main::q_y ← (byte) 0 +Converted procedure call LValue to member variables { (byte) main::$0_x, (byte) main::$0_y } ← call point +Adding struct value member variable copy (byte) main::q_x ← (byte) main::$0_x +Adding struct value member variable copy (byte) main::q_y ← (byte) main::$0_y +Adding struct value list initializer (byte) point::p_x ← (number) 2 +Adding struct value list initializer (byte) point::p_y ← (number) 3 +Adding struct value member variable copy (byte) point::return_x ← (byte) point::p_x +Adding struct value member variable copy (byte) point::return_y ← (byte) point::p_y +Adding struct value member variable copy (byte) point::return_x ← (byte) point::return_x +Adding struct value member variable copy (byte) point::return_y ← (byte) point::return_y +Converted procedure struct return value to member variables return { (byte) point::return_x, (byte) point::return_y } +Replacing struct member reference (struct Point) main::q.x with member variable reference (byte) main::q_x +Replacing struct member reference (struct Point) main::q.y with member variable reference (byte) main::q_y Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400 -Culled Empty Block (label) main::@4 +Identified constant variable (byte) point::p_x +Identified constant variable (byte) point::p_y +Culled Empty Block (label) @1 +Culled Empty Block (label) point::@1 +Unwinding list assignment { (byte) main::$0_x, (byte) main::$0_y } ← { (byte) point::return_x, (byte) point::return_y } +Unwinding list assignment { (byte) point::return_x#0, (byte) point::return_y#0 } ← { (byte) point::return_x#2, (byte) point::return_y#2 } CONTROL FLOW GRAPH SSA @begin: scope:[] from - (struct Point[4]) points#0 ← { fill( 4, 0) } - (byte) OFFS_X#0 ← (number) 0 - (byte) OFFS_Y#0 ← (number) 1 - to:@1 -main: scope:[main] from @1 - (byte) main::i#0 ← (byte) 0 + to:@2 +main: scope:[main] from @2 + (byte) main::q_x#0 ← (byte) 0 + (byte) main::q_y#0 ← (byte) 0 + call point + (byte) point::return_x#0 ← (byte) point::return_x#2 + (byte) point::return_y#0 ← (byte) point::return_y#2 to:main::@1 -main::@1: scope:[main] from main main::@1 - (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) - (byte~) main::$14 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT - (struct Point*~) main::$0 ← (struct Point[4]) points#0 + (byte~) main::$14 - (struct Point*) main::point_i#0 ← (struct Point*~) main::$0 - (byte*~) main::$1 ← ((byte*)) (struct Point*) main::point_i#0 - (byte*~) main::$2 ← (byte*~) main::$1 + (byte) OFFS_X#0 - *((byte*~) main::$2) ← (byte) main::i#2 - (byte*~) main::$3 ← ((byte*)) (struct Point*) main::point_i#0 - (byte*~) main::$4 ← (byte*~) main::$3 + (byte) OFFS_Y#0 - (number~) main::$5 ← (byte) main::i#2 + (number) 4 - *((byte*~) main::$4) ← (number~) main::$5 - (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,3) - (bool~) main::$6 ← (byte) main::i#1 != rangelast(0,3) - if((bool~) main::$6) goto main::@1 - to:main::@2 -main::@2: scope:[main] from main::@1 +main::@1: scope:[main] from main + (byte) point::return_y#3 ← phi( main/(byte) point::return_y#0 ) + (byte) point::return_x#3 ← phi( main/(byte) point::return_x#0 ) + (byte) main::$0_x ← (byte) point::return_x#3 + (byte) main::$0_y ← (byte) point::return_y#3 + (byte) main::q_x#1 ← (byte) main::$0_x + (byte) main::q_y#1 ← (byte) main::$0_y (byte*) main::SCREEN#0 ← ((byte*)) (number) $400 - (byte) main::i1#0 ← (byte) 0 - to:main::@3 -main::@3: scope:[main] from main::@2 main::@3 - (byte) main::i1#2 ← phi( main::@2/(byte) main::i1#0 main::@3/(byte) main::i1#1 ) - (byte~) main::$15 ← (byte) main::i1#2 * (const byte) SIZEOF_STRUCT_POINT - (struct Point*~) main::$7 ← (struct Point[4]) points#0 + (byte~) main::$15 - (struct Point*) main::point_i1#0 ← (struct Point*~) main::$7 - (byte*~) main::$8 ← ((byte*)) (struct Point*) main::point_i1#0 - (byte*~) main::$9 ← (byte*~) main::$8 + (byte) OFFS_X#0 - *((byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*~) main::$9) - (byte*~) main::$10 ← (byte*) main::SCREEN#0 + (number) $28 - (byte*~) main::$11 ← ((byte*)) (struct Point*) main::point_i1#0 - (byte*~) main::$12 ← (byte*~) main::$11 + (byte) OFFS_Y#0 - *((byte*~) main::$10 + (byte) main::i1#2) ← *((byte*~) main::$12) - (byte) main::i1#1 ← (byte) main::i1#2 + rangenext(0,3) - (bool~) main::$13 ← (byte) main::i1#1 != rangelast(0,3) - if((bool~) main::$13) goto main::@3 + *((byte*) main::SCREEN#0 + (number) 0) ← (byte) main::q_x#1 + *((byte*) main::SCREEN#0 + (number) 1) ← (byte) main::q_y#1 to:main::@return -main::@return: scope:[main] from main::@3 +main::@return: scope:[main] from main::@1 return to:@return -@1: scope:[] from @begin +point: scope:[point] from main + (byte) point::p_x#0 ← (number) 2 + (byte) point::p_y#0 ← (number) 3 + (byte) point::return_x#1 ← (byte) point::p_x#0 + (byte) point::return_y#1 ← (byte) point::p_y#0 + to:point::@return +point::@return: scope:[point] from point + (byte) point::return_y#4 ← phi( point/(byte) point::return_y#1 ) + (byte) point::return_x#4 ← phi( point/(byte) point::return_x#1 ) + (byte) point::return_x#2 ← (byte) point::return_x#4 + (byte) point::return_y#2 ← (byte) point::return_y#4 + return + to:@return +@2: scope:[] from @begin call main - to:@2 -@2: scope:[] from @1 + to:@3 +@3: scope:[] from @2 to:@end -@end: scope:[] from @2 +@end: scope:[] from @3 SYMBOL TABLE SSA -(label) @1 (label) @2 +(label) @3 (label) @begin (label) @end -(byte) OFFS_X -(byte) OFFS_X#0 -(byte) OFFS_Y -(byte) OFFS_Y#0 (byte) Point::x (byte) Point::y -(const byte) SIZEOF_STRUCT_POINT = (byte) 2 (void()) main() -(struct Point*~) main::$0 -(byte*~) main::$1 -(byte*~) main::$10 -(byte*~) main::$11 -(byte*~) main::$12 -(bool~) main::$13 -(byte~) main::$14 -(byte~) main::$15 -(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 +(struct Point~) main::$0 +(byte) main::$0_x +(byte) main::$0_y (label) main::@1 -(label) main::@2 -(label) main::@3 (label) main::@return (byte*) main::SCREEN (byte*) main::SCREEN#0 -(byte) main::i -(byte) main::i#0 -(byte) main::i#1 -(byte) main::i#2 -(byte) main::i1 -(byte) main::i1#0 -(byte) main::i1#1 -(byte) main::i1#2 -(struct Point*) main::point_i -(struct Point*) main::point_i#0 -(struct Point*) main::point_i1 -(struct Point*) main::point_i1#0 -(struct Point[4]) points -(struct Point[4]) points#0 +(struct Point) main::q +(byte) main::q_x +(byte) main::q_x#0 +(byte) main::q_x#1 +(byte) main::q_y +(byte) main::q_y#0 +(byte) main::q_y#1 +(struct Point()) point() +(label) point::@return +(struct Point) point::p +(byte) point::p_x +(byte) point::p_x#0 +(byte) point::p_y +(byte) point::p_y#0 +(struct Point) point::return +(byte) point::return_x +(byte) point::return_x#0 +(byte) point::return_x#1 +(byte) point::return_x#2 +(byte) point::return_x#3 +(byte) point::return_x#4 +(byte) point::return_y +(byte) point::return_y#0 +(byte) point::return_y#1 +(byte) point::return_y#2 +(byte) point::return_y#3 +(byte) point::return_y#4 -Adding number conversion cast (unumber) 0 in (byte) OFFS_X#0 ← (number) 0 -Adding number conversion cast (unumber) 1 in (byte) OFFS_Y#0 ← (number) 1 -Adding number conversion cast (unumber) 4 in (number~) main::$5 ← (byte) main::i#2 + (number) 4 -Adding number conversion cast (unumber) main::$5 in (number~) main::$5 ← (byte) main::i#2 + (unumber)(number) 4 -Adding number conversion cast (unumber) $28 in (byte*~) main::$10 ← (byte*) main::SCREEN#0 + (number) $28 +Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← (byte) main::q_x#1 +Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← (byte) main::q_y#1 +Adding number conversion cast (unumber) 2 in (byte) point::p_x#0 ← (number) 2 +Adding number conversion cast (unumber) 3 in (byte) point::p_y#0 ← (number) 3 Successful SSA optimization PassNAddNumberTypeConversions -Inlining cast (byte) OFFS_X#0 ← (unumber)(number) 0 -Inlining cast (byte) OFFS_Y#0 ← (unumber)(number) 1 -Inlining cast (byte*~) main::$1 ← (byte*)(struct Point*) main::point_i#0 -Inlining cast (byte*~) main::$3 ← (byte*)(struct Point*) main::point_i#0 Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400 -Inlining cast (byte*~) main::$8 ← (byte*)(struct Point*) main::point_i1#0 -Inlining cast (byte*~) main::$11 ← (byte*)(struct Point*) main::point_i1#0 +Inlining cast (byte) point::p_x#0 ← (unumber)(number) 2 +Inlining cast (byte) point::p_y#0 ← (unumber)(number) 3 Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 Simplifying constant integer cast 1 -Simplifying constant integer cast 4 -Simplifying constant pointer cast (byte*) 1024 -Simplifying constant integer cast $28 +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) 4 -Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) 2 +Finalized unsigned number type (byte) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions -Inferred type updated to byte in (unumber~) main::$5 ← (byte) main::i#2 + (byte) 4 -Alias (struct Point*) main::point_i#0 = (struct Point*~) main::$0 -Alias (struct Point*) main::point_i1#0 = (struct Point*~) main::$7 +Alias (byte) point::return_x#0 = (byte) point::return_x#3 +Alias (byte) point::return_y#0 = (byte) point::return_y#3 +Alias (byte) main::q_x#1 = (byte) main::$0_x +Alias (byte) main::q_y#1 = (byte) main::$0_y +Alias (byte) point::p_x#0 = (byte) point::return_x#1 (byte) point::return_x#4 (byte) point::return_x#2 +Alias (byte) point::p_y#0 = (byte) point::return_y#1 (byte) point::return_y#4 (byte) point::return_y#2 Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$6 [17] if((byte) main::i#1!=rangelast(0,3)) goto main::@1 -Simple Condition (bool~) main::$13 [33] if((byte) main::i1#1!=rangelast(0,3)) goto main::@3 -Successful SSA optimization Pass2ConditionalJumpSimplification -Constant right-side identified [0] (struct Point[4]) points#0 ← { fill( 4, 0) } -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const struct Point[4]) points#0 = { fill( 4, 0) } -Constant (const byte) OFFS_X#0 = 0 -Constant (const byte) OFFS_Y#0 = 1 -Constant (const byte) main::i#0 = 0 +Constant (const byte) main::q_x#0 = 0 +Constant (const byte) main::q_y#0 = 0 Constant (const byte*) main::SCREEN#0 = (byte*) 1024 -Constant (const byte) main::i1#0 = 0 +Constant (const byte) point::p_x#0 = 2 +Constant (const byte) point::p_y#0 = 3 Successful SSA optimization Pass2ConstantIdentification -Resolved ranged next value [15] main::i#1 ← ++ main::i#2 to ++ -Resolved ranged comparison value [17] if(main::i#1!=rangelast(0,3)) goto main::@1 to (number) 4 -Resolved ranged next value [31] main::i1#1 ← ++ main::i1#2 to ++ -Resolved ranged comparison value [33] if(main::i1#1!=rangelast(0,3)) goto main::@3 to (number) 4 -Converting *(pointer+n) to pointer[n] [10] *((byte*~) main::$2) ← (byte) main::i#2 -- *(main::$1 + OFFS_X#0) -Converting *(pointer+n) to pointer[n] [14] *((byte*~) main::$4) ← (byte~) main::$5 -- *(main::$3 + OFFS_Y#0) -Converting *(pointer+n) to pointer[n] [26] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*~) main::$9) -- *(main::$8 + OFFS_X#0) -Converting *(pointer+n) to pointer[n] [30] *((byte*~) main::$10 + (byte) main::i1#2) ← *((byte*~) main::$12) -- *(main::$11 + OFFS_Y#0) -Successful SSA optimization Pass2InlineDerefIdx -Simplifying expression containing zero main::$1 in [9] (byte*~) main::$2 ← (byte*~) main::$1 + (const byte) OFFS_X#0 -Simplifying expression containing zero main::$1 in [10] *((byte*~) main::$1 + (const byte) OFFS_X#0) ← (byte) main::i#2 -Simplifying expression containing zero main::$8 in [25] (byte*~) main::$9 ← (byte*~) main::$8 + (const byte) OFFS_X#0 -Simplifying expression containing zero main::$8 in [26] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*~) main::$8 + (const byte) OFFS_X#0) +Constant (const byte) point::return_x#0 = point::p_x#0 +Constant (const byte) point::return_y#0 = point::p_y#0 +Successful SSA optimization Pass2ConstantIdentification +Constant (const byte) main::q_x#1 = point::return_x#0 +Constant (const byte) main::q_y#1 = point::return_y#0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero main::SCREEN#0 in [11] *((const byte*) main::SCREEN#0 + (byte) 0) ← (const byte) main::q_x#1 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte*~) main::$2 and assignment [4] (byte*~) main::$2 ← (byte*~) main::$1 -Eliminating unused variable (byte*~) main::$4 and assignment [7] (byte*~) main::$4 ← (byte*~) main::$3 + (const byte) OFFS_Y#0 -Eliminating unused variable (byte*~) main::$9 and assignment [16] (byte*~) main::$9 ← (byte*~) main::$8 -Eliminating unused variable (byte*~) main::$12 and assignment [20] (byte*~) main::$12 ← (byte*~) main::$11 + (const byte) OFFS_Y#0 -Eliminating unused constant (const byte) OFFS_X#0 +Eliminating unused constant (const byte) main::q_x#0 +Eliminating unused constant (const byte) main::q_y#0 Successful SSA optimization PassNEliminateUnusedVars -Adding number conversion cast (unumber) 4 in if((byte) main::i#1!=(number) 4) goto main::@1 -Adding number conversion cast (unumber) 4 in if((byte) main::i1#1!=(number) 4) goto main::@3 -Successful SSA optimization PassNAddNumberTypeConversions -Simplifying constant integer cast 4 -Simplifying constant integer cast 4 -Successful SSA optimization PassNCastSimplification -Finalized unsigned number type (byte) 4 -Finalized unsigned number type (byte) 4 -Successful SSA optimization PassNFinalizeNumberTypeConversions -Constant right-side identified [15] (byte*~) main::$10 ← (const byte*) main::SCREEN#0 + (byte) $28 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const byte*) main::$10 = main::SCREEN#0+$28 -Successful SSA optimization Pass2ConstantIdentification -Converting *(pointer+n) to pointer[n] [4] *((byte*~) main::$1) ← (byte) main::i#2 -- *((byte*)points#0 + main::$14) -Converting *(pointer+n) to pointer[n] [14] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*~) main::$8) -- *((byte*)points#0 + main::$15) -Successful SSA optimization Pass2InlineDerefIdx -Eliminating unused variable (byte*~) main::$1 and assignment [3] (byte*~) main::$1 ← (byte*)(struct Point*) main::point_i#0 -Eliminating unused variable (byte*~) main::$8 and assignment [13] (byte*~) main::$8 ← (byte*)(struct Point*) main::point_i1#0 -Successful SSA optimization PassNEliminateUnusedVars -Constant value identified (byte*)points#0 in [3] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 -Constant value identified (byte*)points#0 in [12] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) -Successful SSA optimization Pass2ConstantValues -Inlining Noop Cast [4] (byte*~) main::$3 ← (byte*)(struct Point*) main::point_i#0 keeping main::point_i#0 -Inlining Noop Cast [13] (byte*~) main::$11 ← (byte*)(struct Point*) main::point_i1#0 keeping main::point_i1#0 -Successful SSA optimization Pass2NopCastInlining -Rewriting multiplication to use shift [1] (byte~) main::$14 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT -Rewriting multiplication to use shift [10] (byte~) main::$15 ← (byte) main::i1#2 * (const byte) SIZEOF_STRUCT_POINT -Successful SSA optimization Pass2MultiplyToShiftRewriting -Inlining constant with var siblings (const byte) main::i#0 -Inlining constant with var siblings (const byte) main::i1#0 -Constant inlined main::i#0 = (byte) 0 -Constant inlined main::i1#0 = (byte) 0 -Constant inlined main::$10 = (const byte*) main::SCREEN#0+(byte) $28 +Constant inlined main::q_x#1 = (const byte) point::p_x#0 +Constant inlined point::return_y#0 = (const byte) point::p_y#0 +Constant inlined point::return_x#0 = (const byte) point::p_x#0 +Constant inlined main::q_y#1 = (const byte) point::p_y#0 Successful SSA optimization Pass2ConstantInlining -Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT -Successful SSA optimization PassNEliminateUnusedVars -Added new block during phi lifting main::@5(between main::@1 and main::@1) -Added new block during phi lifting main::@6(between main::@3 and main::@3) +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 @3 Adding NOP phi() at start of @end Adding NOP phi() at start of main -Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of point CALL GRAPH Calls in [] to main:2 +Calls in [main] to point:6 -Created 2 initial phi equivalence classes -Coalesced [23] main::i1#3 ← main::i1#1 -Coalesced [24] main::i#3 ← main::i#1 -Coalesced down to 2 phi equivalence classes -Culled Empty Block (label) @2 -Culled Empty Block (label) main::@2 -Culled Empty Block (label) main::@6 -Culled Empty Block (label) main::@5 -Renumbering block main::@3 to main::@2 +Created 0 initial phi equivalence classes +Coalesced down to 0 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 +Adding NOP phi() at start of point FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -242,86 +202,51 @@ FINAL CONTROL FLOW GRAPH [3] phi() main: scope:[main] from @1 [4] phi() + [5] call point to:main::@1 -main::@1: scope:[main] from main main::@1 - [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) - [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 - [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 - [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 - [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 - [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 - [11] (byte) main::i#1 ← ++ (byte) main::i#2 - [12] if((byte) main::i#1!=(byte) 4) goto main::@1 - to:main::@2 -main::@2: scope:[main] from main::@1 main::@2 - [13] (byte) main::i1#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::i1#1 ) - [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 - [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 - [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) - [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) - [18] (byte) main::i1#1 ← ++ (byte) main::i1#2 - [19] if((byte) main::i1#1!=(byte) 4) goto main::@2 +main::@1: scope:[main] from main + [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 + [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 to:main::@return -main::@return: scope:[main] from main::@2 - [20] return +main::@return: scope:[main] from main::@1 + [8] return + to:@return +point: scope:[point] from main + [9] phi() + to:point::@return +point::@return: scope:[point] from point + [10] return to:@return VARIABLE REGISTER WEIGHTS -(byte) OFFS_X -(byte) OFFS_Y (byte) Point::x (byte) Point::y (void()) main() -(byte~) main::$14 16.5 -(byte~) main::$15 16.5 -(byte~) main::$5 22.0 +(struct Point~) main::$0 (byte*) main::SCREEN -(byte) main::i -(byte) main::i#1 16.5 -(byte) main::i#2 9.166666666666666 -(byte) main::i1 -(byte) main::i1#1 16.5 -(byte) main::i1#2 11.0 -(struct Point*) main::point_i -(struct Point*) main::point_i#0 3.6666666666666665 -(struct Point*) main::point_i1 -(struct Point*) main::point_i1#0 5.5 -(struct Point[4]) points +(struct Point) main::q +(byte) main::q_x +(byte) main::q_y +(struct Point()) point() +(struct Point) point::p +(byte) point::p_x +(byte) point::p_y +(struct Point) point::return +(byte) point::return_x +(byte) point::return_y Initial phi equivalence classes -[ main::i#2 main::i#1 ] -[ main::i1#2 main::i1#1 ] -Added variable main::$14 to zero page equivalence class [ main::$14 ] -Added variable main::point_i#0 to zero page equivalence class [ main::point_i#0 ] -Added variable main::$5 to zero page equivalence class [ main::$5 ] -Added variable main::$15 to zero page equivalence class [ main::$15 ] -Added variable main::point_i1#0 to zero page equivalence class [ main::point_i1#0 ] Complete equivalence classes -[ main::i#2 main::i#1 ] -[ main::i1#2 main::i1#1 ] -[ main::$14 ] -[ main::point_i#0 ] -[ main::$5 ] -[ main::$15 ] -[ main::point_i1#0 ] -Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Allocated zp ZP_BYTE:3 [ main::i1#2 main::i1#1 ] -Allocated zp ZP_BYTE:4 [ main::$14 ] -Allocated zp ZP_WORD:5 [ main::point_i#0 ] -Allocated zp ZP_BYTE:7 [ main::$5 ] -Allocated zp ZP_BYTE:8 [ main::$15 ] -Allocated zp ZP_WORD:9 [ main::point_i1#0 ] INITIAL ASM //SEG0 File Comments -// Minimal struct - array of struct - far pointer math indexing +// Minimal struct - struct return value //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" //SEG2 Global Constants & labels - .const OFFS_Y = 1 //SEG3 @begin bbegin: //SEG4 [1] phi from @begin to @1 [phi:@begin->@1] @@ -341,161 +266,59 @@ bend: //SEG10 main main: { .label SCREEN = $400 - .label _5 = 7 - .label _14 = 4 - .label _15 = 8 - .label point_i = 5 - .label i = 2 - .label point_i1 = 9 - .label i1 = 3 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - b1_from_main: - //SEG12 [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 - lda #0 - sta i + //SEG11 [5] call point + //SEG12 [9] phi from main to point [phi:main->point] + point_from_main: + jsr point jmp b1 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - b1_from_b1: - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - jmp b1 - //SEG15 main::@1 + //SEG13 main::@1 b1: - //SEG16 [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 -- vbuz1=vbuz2_rol_1 - lda i - asl - sta _14 - //SEG17 [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 -- pssz1=pssc1_plus_vbuz2 - lda _14 - clc - adc #points - adc #0 - sta point_i+1 - //SEG18 [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 -- pbuc1_derefidx_vbuz1=vbuz2 - lda i - ldy _14 - sta points,y - //SEG19 [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 -- vbuz1=vbuz2_plus_vbuc1 - lax i - axs #-[4] - stx _5 - //SEG20 [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 -- pbuz1_derefidx_vbuc1=vbuz2 - // points[i].x = i; - lda _5 - ldy #OFFS_Y - sta (point_i),y - //SEG21 [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 - inc i - //SEG22 [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 - lda #4 - cmp i - bne b1_from_b1 - //SEG23 [13] phi from main::@1 to main::@2 [phi:main::@1->main::@2] - b2_from_b1: - //SEG24 [13] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1 - lda #0 - sta i1 - jmp b2 - //SEG25 [13] phi from main::@2 to main::@2 [phi:main::@2->main::@2] - b2_from_b2: - //SEG26 [13] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy - jmp b2 - //SEG27 main::@2 - b2: - //SEG28 [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 -- vbuz1=vbuz2_rol_1 - lda i1 - asl - sta _15 - //SEG29 [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 -- pssz1=pssc1_plus_vbuz2 - lda _15 - clc - adc #points - adc #0 - sta point_i1+1 - //SEG30 [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2 - ldy _15 - lda points,y - ldy i1 - sta SCREEN,y - //SEG31 [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuc2 - // SCREEN[i] = points[i].x; - ldx i1 - ldy #OFFS_Y - lda (point_i1),y - sta SCREEN+$28,x - //SEG32 [18] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuz1=_inc_vbuz1 - inc i1 - //SEG33 [19] if((byte) main::i1#1!=(byte) 4) goto main::@2 -- vbuz1_neq_vbuc1_then_la1 - lda #4 - cmp i1 - bne b2_from_b2 + //SEG14 [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 -- _deref_pbuc1=vbuc2 + lda #point.p_x + sta SCREEN + //SEG15 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 -- _deref_pbuc1=vbuc2 + lda #point.p_y + sta SCREEN+1 jmp breturn - //SEG34 main::@return + //SEG16 main::@return breturn: - //SEG35 [20] return + //SEG17 [8] return + rts +} +//SEG18 point +point: { + .label p_x = 2 + .label p_y = 3 + jmp breturn + //SEG19 point::@return + breturn: + //SEG20 [10] return rts } - points: .fill 2*4, 0 REGISTER UPLIFT POTENTIAL REGISTERS -Statement [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::$14 ] ( main:2 [ main::i#2 main::$14 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Statement [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 [ main::i#2 main::$14 main::point_i#0 ] ( main:2 [ main::i#2 main::$14 main::point_i#0 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ main::$14 ] -Statement [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 [ main::i#2 main::point_i#0 ] ( main:2 [ main::i#2 main::point_i#0 ] ) always clobbers reg byte a -Statement [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 [ main::i#2 main::point_i#0 main::$5 ] ( main:2 [ main::i#2 main::point_i#0 main::$5 ] ) always clobbers reg byte a -Statement [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte y -Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Statement [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 [ main::i1#2 main::$15 ] ( main:2 [ main::i1#2 main::$15 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::i1#2 main::i1#1 ] -Statement [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 [ main::i1#2 main::$15 main::point_i1#0 ] ( main:2 [ main::i1#2 main::$15 main::point_i1#0 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:8 [ main::$15 ] -Statement [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) [ main::i1#2 main::point_i1#0 ] ( main:2 [ main::i1#2 main::point_i1#0 ] ) always clobbers reg byte a -Statement [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) [ main::i1#2 ] ( main:2 [ main::i1#2 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ main::i1#2 main::i1#1 ] -Statement [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::$14 ] ( main:2 [ main::i#2 main::$14 ] ) always clobbers reg byte a -Statement [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 [ main::i#2 main::$14 main::point_i#0 ] ( main:2 [ main::i#2 main::$14 main::point_i#0 ] ) always clobbers reg byte a -Statement [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 [ main::i#2 main::point_i#0 ] ( main:2 [ main::i#2 main::point_i#0 ] ) always clobbers reg byte a -Statement [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 [ main::i#2 main::point_i#0 main::$5 ] ( main:2 [ main::i#2 main::point_i#0 main::$5 ] ) always clobbers reg byte a -Statement [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte y -Statement [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 [ main::i1#2 main::$15 ] ( main:2 [ main::i1#2 main::$15 ] ) always clobbers reg byte a -Statement [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 [ main::i1#2 main::$15 main::point_i1#0 ] ( main:2 [ main::i1#2 main::$15 main::point_i1#0 ] ) always clobbers reg byte a -Statement [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) [ main::i1#2 main::point_i1#0 ] ( main:2 [ main::i1#2 main::point_i1#0 ] ) always clobbers reg byte a -Statement [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) [ main::i1#2 ] ( main:2 [ main::i1#2 ] ) always clobbers reg byte a reg byte y -Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , -Potential registers zp ZP_BYTE:3 [ main::i1#2 main::i1#1 ] : zp ZP_BYTE:3 , reg byte x , -Potential registers zp ZP_BYTE:4 [ main::$14 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , -Potential registers zp ZP_WORD:5 [ main::point_i#0 ] : zp ZP_WORD:5 , -Potential registers zp ZP_BYTE:7 [ main::$5 ] : zp ZP_BYTE:7 , reg byte a , reg byte x , reg byte y , -Potential registers zp ZP_BYTE:8 [ main::$15 ] : zp ZP_BYTE:8 , reg byte x , reg byte y , -Potential registers zp ZP_WORD:9 [ main::point_i1#0 ] : zp ZP_WORD:9 , +Statement [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 [ ] ( main:2 [ ] ) always clobbers reg byte a REGISTER UPLIFT SCOPES -Uplift Scope [main] 27.5: zp ZP_BYTE:3 [ main::i1#2 main::i1#1 ] 25.67: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:7 [ main::$5 ] 16.5: zp ZP_BYTE:4 [ main::$14 ] 16.5: zp ZP_BYTE:8 [ main::$15 ] 5.5: zp ZP_WORD:9 [ main::point_i1#0 ] 3.67: zp ZP_WORD:5 [ main::point_i#0 ] Uplift Scope [Point] +Uplift Scope [main] +Uplift Scope [point] Uplift Scope [] -Uplifting [main] best 1258 combination reg byte x [ main::i1#2 main::i1#1 ] reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$5 ] reg byte y [ main::$14 ] zp ZP_BYTE:8 [ main::$15 ] zp ZP_WORD:9 [ main::point_i1#0 ] zp ZP_WORD:5 [ main::point_i#0 ] -Limited combination testing to 100 combinations of 144 possible. -Uplifting [Point] best 1258 combination -Uplifting [] best 1258 combination -Attempting to uplift remaining variables inzp ZP_BYTE:8 [ main::$15 ] -Uplifting [main] best 1208 combination reg byte y [ main::$15 ] -Allocated (was zp ZP_WORD:5) zp ZP_WORD:2 [ main::point_i#0 ] -Allocated (was zp ZP_WORD:9) zp ZP_WORD:4 [ main::point_i1#0 ] +Uplifting [Point] best 78 combination +Uplifting [main] best 78 combination +Uplifting [point] best 78 combination +Uplifting [] best 78 combination ASSEMBLER BEFORE OPTIMIZATION //SEG0 File Comments -// Minimal struct - array of struct - far pointer math indexing +// Minimal struct - struct return value //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" //SEG2 Global Constants & labels - .const OFFS_Y = 1 //SEG3 @begin bbegin: //SEG4 [1] phi from @begin to @1 [phi:@begin->@1] @@ -515,118 +338,57 @@ bend: //SEG10 main main: { .label SCREEN = $400 - .label point_i = 2 - .label point_i1 = 4 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - b1_from_main: - //SEG12 [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 - ldx #0 + //SEG11 [5] call point + //SEG12 [9] phi from main to point [phi:main->point] + point_from_main: + jsr point jmp b1 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - b1_from_b1: - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - jmp b1 - //SEG15 main::@1 + //SEG13 main::@1 b1: - //SEG16 [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 -- vbuyy=vbuxx_rol_1 - txa - asl - tay - //SEG17 [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 -- pssz1=pssc1_plus_vbuyy - tya - clc - adc #points - adc #0 - sta point_i+1 - //SEG18 [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 -- pbuc1_derefidx_vbuyy=vbuxx - txa - sta points,y - //SEG19 [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 -- vbuaa=vbuxx_plus_vbuc1 - txa - clc - adc #4 - //SEG20 [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 -- pbuz1_derefidx_vbuc1=vbuaa - // points[i].x = i; - ldy #OFFS_Y - sta (point_i),y - //SEG21 [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx - inx - //SEG22 [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #4 - bne b1_from_b1 - //SEG23 [13] phi from main::@1 to main::@2 [phi:main::@1->main::@2] - b2_from_b1: - //SEG24 [13] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1 - ldx #0 - jmp b2 - //SEG25 [13] phi from main::@2 to main::@2 [phi:main::@2->main::@2] - b2_from_b2: - //SEG26 [13] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy - jmp b2 - //SEG27 main::@2 - b2: - //SEG28 [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 -- vbuyy=vbuxx_rol_1 - txa - asl - tay - //SEG29 [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 -- pssz1=pssc1_plus_vbuyy - tya - clc - adc #points - adc #0 - sta point_i1+1 - //SEG30 [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy - lda points,y - sta SCREEN,x - //SEG31 [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuc2 - // SCREEN[i] = points[i].x; - ldy #OFFS_Y - lda (point_i1),y - sta SCREEN+$28,x - //SEG32 [18] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuxx=_inc_vbuxx - inx - //SEG33 [19] if((byte) main::i1#1!=(byte) 4) goto main::@2 -- vbuxx_neq_vbuc1_then_la1 - cpx #4 - bne b2_from_b2 + //SEG14 [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 -- _deref_pbuc1=vbuc2 + lda #point.p_x + sta SCREEN + //SEG15 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 -- _deref_pbuc1=vbuc2 + lda #point.p_y + sta SCREEN+1 jmp breturn - //SEG34 main::@return + //SEG16 main::@return breturn: - //SEG35 [20] return + //SEG17 [8] return + rts +} +//SEG18 point +point: { + .label p_x = 2 + .label p_y = 3 + jmp breturn + //SEG19 point::@return + breturn: + //SEG20 [10] return rts } - points: .fill 2*4, 0 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 label b1_from_b1 with b1 -Replacing label b2_from_b2 with b2 Removing instruction b1_from_bbegin: Removing instruction b1: Removing instruction main_from_b1: Removing instruction bend_from_b1: -Removing instruction b1_from_b1: -Removing instruction b2_from_b2: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction bend: -Removing instruction b1_from_main: -Removing instruction b2_from_b1: +Removing instruction point_from_main: +Removing instruction 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 jmp b1 -Removing instruction jmp b2 -Succesful ASM optimization Pass5NextJumpElimination Removing instruction bbegin: Succesful ASM optimization Pass5UnusedLabelElimination @@ -634,53 +396,40 @@ FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end -(byte) OFFS_X -(byte) OFFS_Y -(const byte) OFFS_Y#0 OFFS_Y = (byte) 1 (byte) Point::x (byte) Point::y (void()) main() -(byte~) main::$14 reg byte y 16.5 -(byte~) main::$15 reg byte y 16.5 -(byte~) main::$5 reg byte a 22.0 +(struct Point~) main::$0 (label) main::@1 -(label) main::@2 (label) main::@return (byte*) main::SCREEN (const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 -(byte) main::i -(byte) main::i#1 reg byte x 16.5 -(byte) main::i#2 reg byte x 9.166666666666666 -(byte) main::i1 -(byte) main::i1#1 reg byte x 16.5 -(byte) main::i1#2 reg byte x 11.0 -(struct Point*) main::point_i -(struct Point*) main::point_i#0 point_i zp ZP_WORD:2 3.6666666666666665 -(struct Point*) main::point_i1 -(struct Point*) main::point_i1#0 point_i1 zp ZP_WORD:4 5.5 -(struct Point[4]) points -(const struct Point[4]) points#0 points = { fill( 4, 0) } +(struct Point) main::q +(byte) main::q_x +(byte) main::q_y +(struct Point()) point() +(label) point::@return +(struct Point) point::p +(byte) point::p_x +(const byte) point::p_x#0 p_x = (byte) 2 +(byte) point::p_y +(const byte) point::p_y#0 p_y = (byte) 3 +(struct Point) point::return +(byte) point::return_x +(byte) point::return_y -reg byte x [ main::i#2 main::i#1 ] -reg byte x [ main::i1#2 main::i1#1 ] -reg byte y [ main::$14 ] -zp ZP_WORD:2 [ main::point_i#0 ] -reg byte a [ main::$5 ] -reg byte y [ main::$15 ] -zp ZP_WORD:4 [ main::point_i1#0 ] FINAL ASSEMBLER -Score: 1046 +Score: 30 //SEG0 File Comments -// Minimal struct - array of struct - far pointer math indexing +// Minimal struct - struct return value //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" //SEG2 Global Constants & labels - .const OFFS_Y = 1 //SEG3 @begin //SEG4 [1] phi from @begin to @1 [phi:@begin->@1] //SEG5 @1 @@ -691,78 +440,26 @@ Score: 1046 //SEG10 main main: { .label SCREEN = $400 - .label point_i = 2 - .label point_i1 = 4 - //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] - //SEG12 [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 - ldx #0 - //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy - //SEG15 main::@1 - b1: - //SEG16 [6] (byte~) main::$14 ← (byte) main::i#2 << (byte) 1 -- vbuyy=vbuxx_rol_1 - txa - asl - tay - //SEG17 [7] (struct Point*) main::point_i#0 ← (const struct Point[4]) points#0 + (byte~) main::$14 -- pssz1=pssc1_plus_vbuyy - tya - clc - adc #points - adc #0 - sta point_i+1 - //SEG18 [8] *((byte*)(const struct Point[4]) points#0 + (byte~) main::$14) ← (byte) main::i#2 -- pbuc1_derefidx_vbuyy=vbuxx - txa - sta points,y - //SEG19 [9] (byte~) main::$5 ← (byte) main::i#2 + (byte) 4 -- vbuaa=vbuxx_plus_vbuc1 - txa - clc - adc #4 - //SEG20 [10] *((byte*)(struct Point*) main::point_i#0 + (const byte) OFFS_Y#0) ← (byte~) main::$5 -- pbuz1_derefidx_vbuc1=vbuaa - // points[i].x = i; - ldy #OFFS_Y - sta (point_i),y - //SEG21 [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx - inx - //SEG22 [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #4 - bne b1 - //SEG23 [13] phi from main::@1 to main::@2 [phi:main::@1->main::@2] - //SEG24 [13] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1 - ldx #0 - //SEG25 [13] phi from main::@2 to main::@2 [phi:main::@2->main::@2] - //SEG26 [13] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy - //SEG27 main::@2 - b2: - //SEG28 [14] (byte~) main::$15 ← (byte) main::i1#2 << (byte) 1 -- vbuyy=vbuxx_rol_1 - txa - asl - tay - //SEG29 [15] (struct Point*) main::point_i1#0 ← (const struct Point[4]) points#0 + (byte~) main::$15 -- pssz1=pssc1_plus_vbuyy - tya - clc - adc #points - adc #0 - sta point_i1+1 - //SEG30 [16] *((const byte*) main::SCREEN#0 + (byte) main::i1#2) ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$15) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy - lda points,y - sta SCREEN,x - //SEG31 [17] *((const byte*) main::SCREEN#0+(byte) $28 + (byte) main::i1#2) ← *((byte*)(struct Point*) main::point_i1#0 + (const byte) OFFS_Y#0) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuc2 - // SCREEN[i] = points[i].x; - ldy #OFFS_Y - lda (point_i1),y - sta SCREEN+$28,x - //SEG32 [18] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuxx=_inc_vbuxx - inx - //SEG33 [19] if((byte) main::i1#1!=(byte) 4) goto main::@2 -- vbuxx_neq_vbuc1_then_la1 - cpx #4 - bne b2 - //SEG34 main::@return - //SEG35 [20] return + //SEG11 [5] call point + //SEG12 [9] phi from main to point [phi:main->point] + jsr point + //SEG13 main::@1 + //SEG14 [6] *((const byte*) main::SCREEN#0) ← (const byte) point::p_x#0 -- _deref_pbuc1=vbuc2 + lda #point.p_x + sta SCREEN + //SEG15 [7] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point::p_y#0 -- _deref_pbuc1=vbuc2 + lda #point.p_y + sta SCREEN+1 + //SEG16 main::@return + //SEG17 [8] return + rts +} +//SEG18 point +point: { + .label p_x = 2 + .label p_y = 3 + //SEG19 point::@return + //SEG20 [10] return rts } - points: .fill 2*4, 0