Setting struct to load/store in variable affected by address-of (struct Point*) main::q ← &(volatile struct Point) main::p CONTROL FLOW GRAPH SSA (void()) main() main: scope:[main] from _start *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) (volatile struct Point) main::p ← struct-unwound {*(&(volatile struct Point) main::p)} (byte*~) main::$2 ← (byte*)(const struct Point*) main::q (byte*~) main::$0 ← (byte*~) main::$2 + (const byte) OFFSET_STRUCT_POINT_X *((const nomodify byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0) (byte*~) main::$3 ← (byte*)(const struct Point*) main::q (byte*~) main::$1 ← (byte*~) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y *((const nomodify byte*) main::SCREEN + (number) 1) ← *((byte*~) 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: (byte) 2, y: (byte) 3 } (const byte) OFFSET_STRUCT_POINT_X = (byte) 0 (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x (byte) Point::y (const byte) SIZEOF_STRUCT_POINT = (byte) 2 (void()) _start() (label) _start::@1 (label) _start::@return (void()) main() (byte*~) main::$0 (byte*~) main::$1 (byte*~) main::$2 (byte*~) main::$3 (label) main::@return (const nomodify byte*) main::SCREEN = (byte*)(number) $400 (volatile struct Point) main::p loadstore (const struct Point*) main::q = &(volatile struct Point) main::p Adding number conversion cast (unumber) 0 in *((const nomodify byte*) main::SCREEN + (number) 0) ← *((byte*~) main::$0) Adding number conversion cast (unumber) 1 in *((const nomodify byte*) main::SCREEN + (number) 1) ← *((byte*~) 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] (volatile struct Point) main::p ← struct-unwound {*(&(volatile struct Point) main::p)} Constant right-side identified [2] (byte*~) main::$2 ← (byte*)(const struct Point*) main::q Constant right-side identified [5] (byte*~) main::$3 ← (byte*)(const struct Point*) main::q Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte*) main::$2 = (byte*)main::q Constant (const byte*) main::$3 = (byte*)main::q Successful SSA optimization Pass2ConstantIdentification Converting *(pointer+n) to pointer[n] [4] *((const nomodify byte*) main::SCREEN + (byte) 0) ← *((byte*~) main::$0) -- *(main::$2 + OFFSET_STRUCT_POINT_X) Converting *(pointer+n) to pointer[n] [7] *((const nomodify byte*) main::SCREEN + (byte) 1) ← *((byte*~) main::$1) -- *(main::$3 + OFFSET_STRUCT_POINT_Y) Successful SSA optimization Pass2InlineDerefIdx Simplifying expression containing zero main::$2 in [3] (byte*~) main::$0 ← (const byte*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X Simplifying expression containing zero main::$2 in [4] *((const nomodify byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$2 + (const byte) OFFSET_STRUCT_POINT_X) Simplifying expression containing zero main::SCREEN in [4] *((const nomodify byte*) main::SCREEN + (byte) 0) ← *((const byte*) main::$2) Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable (byte*~) main::$0 and assignment [1] (byte*~) main::$0 ← (const byte*) main::$2 Eliminating unused variable (byte*~) main::$1 and assignment [3] (byte*~) main::$1 ← (const byte*) main::$3 + (const byte) OFFSET_STRUCT_POINT_Y Eliminating unused constant (const byte) 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*)(const struct Point*) main::q Constant inlined main::$3 = (byte*)(const struct Point*) 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] *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) [1] *((const nomodify byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [2] *((const nomodify byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) to:main::@return main::@return: scope:[main] from main [3] return to:@return VARIABLE REGISTER WEIGHTS (byte) Point::x (byte) Point::y (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 ] INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Minimal struct - using address-of // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .const SIZEOF_STRUCT_POINT = 2 .const OFFSET_STRUCT_POINT_Y = 1 // main main: { .label SCREEN = $400 .label q = p .label p = 2 // [0] *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 ldy #SIZEOF_STRUCT_POINT !: lda __0-1,y sta p-1,y dey bne !- // [1] *((const nomodify byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2 lda.z q sta SCREEN // [2] *((const nomodify byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) 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 __0: .byte 2, 3 REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y Statement [1] *((const nomodify byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) [ ] ( [ ] { } ) always clobbers reg byte a Statement [2] *((const nomodify byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) 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 .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .const SIZEOF_STRUCT_POINT = 2 .const OFFSET_STRUCT_POINT_Y = 1 // main main: { .label SCREEN = $400 .label q = p .label p = 2 // [0] *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 ldy #SIZEOF_STRUCT_POINT !: lda __0-1,y sta p-1,y dey bne !- // [1] *((const nomodify byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2 lda.z q sta SCREEN // [2] *((const nomodify byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) 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 __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: (byte) 2, y: (byte) 3 } (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x (byte) Point::y (const byte) SIZEOF_STRUCT_POINT = (byte) 2 (void()) main() (label) main::@return (const nomodify byte*) main::SCREEN = (byte*) 1024 (volatile struct Point) main::p loadstore zp[2]:2 (const struct Point*) main::q = &(volatile struct Point) main::p zp[2]:2 [ main::p ] FINAL ASSEMBLER Score: 37 // File Comments // Minimal struct - using address-of // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .const SIZEOF_STRUCT_POINT = 2 .const OFFSET_STRUCT_POINT_Y = 1 // main main: { .label SCREEN = $400 .label q = p .label p = 2 // p = { 2, 3 } // [0] *(&(volatile struct Point) main::p) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) 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] *((const nomodify byte*) main::SCREEN) ← *((byte*)(const struct Point*) main::q) -- _deref_pbuc1=_deref_pbuc2 lda.z q sta SCREEN // SCREEN[1] = q->y // [2] *((const nomodify byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct Point*) main::q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 lda q+OFFSET_STRUCT_POINT_Y sta SCREEN+1 // main::@return // } // [3] return rts } // File Data __0: .byte 2, 3