Eliminating unused variable with no statement main::$0 Unwinding list assignment { main::$0_x, main::$0_y } = { point::return_x, point::return_y } Unwinding list assignment { point::return_x#0, point::return_y#0 } = { point::return_x#3, point::return_y#3 } CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start main::q_x#0 = 0 main::q_y#0 = 0 call point point::return_x#0 = point::return_x#3 point::return_y#0 = point::return_y#3 to:main::@1 main::@1: scope:[main] from main point::return_y#2 = phi( main/point::return_y#0 ) point::return_x#2 = phi( main/point::return_x#0 ) main::$0_x = point::return_x#2 main::$0_y = point::return_y#2 main::q_x#1 = main::$0_x main::q_y#1 = main::$0_y main::SCREEN[0] = main::q_x#1 main::SCREEN[1] = main::q_y#1 to:main::@return main::@return: scope:[main] from main::@1 return to:@return struct Point point() point: scope:[point] from main point::return_x#1 = point::p_x point::return_y#1 = point::p_y point::return#0 = struct-unwound {point::return_x#1, point::return_y#1} to:point::@return point::@return: scope:[point] from point point::return_y#3 = phi( point/point::return_y#1 ) point::return_x#3 = phi( point/point::return_x#1 ) point::return#1 = struct-unwound {} 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 void __start() void main() char main::$0_x char main::$0_y __constant char * const main::SCREEN = (char *)$400 char main::q_x char main::q_x#0 char main::q_x#1 char main::q_y char main::q_y#0 char main::q_y#1 struct Point point() __constant char point::p_x = 2 __constant char point::p_y = 3 struct Point point::return struct Point point::return#0 struct Point point::return#1 char point::return_x char point::return_x#0 char point::return_x#1 char point::return_x#2 char point::return_x#3 char point::return_y char point::return_y#0 char point::return_y#1 char point::return_y#2 char point::return_y#3 Adding number conversion cast (unumber) 0 in main::SCREEN[0] = main::q_x#1 Adding number conversion cast (unumber) 1 in main::SCREEN[1] = main::q_y#1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 0 Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 0 Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias point::return_x#0 = point::return_x#2 Alias point::return_y#0 = point::return_y#2 Alias main::q_x#1 = main::$0_x Alias main::q_y#1 = main::$0_y Alias point::return_x#1 = point::return_x#3 Alias point::return_y#1 = point::return_y#3 Successful SSA optimization Pass2AliasElimination Constant main::q_x#0 = 0 Constant main::q_y#0 = 0 Constant point::return_x#1 = point::p_x Constant point::return_y#1 = point::p_y Successful SSA optimization Pass2ConstantIdentification Constant point::return_x#0 = point::return_x#1 Constant point::return_y#0 = point::return_y#1 Successful SSA optimization Pass2ConstantIdentification Constant main::q_x#1 = point::return_x#0 Constant main::q_y#1 = point::return_y#0 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero main::SCREEN in [7] main::SCREEN[0] = main::q_x#1 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable point::return#0 and assignment [4] point::return#0 = struct-unwound {point::return_x#1, point::return_y#1} Eliminating unused variable point::return#1 and assignment [5] point::return#1 = struct-unwound {} Eliminating unused constant main::q_x#0 Eliminating unused constant main::q_y#0 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::q_x#1 = point::p_x Constant inlined point::return_y#1 = point::p_y Constant inlined point::return_x#1 = point::p_x Constant inlined point::return_y#0 = point::p_y Constant inlined point::return_x#0 = point::p_x Constant inlined main::q_y#1 = point::p_y Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(main::SCREEN+1) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main Adding NOP phi() at start of point CALL GRAPH Calls in [main] to point:1 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Adding NOP phi() at start of main Adding NOP phi() at start of point FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] phi() [1] call point to:main::@1 main::@1: scope:[main] from main [2] *main::SCREEN = point::p_x [3] *(main::SCREEN+1) = point::p_y to:main::@return main::@return: scope:[main] from main::@1 [4] return to:@return struct Point point() point: scope:[point] from main [5] phi() to:point::@return point::@return: scope:[point] from point [6] return to:@return VARIABLE REGISTER WEIGHTS void main() char main::q_x char main::q_y struct Point point() struct Point point::return char point::return_x char point::return_y Initial phi equivalence classes Complete equivalence classes REGISTER UPLIFT POTENTIAL REGISTERS Statement [2] *main::SCREEN = point::p_x [ ] ( [ ] { } ) always clobbers reg byte a Statement [3] *(main::SCREEN+1) = point::p_y [ ] ( [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [Point] Uplift Scope [main] Uplift Scope [point] Uplift Scope [] Uplifting [Point] best 66 combination Uplifting [main] best 66 combination Uplifting [point] best 66 combination Uplifting [] best 66 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Minimal struct - struct return value // Upstart // Commodore 64 PRG executable file .file [name="struct-5.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 .segment Code // main main: { .label SCREEN = $400 // [1] call point // [5] phi from main to point [phi:main->point] point_from_main: jsr point jmp __b1 // main::@1 __b1: // [2] *main::SCREEN = point::p_x -- _deref_pbuc1=vbuc2 lda #point.p_x sta SCREEN // [3] *(main::SCREEN+1) = point::p_y -- _deref_pbuc1=vbuc2 lda #point.p_y sta SCREEN+1 jmp __breturn // main::@return __breturn: // [4] return rts } // point point: { .label p_x = 2 .label p_y = 3 jmp __breturn // point::@return __breturn: // [6] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction point_from_main: Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE void main() __constant char * const main::SCREEN = (char *) 1024 char main::q_x char main::q_y struct Point point() __constant char point::p_x = 2 __constant char point::p_y = 3 struct Point point::return char point::return_x char point::return_y FINAL ASSEMBLER Score: 30 // File Comments // Minimal struct - struct return value // Upstart // Commodore 64 PRG executable file .file [name="struct-5.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 .segment Code // main main: { .label SCREEN = $400 // point() // [1] call point // [5] phi from main to point [phi:main->point] jsr point // main::@1 // SCREEN[0] = q.x // [2] *main::SCREEN = point::p_x -- _deref_pbuc1=vbuc2 lda #point.p_x sta SCREEN // SCREEN[1] = q.y // [3] *(main::SCREEN+1) = point::p_y -- _deref_pbuc1=vbuc2 lda #point.p_y sta SCREEN+1 // main::@return // } // [4] return rts } // point point: { .label p_x = 2 .label p_y = 3 // point::@return // [6] return rts } // File Data