Rewriting struct pointer member access *((struct Point*) points).x Rewriting struct pointer member access *((struct Point*) points).x Rewriting struct pointer member access *((struct Point*) points).y Rewriting struct pointer member access *((struct Point*) points).y Rewriting struct pointer member access *((struct Point*) points).x Rewriting struct pointer member access *((struct Point*) points).y Identified constant variable (struct Point*) points CONTROL FLOW GRAPH SSA @begin: scope:[] from to:@1 (void()) main() main: scope:[main] from @1 (byte*~) main::$0 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X (byte*~) main::$1 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X *((byte*~) main::$1) ← *((byte*~) main::$0) + (number) 5 (byte*~) main::$2 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y (byte*~) main::$3 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y *((byte*~) main::$3) ← *((byte*~) main::$2) + (number) 5 (byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$4) (byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$5) to:main::@return main::@return: scope:[main] from main return to:@return @1: scope:[] from @begin call main to:@2 @2: scope:[] from @1 to:@end @end: scope:[] from @2 SYMBOL TABLE SSA (label) @1 (label) @2 (label) @begin (label) @end (const byte) OFFSET_STRUCT_POINT_X = (byte) 0 (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x (byte) Point::y (void()) main() (byte*~) main::$0 (byte*~) main::$1 (byte*~) main::$2 (byte*~) main::$3 (byte*~) main::$4 (byte*~) main::$5 (label) main::@return (const byte*) main::SCREEN = (byte*)(number) $400 (const struct Point*) points = (struct Point*)(number) $1000 Adding number conversion cast (unumber) 5 in *((byte*~) main::$1) ← *((byte*~) main::$0) + (number) 5 Adding number conversion cast (unumber) 5 in *((byte*~) main::$3) ← *((byte*~) main::$2) + (number) 5 Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$4) Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← *((byte*~) main::$5) Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant pointer cast (struct Point*) 4096 Simplifying constant integer cast 5 Simplifying constant integer cast 5 Simplifying constant integer cast 0 Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 5 Finalized unsigned number type (byte) 5 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Constant right-side identified [0] (byte*~) main::$0 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X Constant right-side identified [1] (byte*~) main::$1 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X Constant right-side identified [3] (byte*~) main::$2 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y Constant right-side identified [4] (byte*~) main::$3 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y Constant right-side identified [6] (byte*~) main::$4 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_X Constant right-side identified [8] (byte*~) main::$5 ← (byte*)(const struct Point*) points + (const byte) OFFSET_STRUCT_POINT_Y Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte*) main::$0 = (byte*)points+OFFSET_STRUCT_POINT_X Constant (const byte*) main::$1 = (byte*)points+OFFSET_STRUCT_POINT_X Constant (const byte*) main::$2 = (byte*)points+OFFSET_STRUCT_POINT_Y Constant (const byte*) main::$3 = (byte*)points+OFFSET_STRUCT_POINT_Y Constant (const byte*) main::$4 = (byte*)points+OFFSET_STRUCT_POINT_X Constant (const byte*) main::$5 = (byte*)points+OFFSET_STRUCT_POINT_Y Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero (byte*)points in Simplifying expression containing zero (byte*)points in Simplifying expression containing zero (byte*)points in Simplifying expression containing zero main::SCREEN in [7] *((const byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$4) Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars Constant inlined main::$1 = (byte*)(const struct Point*) points Constant inlined main::$2 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y Constant inlined main::$0 = (byte*)(const struct Point*) points Constant inlined main::$5 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y Constant inlined main::$3 = (byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y Constant inlined main::$4 = (byte*)(const struct Point*) points Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(main::SCREEN+1) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @2 Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @2 Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] phi() to:@1 @1: scope:[] from @begin [1] phi() [2] call main to:@end @end: scope:[] from @1 [3] phi() (void()) main() main: scope:[main] from @1 [4] *((byte*)(const struct Point*) points) ← *((byte*)(const struct Point*) points) + (byte) 5 [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) 5 [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) points) [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) to:main::@return main::@return: scope:[main] from main [8] return to:@return VARIABLE REGISTER WEIGHTS (byte) Point::x (byte) Point::y (void()) main() Initial phi equivalence classes Complete equivalence classes INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Minimal struct - modifying pointer to struct in memory using arrow operator // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .const OFFSET_STRUCT_POINT_Y = 1 .label points = $1000 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { .label SCREEN = $400 // [4] *((byte*)(const struct Point*) points) ← *((byte*)(const struct Point*) points) + (byte) 5 -- _deref_pbuc1=_deref_pbuc1_plus_vbuc2 lda #5 clc adc points sta points // [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) 5 -- _deref_pbuc1=_deref_pbuc2_plus_vbuc3 lda #5 clc adc points+OFFSET_STRUCT_POINT_Y sta points+OFFSET_STRUCT_POINT_Y // [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2 lda points sta SCREEN // [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda points+OFFSET_STRUCT_POINT_Y sta SCREEN+1 jmp __breturn // main::@return __breturn: // [8] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] *((byte*)(const struct Point*) points) ← *((byte*)(const struct Point*) points) + (byte) 5 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) 5 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) points) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [Point] Uplift Scope [main] Uplift Scope [] Uplifting [Point] best 61 combination Uplifting [main] best 61 combination Uplifting [] best 61 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Minimal struct - modifying pointer to struct in memory using arrow operator // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .const OFFSET_STRUCT_POINT_Y = 1 .label points = $1000 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { .label SCREEN = $400 // [4] *((byte*)(const struct Point*) points) ← *((byte*)(const struct Point*) points) + (byte) 5 -- _deref_pbuc1=_deref_pbuc1_plus_vbuc2 lda #5 clc adc points sta points // [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) 5 -- _deref_pbuc1=_deref_pbuc2_plus_vbuc3 lda #5 clc adc points+OFFSET_STRUCT_POINT_Y sta points+OFFSET_STRUCT_POINT_Y // [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2 lda points sta SCREEN // [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda points+OFFSET_STRUCT_POINT_Y sta SCREEN+1 jmp __breturn // main::@return __breturn: // [8] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Replacing label __bbegin with __b1 Removing instruction __bbegin: Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __bend: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly Removing instruction jsr main Succesful ASM optimization Pass5SkipBegin Removing instruction __b1: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x (byte) Point::y (void()) main() (label) main::@return (const byte*) main::SCREEN = (byte*) 1024 (const struct Point*) points = (struct Point*) 4096 FINAL ASSEMBLER Score: 46 // File Comments // Minimal struct - modifying pointer to struct in memory using arrow operator // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .const OFFSET_STRUCT_POINT_Y = 1 .label points = $1000 // @begin // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main // [3] phi from @1 to @end [phi:@1->@end] // @end // main main: { .label SCREEN = $400 // points->x += 5 // [4] *((byte*)(const struct Point*) points) ← *((byte*)(const struct Point*) points) + (byte) 5 -- _deref_pbuc1=_deref_pbuc1_plus_vbuc2 lda #5 clc adc points sta points // points->y += 5 // [5] *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) + (byte) 5 -- _deref_pbuc1=_deref_pbuc2_plus_vbuc3 lda #5 clc adc points+OFFSET_STRUCT_POINT_Y sta points+OFFSET_STRUCT_POINT_Y // SCREEN[0] = points->x // [6] *((const byte*) main::SCREEN) ← *((byte*)(const struct Point*) points) -- _deref_pbuc1=_deref_pbuc2 lda points sta SCREEN // SCREEN[1] = points->y // [7] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) points+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda points+OFFSET_STRUCT_POINT_Y sta SCREEN+1 // main::@return // } // [8] return rts } // File Data