Resolved forward reference fn1 to void fn1() Resolved forward reference fn2 to void fn2() CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start main::f#0 = (void()*) 0 main::f#1 = &fn1 main::$0 = < (word)main::f#1 main::SCREEN[0] = main::$0 main::$1 = > (word)main::f#1 main::SCREEN[1] = main::$1 main::f#2 = &fn2 main::$2 = < (word)main::f#2 main::SCREEN[2] = main::$2 main::$3 = > (word)main::f#2 main::SCREEN[3] = main::$3 to:main::@return main::@return: scope:[main] from main return to:@return void fn1() fn1: scope:[fn1] from *fn1::BORDER_COLOR = ++ *fn1::BORDER_COLOR to:fn1::@return fn1::@return: scope:[fn1] from fn1 return to:@return void fn2() fn2: scope:[fn2] from *fn2::BG_COLOR = ++ *fn2::BG_COLOR to:fn2::@return fn2::@return: scope:[fn2] from fn2 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 fn1() const nomodify byte* fn1::BORDER_COLOR = (byte*)$d020 void fn2() const nomodify byte* fn2::BG_COLOR = (byte*)$d021 void main() byte~ main::$0 byte~ main::$1 byte~ main::$2 byte~ main::$3 const nomodify byte* main::SCREEN = (byte*)$400 void()* main::f void()* main::f#0 void()* main::f#1 void()* main::f#2 Adding number conversion cast (unumber) 0 in main::SCREEN[0] = main::$0 Adding number conversion cast (unumber) 1 in main::SCREEN[1] = main::$1 Adding number conversion cast (unumber) 2 in main::SCREEN[2] = main::$2 Adding number conversion cast (unumber) 3 in main::SCREEN[3] = main::$3 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant pointer cast (byte*) 53280 Simplifying constant pointer cast (byte*) 53281 Simplifying constant integer cast 0 Simplifying constant integer cast 1 Simplifying constant integer cast 2 Simplifying constant integer cast 3 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 1 Finalized unsigned number type (byte) 2 Finalized unsigned number type (byte) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions Constant main::f#0 = (void()*) 0 Constant main::f#1 = &fn1 Constant main::f#2 = &fn2 Successful SSA optimization Pass2ConstantIdentification Constant value identified (word)main::f#1 in [2] main::$0 = < (word)main::f#1 Constant value identified (word)main::f#1 in [4] main::$1 = > (word)main::f#1 Constant value identified (word)main::f#2 in [7] main::$2 = < (word)main::f#2 Constant value identified (word)main::f#2 in [9] main::$3 = > (word)main::f#2 Successful SSA optimization Pass2ConstantValues Simplifying expression containing zero main::SCREEN in [3] main::SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant main::f#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 right-side identified [0] main::$0 = < (word)main::f#1 Constant right-side identified [2] main::$1 = > (word)main::f#1 Constant right-side identified [4] main::$2 = < (word)main::f#2 Constant right-side identified [6] main::$3 = > (word)main::f#2 Successful SSA optimization Pass2ConstantRValueConsolidation Constant main::$0 = <(word)main::f#1 Constant main::$1 = >(word)main::f#1 Constant main::$2 = <(word)main::f#2 Constant main::$3 = >(word)main::f#2 Successful SSA optimization Pass2ConstantIdentification Inlining constant with different constant siblings main::f#1 Inlining constant with different constant siblings main::f#2 Constant inlined main::f#2 = &fn2 Constant inlined main::$3 = >(word)&fn2 Constant inlined main::$1 = >(word)&fn1 Constant inlined main::$2 = <(word)&fn2 Constant inlined main::f#1 = &fn1 Constant inlined main::$0 = <(word)&fn1 Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(main::SCREEN+1) Consolidated array index constant in *(main::SCREEN+2) Consolidated array index constant in *(main::SCREEN+3) Successful SSA optimization Pass2ConstantAdditionElimination CALL GRAPH Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes FINAL CONTROL FLOW GRAPH void fn2() fn2: scope:[fn2] from [0] *fn2::BG_COLOR = ++ *fn2::BG_COLOR to:fn2::@return fn2::@return: scope:[fn2] from fn2 [1] return to:@return void fn1() fn1: scope:[fn1] from [2] *fn1::BORDER_COLOR = ++ *fn1::BORDER_COLOR to:fn1::@return fn1::@return: scope:[fn1] from fn1 [3] return to:@return void main() main: scope:[main] from [4] *main::SCREEN = <(word)&fn1 [5] *(main::SCREEN+1) = >(word)&fn1 [6] *(main::SCREEN+2) = <(word)&fn2 [7] *(main::SCREEN+3) = >(word)&fn2 to:main::@return main::@return: scope:[main] from main [8] return to:@return VARIABLE REGISTER WEIGHTS void fn1() void fn2() void main() void()* main::f Initial phi equivalence classes Complete equivalence classes REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] *main::SCREEN = <(word)&fn1 [ ] ( [ ] { } ) always clobbers reg byte a Statement [5] *(main::SCREEN+1) = >(word)&fn1 [ ] ( [ ] { } ) always clobbers reg byte a Statement [6] *(main::SCREEN+2) = <(word)&fn2 [ ] ( [ ] { } ) always clobbers reg byte a Statement [7] *(main::SCREEN+3) = >(word)&fn2 [ ] ( [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [main] Uplift Scope [fn1] Uplift Scope [fn2] Uplift Scope [] Uplifting [main] best 63 combination Uplifting [fn1] best 63 combination Uplifting [fn2] best 63 combination Uplifting [] best 63 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Tests creating pointers to non-args no-return functions // Upstart // Commodore 64 PRG executable file .file [name="function-pointer-noarg.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 // fn2 fn2: { .label BG_COLOR = $d021 // [0] *fn2::BG_COLOR = ++ *fn2::BG_COLOR -- _deref_pbuc1=_inc__deref_pbuc1 inc BG_COLOR jmp __breturn // fn2::@return __breturn: // [1] return rts } // fn1 fn1: { .label BORDER_COLOR = $d020 // [2] *fn1::BORDER_COLOR = ++ *fn1::BORDER_COLOR -- _deref_pbuc1=_inc__deref_pbuc1 inc BORDER_COLOR jmp __breturn // fn1::@return __breturn: // [3] return rts } // main main: { .label SCREEN = $400 // [4] *main::SCREEN = <(word)&fn1 -- _deref_pbuc1=vbuc2 lda #(word)&fn1 -- _deref_pbuc1=vbuc2 lda #>fn1 sta SCREEN+1 // [6] *(main::SCREEN+2) = <(word)&fn2 -- _deref_pbuc1=vbuc2 lda #(word)&fn2 -- _deref_pbuc1=vbuc2 lda #>fn2 sta SCREEN+3 jmp __breturn // main::@return __breturn: // [8] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __breturn Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE void fn1() const nomodify byte* fn1::BORDER_COLOR = (byte*) 53280 void fn2() const nomodify byte* fn2::BG_COLOR = (byte*) 53281 void main() const nomodify byte* main::SCREEN = (byte*) 1024 void()* main::f FINAL ASSEMBLER Score: 54 // File Comments // Tests creating pointers to non-args no-return functions // Upstart // Commodore 64 PRG executable file .file [name="function-pointer-noarg.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 // fn2 fn2: { .label BG_COLOR = $d021 // (*BG_COLOR)++; // [0] *fn2::BG_COLOR = ++ *fn2::BG_COLOR -- _deref_pbuc1=_inc__deref_pbuc1 inc BG_COLOR // fn2::@return // } // [1] return rts } // fn1 fn1: { .label BORDER_COLOR = $d020 // (*BORDER_COLOR)++; // [2] *fn1::BORDER_COLOR = ++ *fn1::BORDER_COLOR -- _deref_pbuc1=_inc__deref_pbuc1 inc BORDER_COLOR // fn1::@return // } // [3] return rts } // main main: { .label SCREEN = $400 // SCREEN[0] = <(word)f // [4] *main::SCREEN = <(word)&fn1 -- _deref_pbuc1=vbuc2 lda #(word)f // [5] *(main::SCREEN+1) = >(word)&fn1 -- _deref_pbuc1=vbuc2 lda #>fn1 sta SCREEN+1 // SCREEN[2] = <(word)f // [6] *(main::SCREEN+2) = <(word)&fn2 -- _deref_pbuc1=vbuc2 lda #(word)f // [7] *(main::SCREEN+3) = >(word)&fn2 -- _deref_pbuc1=vbuc2 lda #>fn2 sta SCREEN+3 // main::@return // } // [8] return rts } // File Data