CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start main::i = 0 to:main::@1 main::@1: scope:[main] from main main::@2 sub1::i#0 = main::i call sub1 sub1::return#0 = sub1::return#2 to:main::@2 main::@2: scope:[main] from main::@1 sub1::return#3 = phi( main::@1/sub1::return#0 ) main::$0 = sub1::return#3 main::SCREEN[main::i] = main::$0 main::i = main::i + rangenext(0,2) main::$1 = main::i != rangelast(0,2) if(main::$1) goto main::@1 to:main::@return main::@return: scope:[main] from main::@2 return to:@return char sub1(char i) sub1: scope:[sub1] from main::@1 sub1::i#1 = phi( main::@1/sub1::i#0 ) sub1::$0 = sub1::i#1 + sub1::i#1 sub1::return#1 = sub1::$0 to:sub1::@return sub1::@return: scope:[sub1] from sub1 sub1::return#4 = phi( sub1/sub1::return#1 ) sub1::return#2 = sub1::return#4 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 bool main::$1 __constant char * const main::SCREEN = (char *)$400 __loadstore volatile char main::i char sub1(char i) char sub1::$0 char sub1::i char sub1::i#0 char sub1::i#1 char sub1::return char sub1::return#0 char sub1::return#1 char sub1::return#2 char sub1::return#3 char sub1::return#4 Simplifying constant pointer cast (char *) 1024 Successful SSA optimization PassNCastSimplification Alias sub1::return#0 = sub1::return#3 Alias sub1::return#1 = sub1::$0 sub1::return#4 sub1::return#2 Successful SSA optimization Pass2AliasElimination Identical Phi Values sub1::i#1 sub1::i#0 Successful SSA optimization Pass2IdenticalPhiElimination Simple Condition main::$1 [8] if(main::i!=rangelast(0,2)) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification Resolved ranged next value [6] main::i = ++ main::i to ++ Resolved ranged comparison value [8] if(main::i!=rangelast(0,2)) goto main::@1 to 3 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 Adding number conversion cast (unumber) 3 in [7] if(main::i!=3) goto main::@1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast 3 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions CALL GRAPH Calls in [main] to sub1:2 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::i = 0 to:main::@1 main::@1: scope:[main] from main main::@2 [1] sub1::i#0 = main::i [2] call sub1 [3] sub1::return#0 = sub1::return#1 to:main::@2 main::@2: scope:[main] from main::@1 [4] main::$0 = sub1::return#0 [5] main::SCREEN[main::i] = main::$0 [6] main::i = ++ main::i [7] if(main::i!=3) goto main::@1 to:main::@return main::@return: scope:[main] from main::@2 [8] return to:@return char sub1(char i) sub1: scope:[sub1] from main::@1 [9] sub1::return#1 = sub1::i#0 + sub1::i#0 to:sub1::@return sub1::@return: scope:[sub1] from sub1 [10] return to:@return VARIABLE REGISTER WEIGHTS void main() char main::$0 // 22.0 __loadstore volatile char main::i // 7.125 char sub1(char i) char sub1::i char sub1::i#0 // 213.0 char sub1::return char sub1::return#0 // 22.0 char sub1::return#1 // 37.33333333333333 Initial phi equivalence classes Added variable main::i to live range equivalence class [ main::i ] Added variable sub1::i#0 to live range equivalence class [ sub1::i#0 ] Added variable sub1::return#0 to live range equivalence class [ sub1::return#0 ] Added variable main::$0 to live range equivalence class [ main::$0 ] Added variable sub1::return#1 to live range equivalence class [ sub1::return#1 ] Complete equivalence classes [ main::i ] [ sub1::i#0 ] [ sub1::return#0 ] [ main::$0 ] [ sub1::return#1 ] Allocated zp[1]:129 [ sub1::i#0 ] Allocated zp[1]:130 [ sub1::return#1 ] Allocated zp[1]:131 [ sub1::return#0 ] Allocated zp[1]:132 [ main::$0 ] Allocated zp[1]:133 [ main::i ] REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] main::i = 0 [ main::i ] ( [ main::i ] { } ) always clobbers reg byte a Statement [5] main::SCREEN[main::i] = main::$0 [ main::i ] ( [ main::i ] { } ) always clobbers reg byte y Statement [7] if(main::i!=3) goto main::@1 [ main::i ] ( [ main::i ] { } ) always clobbers reg byte a Statement [9] sub1::return#1 = sub1::i#0 + sub1::i#0 [ sub1::return#1 ] ( sub1:2 [ main::i sub1::return#1 ] { { sub1::i#0 = main::i } { sub1::return#0 = sub1::return#1 } } ) always clobbers reg byte a Potential registers zp[1]:133 [ main::i ] : zp[1]:133 , Potential registers zp[1]:129 [ sub1::i#0 ] : zp[1]:129 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:131 [ sub1::return#0 ] : zp[1]:131 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:132 [ main::$0 ] : zp[1]:132 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:130 [ sub1::return#1 ] : zp[1]:130 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [sub1] 213: zp[1]:129 [ sub1::i#0 ] 37.33: zp[1]:130 [ sub1::return#1 ] 22: zp[1]:131 [ sub1::return#0 ] Uplift Scope [main] 22: zp[1]:132 [ main::$0 ] 7.12: zp[1]:133 [ main::i ] Uplift Scope [] Uplifting [sub1] best 440 combination reg byte a [ sub1::i#0 ] reg byte a [ sub1::return#1 ] reg byte a [ sub1::return#0 ] Uplifting [main] best 380 combination reg byte a [ main::$0 ] zp[1]:133 [ main::i ] Uplifting [] best 380 combination Attempting to uplift remaining variables inzp[1]:133 [ main::i ] Uplifting [main] best 380 combination zp[1]:133 [ main::i ] Allocated (was zp[1]:133) zp[1]:129 [ main::i ] ASSEMBLER BEFORE OPTIMIZATION // File Comments // Demonstrates global directive reserving a range of addresses on zeropage // Upstart // Commodore 64 PRG executable file .file [name="reserve-zp-global-range.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 .label i = $81 // [0] main::i = 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: // [1] sub1::i#0 = main::i -- vbuaa=vbuz1 lda.z i // [2] call sub1 jsr sub1 // [3] sub1::return#0 = sub1::return#1 jmp __b2 // main::@2 __b2: // [4] main::$0 = sub1::return#0 // [5] main::SCREEN[main::i] = main::$0 -- pbuc1_derefidx_vbuz1=vbuaa ldy.z i sta SCREEN,y // [6] main::i = ++ main::i -- vbuz1=_inc_vbuz1 inc.z i // [7] if(main::i!=3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #3 cmp.z i bne __b1 jmp __breturn // main::@return __breturn: // [8] return rts } // sub1 // __register(A) char sub1(__register(A) char i) sub1: { // [9] sub1::return#1 = sub1::i#0 + sub1::i#0 -- vbuaa=vbuaa_plus_vbuaa asl jmp __breturn // sub1::@return __breturn: // [10] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __b2: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE void main() char main::$0 // reg byte a 22.0 __constant char * const main::SCREEN = (char *) 1024 __loadstore volatile char main::i // zp[1]:129 7.125 char sub1(char i) char sub1::i char sub1::i#0 // reg byte a 213.0 char sub1::return char sub1::return#0 // reg byte a 22.0 char sub1::return#1 // reg byte a 37.33333333333333 zp[1]:129 [ main::i ] reg byte a [ sub1::i#0 ] reg byte a [ sub1::return#0 ] reg byte a [ main::$0 ] reg byte a [ sub1::return#1 ] FINAL ASSEMBLER Score: 314 // File Comments // Demonstrates global directive reserving a range of addresses on zeropage // Upstart // Commodore 64 PRG executable file .file [name="reserve-zp-global-range.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 .label i = $81 // for( volatile byte i : 0..2) // [0] main::i = 0 -- vbuz1=vbuc1 lda #0 sta.z i // main::@1 __b1: // sub1(i) // [1] sub1::i#0 = main::i -- vbuaa=vbuz1 lda.z i // [2] call sub1 jsr sub1 // [3] sub1::return#0 = sub1::return#1 // main::@2 // [4] main::$0 = sub1::return#0 // SCREEN[i] = sub1(i) // [5] main::SCREEN[main::i] = main::$0 -- pbuc1_derefidx_vbuz1=vbuaa ldy.z i sta SCREEN,y // for( volatile byte i : 0..2) // [6] main::i = ++ main::i -- vbuz1=_inc_vbuz1 inc.z i // [7] if(main::i!=3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #3 cmp.z i bne __b1 // main::@return // } // [8] return rts } // sub1 // __register(A) char sub1(__register(A) char i) sub1: { // i+i // [9] sub1::return#1 = sub1::i#0 + sub1::i#0 -- vbuaa=vbuaa_plus_vbuaa asl // sub1::@return // } // [10] return rts } // File Data