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 (byte) point_x#0 ← (byte) 0 (byte) point_y#0 ← (byte) 0 to:@1 main: scope:[main] from @1 (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) ← (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 (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 SYMBOL TABLE SSA (label) @1 (label) @2 (label) @begin (label) @end (byte) Point::x (byte) Point::y (void()) main() (label) main::@return (byte*) main::SCREEN (byte*) main::SCREEN#0 (struct Point) point (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 (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 (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 Simplifying constant integer cast 3 Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 2 Finalized unsigned number type (byte) 3 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions 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 (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) ← (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 CALL GRAPH Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @2 Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] phi() to:@1 @1: scope:[] from @begin [1] phi() [2] call main to:@end @end: scope:[] from @1 [3] phi() main: scope:[main] from @1 [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 [6] return to:@return VARIABLE REGISTER WEIGHTS (byte) Point::x (byte) Point::y (void()) main() (byte*) main::SCREEN (struct Point) point (byte) point_x (byte) point_y Initial phi equivalence classes Complete equivalence classes INITIAL ASM //SEG0 File Comments // Minimal struct - declaration, instantiation and usage //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" //SEG2 Global Constants & labels .const point_x = 2 .const point_y = 3 //SEG3 @begin bbegin: //SEG4 [1] phi from @begin to @1 [phi:@begin->@1] b1_from_bbegin: jmp b1 //SEG5 @1 b1: //SEG6 [2] call main jsr main //SEG7 [3] phi from @1 to @end [phi:@1->@end] bend_from_b1: jmp bend //SEG8 @end bend: //SEG9 main main: { .label SCREEN = $400 //SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2 lda #point_x sta SCREEN //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 //SEG12 main::@return breturn: //SEG13 [6] return rts } REGISTER UPLIFT POTENTIAL REGISTERS 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 [Point] Uplift Scope [main] Uplift Scope [] Uplifting [Point] best 33 combination Uplifting [main] best 33 combination Uplifting [] best 33 combination ASSEMBLER BEFORE OPTIMIZATION //SEG0 File Comments // Minimal struct - declaration, instantiation and usage //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" //SEG2 Global Constants & labels .const point_x = 2 .const point_y = 3 //SEG3 @begin bbegin: //SEG4 [1] phi from @begin to @1 [phi:@begin->@1] b1_from_bbegin: jmp b1 //SEG5 @1 b1: //SEG6 [2] call main jsr main //SEG7 [3] phi from @1 to @end [phi:@1->@end] bend_from_b1: jmp bend //SEG8 @end bend: //SEG9 main main: { .label SCREEN = $400 //SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2 lda #point_x sta SCREEN //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 //SEG12 main::@return breturn: //SEG13 [6] return rts } ASSEMBLER OPTIMIZATIONS Removing instruction jmp b1 Removing instruction jmp bend Removing instruction jmp breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction b1_from_bbegin: Removing instruction b1: Removing instruction bend_from_b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction bend: Removing instruction breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly Removing instruction jsr main Succesful ASM optimization Pass5SkipBegin Removing instruction bbegin: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (byte) Point::x (byte) Point::y (void()) main() (label) main::@return (byte*) main::SCREEN (const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 (struct Point) point (byte) point_x (const byte) point_x#1 point_x = (byte) 2 (byte) point_y (const byte) point_y#1 point_y = (byte) 3 FINAL ASSEMBLER Score: 18 //SEG0 File Comments // Minimal struct - declaration, instantiation and usage //SEG1 Basic Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" //SEG2 Global Constants & labels .const point_x = 2 .const point_y = 3 //SEG3 @begin //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 //SEG10 [4] *((const byte*) main::SCREEN#0) ← (const byte) point_x#1 -- _deref_pbuc1=vbuc2 lda #point_x sta SCREEN //SEG11 [5] *((const byte*) main::SCREEN#0+(byte) 1) ← (const byte) point_y#1 -- _deref_pbuc1=vbuc2 lda #point_y sta SCREEN+1 //SEG12 main::@return //SEG13 [6] return rts }