CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start *(&main::p) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) main::p = struct-unwound {*(&main::p)} main::$2 = (byte*)main::q main::$0 = main::$2 + OFFSET_STRUCT_POINT_X main::SCREEN[0] = *main::$0 main::$3 = (byte*)main::q main::$1 = main::$3 + OFFSET_STRUCT_POINT_Y main::SCREEN[1] = *main::$1 to:main::@return main::@return: scope:[main] from main return to:@return void __start() __start: scope:[__start] from call main to:__start::@1 __start::@1: scope:[__start] from __start to:__start::@return __start::@return: scope:[__start] from __start::@1 return to:@return SYMBOL TABLE SSA const struct Point $0 = { x: 2, y: 3 } const byte OFFSET_STRUCT_POINT_X = 0 const byte OFFSET_STRUCT_POINT_Y = 1 const byte SIZEOF_STRUCT_POINT = 2 void __start() void main() byte*~ main::$0 byte*~ main::$1 byte*~ main::$2 byte*~ main::$3 const nomodify byte* main::SCREEN = (byte*)$400 volatile struct Point main::p loadstore const struct Point* main::q = &main::p Adding number conversion cast (unumber) 0 in main::SCREEN[0] = *main::$0 Adding number conversion cast (unumber) 1 in main::SCREEN[1] = *main::$1 Successful SSA optimization PassNAddNumberTypeConversions 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) 0 Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Removing C-classic struct-unwound assignment [1] main::p = struct-unwound {*(&main::p)} Constant right-side identified [2] main::$2 = (byte*)main::q Constant right-side identified [5] main::$3 = (byte*)main::q Successful SSA optimization Pass2ConstantRValueConsolidation Constant main::$2 = (byte*)main::q Constant main::$3 = (byte*)main::q Successful SSA optimization Pass2ConstantIdentification Converting *(pointer+n) to pointer[n] [4] main::SCREEN[0] = *main::$0 -- main::$2[OFFSET_STRUCT_POINT_X] Converting *(pointer+n) to pointer[n] [7] main::SCREEN[1] = *main::$1 -- main::$3[OFFSET_STRUCT_POINT_Y] Successful SSA optimization Pass2InlineDerefIdx Simplifying expression containing zero main::$2 in [3] main::$0 = main::$2 + OFFSET_STRUCT_POINT_X Simplifying expression containing zero main::$2 in [4] main::SCREEN[0] = main::$2[OFFSET_STRUCT_POINT_X] Simplifying expression containing zero main::SCREEN in [4] main::SCREEN[0] = *main::$2 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable main::$0 and assignment [1] main::$0 = main::$2 Eliminating unused variable main::$1 and assignment [3] main::$1 = main::$3 + OFFSET_STRUCT_POINT_Y Eliminating unused constant OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars Removing unused procedure __start Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart Constant inlined main::$2 = (byte*)main::q Constant inlined main::$3 = (byte*)main::q Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *((byte*)main::q+OFFSET_STRUCT_POINT_Y) Consolidated array index constant in *(main::SCREEN+1) Successful SSA optimization Pass2ConstantAdditionElimination CALL GRAPH Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] *(&main::p) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [1] *main::SCREEN = *((byte*)main::q) [2] *(main::SCREEN+1) = *((byte*)main::q+OFFSET_STRUCT_POINT_Y) to:main::@return main::@return: scope:[main] from main [3] return to:@return VARIABLE REGISTER WEIGHTS void main() volatile struct Point main::p loadstore Initial phi equivalence classes Added variable main::p to live range equivalence class [ main::p ] Complete equivalence classes [ main::p ] Allocated zp[2]:2 [ main::p ] REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] *(&main::p) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y Statement [1] *main::SCREEN = *((byte*)main::q) [ ] ( [ ] { } ) always clobbers reg byte a Statement [2] *(main::SCREEN+1) = *((byte*)main::q+OFFSET_STRUCT_POINT_Y) [ ] ( [ ] { } ) always clobbers reg byte a Potential registers zp[2]:2 [ main::p ] : zp[2]:2 , REGISTER UPLIFT SCOPES Uplift Scope [Point] Uplift Scope [main] 0: zp[2]:2 [ main::p ] Uplift Scope [] Uplifting [Point] best 40 combination Uplifting [main] best 40 combination zp[2]:2 [ main::p ] Uplifting [] best 40 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Minimal struct - using address-of // Upstart // Commodore 64 PRG executable file .file [name="struct-ptr-12.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) // Global Constants & labels .const SIZEOF_STRUCT_POINT = 2 .const OFFSET_STRUCT_POINT_Y = 1 .segment Code // main main: { .label SCREEN = $400 .label q = p .label p = 2 // [0] *(&main::p) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 ldy #SIZEOF_STRUCT_POINT !: lda __0-1,y sta p-1,y dey bne !- // [1] *main::SCREEN = *((byte*)main::q) -- _deref_pbuc1=_deref_pbuc2 lda.z q sta SCREEN // [2] *(main::SCREEN+1) = *((byte*)main::q+OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda q+OFFSET_STRUCT_POINT_Y sta SCREEN+1 jmp __breturn // main::@return __breturn: // [3] return rts } // File Data .segment Data __0: .byte 2, 3 ASSEMBLER OPTIMIZATIONS Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE const struct Point $0 = { x: 2, y: 3 } const byte OFFSET_STRUCT_POINT_Y = 1 const byte SIZEOF_STRUCT_POINT = 2 void main() const nomodify byte* main::SCREEN = (byte*) 1024 volatile struct Point main::p loadstore zp[2]:2 const struct Point* main::q = &main::p zp[2]:2 [ main::p ] FINAL ASSEMBLER Score: 37 // File Comments // Minimal struct - using address-of // Upstart // Commodore 64 PRG executable file .file [name="struct-ptr-12.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) // Global Constants & labels .const SIZEOF_STRUCT_POINT = 2 .const OFFSET_STRUCT_POINT_Y = 1 .segment Code // main main: { .label SCREEN = $400 .label q = p .label p = 2 // p = { 2, 3 } // [0] *(&main::p) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 ldy #SIZEOF_STRUCT_POINT !: lda __0-1,y sta p-1,y dey bne !- // SCREEN[0] = q->x // [1] *main::SCREEN = *((byte*)main::q) -- _deref_pbuc1=_deref_pbuc2 lda.z q sta SCREEN // SCREEN[1] = q->y // [2] *(main::SCREEN+1) = *((byte*)main::q+OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda q+OFFSET_STRUCT_POINT_Y sta SCREEN+1 // main::@return // } // [3] return rts } // File Data .segment Data __0: .byte 2, 3