Inlined call call __init CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start::@1 idx#15 = phi( __start::@1/idx#16 ) euclid::a#0 = $80 euclid::b#0 = 2 call euclid euclid::return#0 = euclid::return#5 to:main::@1 main::@1: scope:[main] from main idx#8 = phi( main/idx#15 ) euclid::return#6 = phi( main/euclid::return#0 ) main::$0 = euclid::return#6 SCREEN[idx#8] = main::$0 idx#0 = ++ idx#8 euclid::a#1 = $a9 euclid::b#1 = $45 call euclid euclid::return#1 = euclid::return#5 to:main::@2 main::@2: scope:[main] from main::@1 idx#9 = phi( main::@1/idx#0 ) euclid::return#7 = phi( main::@1/euclid::return#1 ) main::$1 = euclid::return#7 SCREEN[idx#9] = main::$1 idx#1 = ++ idx#9 euclid::a#2 = $ff euclid::b#2 = $9b call euclid euclid::return#2 = euclid::return#5 to:main::@3 main::@3: scope:[main] from main::@2 idx#10 = phi( main::@2/idx#1 ) euclid::return#8 = phi( main::@2/euclid::return#2 ) main::$2 = euclid::return#8 SCREEN[idx#10] = main::$2 idx#2 = ++ idx#10 euclid::a#3 = $63 euclid::b#3 = 3 call euclid euclid::return#3 = euclid::return#5 to:main::@4 main::@4: scope:[main] from main::@3 idx#11 = phi( main::@3/idx#2 ) euclid::return#9 = phi( main::@3/euclid::return#3 ) main::$3 = euclid::return#9 SCREEN[idx#11] = main::$3 idx#3 = ++ idx#11 to:main::@return main::@return: scope:[main] from main::@4 idx#12 = phi( main::@4/idx#3 ) idx#4 = idx#12 return to:@return char euclid(char a , char b) euclid: scope:[euclid] from main main::@1 main::@2 main::@3 euclid::b#9 = phi( main/euclid::b#0, main::@1/euclid::b#1, main::@2/euclid::b#2, main::@3/euclid::b#3 ) euclid::a#10 = phi( main/euclid::a#0, main::@1/euclid::a#1, main::@2/euclid::a#2, main::@3/euclid::a#3 ) to:euclid::@1 euclid::@1: scope:[euclid] from euclid euclid::@4 euclid::@5 euclid::b#5 = phi( euclid/euclid::b#9, euclid::@4/euclid::b#7, euclid::@5/euclid::b#4 ) euclid::a#5 = phi( euclid/euclid::a#10, euclid::@4/euclid::a#4, euclid::@5/euclid::a#9 ) euclid::$0 = euclid::a#5 != euclid::b#5 if(euclid::$0) goto euclid::@2 to:euclid::@3 euclid::@2: scope:[euclid] from euclid::@1 euclid::b#6 = phi( euclid::@1/euclid::b#5 ) euclid::a#6 = phi( euclid::@1/euclid::a#5 ) euclid::$1 = euclid::a#6 > euclid::b#6 if(euclid::$1) goto euclid::@4 to:euclid::@5 euclid::@3: scope:[euclid] from euclid::@1 euclid::a#7 = phi( euclid::@1/euclid::a#5 ) euclid::return#4 = euclid::a#7 to:euclid::@return euclid::@4: scope:[euclid] from euclid::@2 euclid::b#7 = phi( euclid::@2/euclid::b#6 ) euclid::a#8 = phi( euclid::@2/euclid::a#6 ) euclid::$3 = euclid::a#8 - euclid::b#7 euclid::a#4 = euclid::$3 to:euclid::@1 euclid::@5: scope:[euclid] from euclid::@2 euclid::a#9 = phi( euclid::@2/euclid::a#6 ) euclid::b#8 = phi( euclid::@2/euclid::b#6 ) euclid::$2 = euclid::b#8 - euclid::a#9 euclid::b#4 = euclid::$2 to:euclid::@1 euclid::@return: scope:[euclid] from euclid::@3 euclid::return#10 = phi( euclid::@3/euclid::return#4 ) euclid::return#5 = euclid::return#10 return to:@return void __start() __start: scope:[__start] from to:__start::__init1 __start::__init1: scope:[__start] from __start idx#5 = 0 to:__start::@1 __start::@1: scope:[__start] from __start::__init1 idx#16 = phi( __start::__init1/idx#5 ) call main to:__start::@2 __start::@2: scope:[__start] from __start::@1 idx#13 = phi( __start::@1/idx#4 ) idx#6 = idx#13 to:__start::@return __start::@return: scope:[__start] from __start::@2 idx#14 = phi( __start::@2/idx#6 ) idx#7 = idx#14 return to:@return SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() char euclid(char a , char b) bool euclid::$0 bool euclid::$1 char euclid::$2 char euclid::$3 char euclid::a char euclid::a#0 char euclid::a#1 char euclid::a#10 char euclid::a#2 char euclid::a#3 char euclid::a#4 char euclid::a#5 char euclid::a#6 char euclid::a#7 char euclid::a#8 char euclid::a#9 char euclid::b char euclid::b#0 char euclid::b#1 char euclid::b#2 char euclid::b#3 char euclid::b#4 char euclid::b#5 char euclid::b#6 char euclid::b#7 char euclid::b#8 char euclid::b#9 char euclid::return char euclid::return#0 char euclid::return#1 char euclid::return#10 char euclid::return#2 char euclid::return#3 char euclid::return#4 char euclid::return#5 char euclid::return#6 char euclid::return#7 char euclid::return#8 char euclid::return#9 char idx char idx#0 char idx#1 char idx#10 char idx#11 char idx#12 char idx#13 char idx#14 char idx#15 char idx#16 char idx#2 char idx#3 char idx#4 char idx#5 char idx#6 char idx#7 char idx#8 char idx#9 void main() char main::$0 char main::$1 char main::$2 char main::$3 Adding number conversion cast (unumber) $80 in euclid::a#0 = $80 Adding number conversion cast (unumber) 2 in euclid::b#0 = 2 Adding number conversion cast (unumber) $a9 in euclid::a#1 = $a9 Adding number conversion cast (unumber) $45 in euclid::b#1 = $45 Adding number conversion cast (unumber) $ff in euclid::a#2 = $ff Adding number conversion cast (unumber) $9b in euclid::b#2 = $9b Adding number conversion cast (unumber) $63 in euclid::a#3 = $63 Adding number conversion cast (unumber) 3 in euclid::b#3 = 3 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast euclid::a#0 = (unumber)$80 Inlining cast euclid::b#0 = (unumber)2 Inlining cast euclid::a#1 = (unumber)$a9 Inlining cast euclid::b#1 = (unumber)$45 Inlining cast euclid::a#2 = (unumber)$ff Inlining cast euclid::b#2 = (unumber)$9b Inlining cast euclid::a#3 = (unumber)$63 Inlining cast euclid::b#3 = (unumber)3 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast $80 Simplifying constant integer cast 2 Simplifying constant integer cast $a9 Simplifying constant integer cast $45 Simplifying constant integer cast $ff Simplifying constant integer cast $9b Simplifying constant integer cast $63 Simplifying constant integer cast 3 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) $80 Finalized unsigned number type (char) 2 Finalized unsigned number type (char) $a9 Finalized unsigned number type (char) $45 Finalized unsigned number type (char) $ff Finalized unsigned number type (char) $9b Finalized unsigned number type (char) $63 Finalized unsigned number type (char) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias euclid::return#0 = euclid::return#6 Alias idx#15 = idx#8 Alias euclid::return#1 = euclid::return#7 Alias idx#0 = idx#9 Alias euclid::return#2 = euclid::return#8 Alias idx#1 = idx#10 Alias euclid::return#3 = euclid::return#9 Alias idx#11 = idx#2 Alias idx#12 = idx#3 idx#4 Alias euclid::a#5 = euclid::a#6 euclid::a#7 euclid::return#4 euclid::a#8 euclid::a#9 euclid::return#10 euclid::return#5 Alias euclid::b#5 = euclid::b#6 euclid::b#7 euclid::b#8 Alias euclid::a#4 = euclid::$3 Alias euclid::b#4 = euclid::$2 Alias idx#16 = idx#5 Alias idx#13 = idx#6 idx#14 idx#7 Successful SSA optimization Pass2AliasElimination Identical Phi Values idx#15 idx#16 Identical Phi Values idx#13 idx#12 Successful SSA optimization Pass2IdenticalPhiElimination Simple Condition euclid::$0 [33] if(euclid::a#5!=euclid::b#5) goto euclid::@2 Simple Condition euclid::$1 [35] if(euclid::a#5>euclid::b#5) goto euclid::@4 Successful SSA optimization Pass2ConditionalJumpSimplification Constant euclid::a#0 = $80 Constant euclid::b#0 = 2 Constant euclid::a#1 = $a9 Constant euclid::b#1 = $45 Constant euclid::a#2 = $ff Constant euclid::b#2 = $9b Constant euclid::a#3 = $63 Constant euclid::b#3 = 3 Constant idx#16 = 0 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [6] SCREEN[idx#16] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable idx#12 and assignment [19] idx#12 = ++ idx#11 Successful SSA optimization PassNEliminateUnusedVars Removing unused procedure __start Removing unused procedure block __start Removing unused procedure block __start::__init1 Removing unused procedure block __start::@1 Removing unused procedure block __start::@2 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart Constant right-side identified [4] idx#0 = ++ idx#16 Successful SSA optimization Pass2ConstantRValueConsolidation Constant idx#0 = ++idx#16 Successful SSA optimization Pass2ConstantIdentification Constant right-side identified [8] idx#1 = ++ idx#0 Successful SSA optimization Pass2ConstantRValueConsolidation Constant idx#1 = ++idx#0 Successful SSA optimization Pass2ConstantIdentification Constant right-side identified [12] idx#11 = ++ idx#1 Successful SSA optimization Pass2ConstantRValueConsolidation Constant idx#11 = ++idx#1 Successful SSA optimization Pass2ConstantIdentification Inlining constant with var siblings euclid::a#0 Inlining constant with var siblings euclid::b#0 Inlining constant with var siblings euclid::a#1 Inlining constant with var siblings euclid::b#1 Inlining constant with var siblings euclid::a#2 Inlining constant with var siblings euclid::b#2 Inlining constant with var siblings euclid::a#3 Inlining constant with var siblings euclid::b#3 Inlining constant with different constant siblings idx#16 Inlining constant with different constant siblings idx#0 Inlining constant with different constant siblings idx#1 Inlining constant with different constant siblings idx#11 Constant inlined idx#11 = ++++++0 Constant inlined euclid::b#0 = 2 Constant inlined euclid::a#1 = $a9 Constant inlined euclid::a#0 = $80 Constant inlined euclid::b#2 = $9b Constant inlined euclid::a#3 = $63 Constant inlined idx#0 = ++0 Constant inlined euclid::b#1 = $45 Constant inlined euclid::a#2 = $ff Constant inlined idx#1 = ++++0 Constant inlined idx#16 = 0 Constant inlined euclid::b#3 = 3 Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+++0) Consolidated array index constant in *(SCREEN+++++0) Consolidated array index constant in *(SCREEN+++++++0) Successful SSA optimization Pass2ConstantAdditionElimination Simplifying constant integer increment ++0 Simplifying constant integer increment ++0 Simplifying constant integer increment ++1 Successful SSA optimization Pass2ConstantSimplification Simplifying constant integer increment ++1 Simplifying constant integer increment ++2 Successful SSA optimization Pass2ConstantSimplification Adding NOP phi() at start of main Adding NOP phi() at start of euclid::@3 CALL GRAPH Calls in [main] to euclid:1 euclid:5 euclid:9 euclid:13 Created 4 initial phi equivalence classes Coalesced [19] euclid::a#11 = euclid::a#10 Coalesced [20] euclid::b#10 = euclid::b#9 Coalesced (already) [27] euclid::a#13 = euclid::a#5 Coalesced [28] euclid::b#12 = euclid::b#4 Coalesced [30] euclid::a#12 = euclid::a#4 Coalesced (already) [31] euclid::b#11 = euclid::b#5 Coalesced down to 2 phi equivalence classes Culled Empty Block label euclid::@3 Renumbering block euclid::@4 to euclid::@3 Renumbering block euclid::@5 to euclid::@4 Adding NOP phi() at start of main FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] phi() [1] call euclid [2] euclid::return#0 = euclid::a#5 to:main::@1 main::@1: scope:[main] from main [3] main::$0 = euclid::return#0 [4] *SCREEN = main::$0 [5] call euclid [6] euclid::return#1 = euclid::a#5 to:main::@2 main::@2: scope:[main] from main::@1 [7] main::$1 = euclid::return#1 [8] *(SCREEN+1) = main::$1 [9] call euclid [10] euclid::return#2 = euclid::a#5 to:main::@3 main::@3: scope:[main] from main::@2 [11] main::$2 = euclid::return#2 [12] *(SCREEN+2) = main::$2 [13] call euclid [14] euclid::return#3 = euclid::a#5 to:main::@4 main::@4: scope:[main] from main::@3 [15] main::$3 = euclid::return#3 [16] *(SCREEN+3) = main::$3 to:main::@return main::@return: scope:[main] from main::@4 [17] return to:@return char euclid(char a , char b) euclid: scope:[euclid] from main main::@1 main::@2 main::@3 [18] euclid::b#9 = phi( main/2, main::@1/$45, main::@2/$9b, main::@3/3 ) [18] euclid::a#10 = phi( main/$80, main::@1/$a9, main::@2/$ff, main::@3/$63 ) to:euclid::@1 euclid::@1: scope:[euclid] from euclid euclid::@3 euclid::@4 [19] euclid::b#5 = phi( euclid/euclid::b#9, euclid::@3/euclid::b#5, euclid::@4/euclid::b#4 ) [19] euclid::a#5 = phi( euclid/euclid::a#10, euclid::@3/euclid::a#4, euclid::@4/euclid::a#5 ) [20] if(euclid::a#5!=euclid::b#5) goto euclid::@2 to:euclid::@return euclid::@return: scope:[euclid] from euclid::@1 [21] return to:@return euclid::@2: scope:[euclid] from euclid::@1 [22] if(euclid::a#5>euclid::b#5) goto euclid::@3 to:euclid::@4 euclid::@4: scope:[euclid] from euclid::@2 [23] euclid::b#4 = euclid::b#5 - euclid::a#5 to:euclid::@1 euclid::@3: scope:[euclid] from euclid::@2 [24] euclid::a#4 = euclid::a#5 - euclid::b#5 to:euclid::@1 VARIABLE REGISTER WEIGHTS char euclid(char a , char b) char euclid::a char euclid::a#10 // 11.0 char euclid::a#4 // 202.0 char euclid::a#5 // 80.66666666666666 char euclid::b char euclid::b#4 // 202.0 char euclid::b#5 // 179.5 char euclid::b#9 // 11.0 char euclid::return char euclid::return#0 // 4.0 char euclid::return#1 // 4.0 char euclid::return#2 // 4.0 char euclid::return#3 // 4.0 char idx void main() char main::$0 // 4.0 char main::$1 // 4.0 char main::$2 // 4.0 char main::$3 // 4.0 Initial phi equivalence classes [ euclid::a#5 euclid::a#10 euclid::a#4 ] [ euclid::b#5 euclid::b#9 euclid::b#4 ] Added variable euclid::return#0 to live range equivalence class [ euclid::return#0 ] Added variable main::$0 to live range equivalence class [ main::$0 ] Added variable euclid::return#1 to live range equivalence class [ euclid::return#1 ] Added variable main::$1 to live range equivalence class [ main::$1 ] Added variable euclid::return#2 to live range equivalence class [ euclid::return#2 ] Added variable main::$2 to live range equivalence class [ main::$2 ] Added variable euclid::return#3 to live range equivalence class [ euclid::return#3 ] Added variable main::$3 to live range equivalence class [ main::$3 ] Complete equivalence classes [ euclid::a#5 euclid::a#10 euclid::a#4 ] [ euclid::b#5 euclid::b#9 euclid::b#4 ] [ euclid::return#0 ] [ main::$0 ] [ euclid::return#1 ] [ main::$1 ] [ euclid::return#2 ] [ main::$2 ] [ euclid::return#3 ] [ main::$3 ] Allocated zp[1]:2 [ euclid::b#5 euclid::b#9 euclid::b#4 ] Allocated zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] Allocated zp[1]:4 [ euclid::return#0 ] Allocated zp[1]:5 [ main::$0 ] Allocated zp[1]:6 [ euclid::return#1 ] Allocated zp[1]:7 [ main::$1 ] Allocated zp[1]:8 [ euclid::return#2 ] Allocated zp[1]:9 [ main::$2 ] Allocated zp[1]:10 [ euclid::return#3 ] Allocated zp[1]:11 [ main::$3 ] REGISTER UPLIFT POTENTIAL REGISTERS Statement [23] euclid::b#4 = euclid::b#5 - euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( euclid:1 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] Statement [24] euclid::a#4 = euclid::a#5 - euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( euclid:1 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ euclid::b#5 euclid::b#9 euclid::b#4 ] Statement [23] euclid::b#4 = euclid::b#5 - euclid::a#5 [ euclid::a#5 euclid::b#4 ] ( euclid:1 [ euclid::a#5 euclid::b#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::a#5 euclid::b#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::a#5 euclid::b#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::a#5 euclid::b#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Statement [24] euclid::a#4 = euclid::a#5 - euclid::b#5 [ euclid::b#5 euclid::a#4 ] ( euclid:1 [ euclid::b#5 euclid::a#4 ] { { euclid::return#0 = euclid::a#5 } } euclid:5 [ euclid::b#5 euclid::a#4 ] { { euclid::return#1 = euclid::a#5 } } euclid:9 [ euclid::b#5 euclid::a#4 ] { { euclid::return#2 = euclid::a#5 } } euclid:13 [ euclid::b#5 euclid::a#4 ] { { euclid::return#3 = euclid::a#5 } } ) always clobbers reg byte a Potential registers zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] : zp[1]:3 , reg byte x , reg byte y , Potential registers zp[1]:2 [ euclid::b#5 euclid::b#9 euclid::b#4 ] : zp[1]:2 , reg byte x , reg byte y , Potential registers zp[1]:4 [ euclid::return#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:6 [ euclid::return#1 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:7 [ main::$1 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:8 [ euclid::return#2 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:9 [ main::$2 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:10 [ euclid::return#3 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:11 [ main::$3 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [euclid] 392.5: zp[1]:2 [ euclid::b#5 euclid::b#9 euclid::b#4 ] 293.67: zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] 4: zp[1]:4 [ euclid::return#0 ] 4: zp[1]:6 [ euclid::return#1 ] 4: zp[1]:8 [ euclid::return#2 ] 4: zp[1]:10 [ euclid::return#3 ] Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] 4: zp[1]:7 [ main::$1 ] 4: zp[1]:9 [ main::$2 ] 4: zp[1]:11 [ main::$3 ] Uplift Scope [] Uplifting [euclid] best 613 combination reg byte x [ euclid::b#5 euclid::b#9 euclid::b#4 ] zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] reg byte a [ euclid::return#0 ] reg byte a [ euclid::return#1 ] zp[1]:8 [ euclid::return#2 ] zp[1]:10 [ euclid::return#3 ] Limited combination testing to 100 combinations of 2304 possible. Uplifting [main] best 589 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] Limited combination testing to 100 combinations of 256 possible. Uplifting [] best 589 combination Attempting to uplift remaining variables inzp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] Uplifting [euclid] best 589 combination zp[1]:3 [ euclid::a#5 euclid::a#10 euclid::a#4 ] Attempting to uplift remaining variables inzp[1]:8 [ euclid::return#2 ] Uplifting [euclid] best 583 combination reg byte a [ euclid::return#2 ] Attempting to uplift remaining variables inzp[1]:10 [ euclid::return#3 ] Uplifting [euclid] best 577 combination reg byte a [ euclid::return#3 ] Allocated (was zp[1]:3) zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments // Demonstrates a problem where wrong alive ranges result in clobbering an alive variable // The compiler does not realize that A is alive in the statement b=b-a - and thus can clobber it. // Upstart // Commodore 64 PRG executable file .file [name="euclid-problem-2.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 .label SCREEN = $400 .segment Code // main main: { // [1] call euclid // [18] phi from main to euclid [phi:main->euclid] euclid_from_main: // [18] phi euclid::b#9 = 2 [phi:main->euclid#0] -- vbuxx=vbuc1 ldx #2 // [18] phi euclid::a#10 = $80 [phi:main->euclid#1] -- vbuz1=vbuc1 lda #$80 sta.z euclid.a jsr euclid // [2] euclid::return#0 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b1 // main::@1 __b1: // [3] main::$0 = euclid::return#0 // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN // [5] call euclid // [18] phi from main::@1 to euclid [phi:main::@1->euclid] euclid_from___b1: // [18] phi euclid::b#9 = $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 ldx #$45 // [18] phi euclid::a#10 = $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 lda #$a9 sta.z euclid.a jsr euclid // [6] euclid::return#1 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b2 // main::@2 __b2: // [7] main::$1 = euclid::return#1 // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa sta SCREEN+1 // [9] call euclid // [18] phi from main::@2 to euclid [phi:main::@2->euclid] euclid_from___b2: // [18] phi euclid::b#9 = $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 ldx #$9b // [18] phi euclid::a#10 = $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 lda #$ff sta.z euclid.a jsr euclid // [10] euclid::return#2 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b3 // main::@3 __b3: // [11] main::$2 = euclid::return#2 // [12] *(SCREEN+2) = main::$2 -- _deref_pbuc1=vbuaa sta SCREEN+2 // [13] call euclid // [18] phi from main::@3 to euclid [phi:main::@3->euclid] euclid_from___b3: // [18] phi euclid::b#9 = 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 ldx #3 // [18] phi euclid::a#10 = $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 lda #$63 sta.z euclid.a jsr euclid // [14] euclid::return#3 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a jmp __b4 // main::@4 __b4: // [15] main::$3 = euclid::return#3 // [16] *(SCREEN+3) = main::$3 -- _deref_pbuc1=vbuaa sta SCREEN+3 jmp __breturn // main::@return __breturn: // [17] return rts } // euclid // Calculate least common denominator using euclids subtraction method // __register(A) char euclid(__zp(2) char a, __register(X) char b) euclid: { .label a = 2 // [19] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] __b1_from_euclid: __b1_from___b3: __b1_from___b4: // [19] phi euclid::b#5 = euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy // [19] phi euclid::a#5 = euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy jmp __b1 // euclid::@1 __b1: // [20] if(euclid::a#5!=euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 cpx.z a bne __b2 jmp __breturn // euclid::@return __breturn: // [21] return rts // euclid::@2 __b2: // [22] if(euclid::a#5>euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 cpx.z a bcc __b3 jmp __b4 // euclid::@4 __b4: // [23] euclid::b#4 = euclid::b#5 - euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 txa sec sbc.z a tax jmp __b1_from___b4 // euclid::@3 __b3: // [24] euclid::a#4 = euclid::a#5 - euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx txa eor #$ff sec adc.z a sta.z a jmp __b1_from___b3 } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __b3 Removing instruction jmp __b4 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __b4 Succesful ASM optimization Pass5NextJumpElimination Replacing label __b1_from___b4 with __b1 Replacing label __b1_from___b3 with __b1 Removing instruction __b1_from_euclid: Removing instruction __b1_from___b3: Removing instruction __b1_from___b4: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction euclid_from_main: Removing instruction __b1: Removing instruction euclid_from___b1: Removing instruction __b2: Removing instruction euclid_from___b2: Removing instruction __b3: Removing instruction euclid_from___b3: Removing instruction __b4: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __b4: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 char euclid(char a , char b) char euclid::a char euclid::a#10 // a zp[1]:2 11.0 char euclid::a#4 // a zp[1]:2 202.0 char euclid::a#5 // a zp[1]:2 80.66666666666666 char euclid::b char euclid::b#4 // reg byte x 202.0 char euclid::b#5 // reg byte x 179.5 char euclid::b#9 // reg byte x 11.0 char euclid::return char euclid::return#0 // reg byte a 4.0 char euclid::return#1 // reg byte a 4.0 char euclid::return#2 // reg byte a 4.0 char euclid::return#3 // reg byte a 4.0 char idx void main() char main::$0 // reg byte a 4.0 char main::$1 // reg byte a 4.0 char main::$2 // reg byte a 4.0 char main::$3 // reg byte a 4.0 zp[1]:2 [ euclid::a#5 euclid::a#10 euclid::a#4 ] reg byte x [ euclid::b#5 euclid::b#9 euclid::b#4 ] reg byte a [ euclid::return#0 ] reg byte a [ main::$0 ] reg byte a [ euclid::return#1 ] reg byte a [ main::$1 ] reg byte a [ euclid::return#2 ] reg byte a [ main::$2 ] reg byte a [ euclid::return#3 ] reg byte a [ main::$3 ] FINAL ASSEMBLER Score: 472 // File Comments // Demonstrates a problem where wrong alive ranges result in clobbering an alive variable // The compiler does not realize that A is alive in the statement b=b-a - and thus can clobber it. // Upstart // Commodore 64 PRG executable file .file [name="euclid-problem-2.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 .label SCREEN = $400 .segment Code // main main: { // euclid(128,2) // [1] call euclid // [18] phi from main to euclid [phi:main->euclid] // [18] phi euclid::b#9 = 2 [phi:main->euclid#0] -- vbuxx=vbuc1 ldx #2 // [18] phi euclid::a#10 = $80 [phi:main->euclid#1] -- vbuz1=vbuc1 lda #$80 sta.z euclid.a jsr euclid // euclid(128,2) // [2] euclid::return#0 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@1 // [3] main::$0 = euclid::return#0 // SCREEN[idx++] = euclid(128,2) // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN // euclid(169,69) // [5] call euclid // [18] phi from main::@1 to euclid [phi:main::@1->euclid] // [18] phi euclid::b#9 = $45 [phi:main::@1->euclid#0] -- vbuxx=vbuc1 ldx #$45 // [18] phi euclid::a#10 = $a9 [phi:main::@1->euclid#1] -- vbuz1=vbuc1 lda #$a9 sta.z euclid.a jsr euclid // euclid(169,69) // [6] euclid::return#1 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@2 // [7] main::$1 = euclid::return#1 // SCREEN[idx++] = euclid(169,69) // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa sta SCREEN+1 // euclid(255,155) // [9] call euclid // [18] phi from main::@2 to euclid [phi:main::@2->euclid] // [18] phi euclid::b#9 = $9b [phi:main::@2->euclid#0] -- vbuxx=vbuc1 ldx #$9b // [18] phi euclid::a#10 = $ff [phi:main::@2->euclid#1] -- vbuz1=vbuc1 lda #$ff sta.z euclid.a jsr euclid // euclid(255,155) // [10] euclid::return#2 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@3 // [11] main::$2 = euclid::return#2 // SCREEN[idx++] = euclid(255,155) // [12] *(SCREEN+2) = main::$2 -- _deref_pbuc1=vbuaa sta SCREEN+2 // euclid(99,3) // [13] call euclid // [18] phi from main::@3 to euclid [phi:main::@3->euclid] // [18] phi euclid::b#9 = 3 [phi:main::@3->euclid#0] -- vbuxx=vbuc1 ldx #3 // [18] phi euclid::a#10 = $63 [phi:main::@3->euclid#1] -- vbuz1=vbuc1 lda #$63 sta.z euclid.a jsr euclid // euclid(99,3) // [14] euclid::return#3 = euclid::a#5 -- vbuaa=vbuz1 lda.z euclid.a // main::@4 // [15] main::$3 = euclid::return#3 // SCREEN[idx++] = euclid(99,3) // [16] *(SCREEN+3) = main::$3 -- _deref_pbuc1=vbuaa sta SCREEN+3 // main::@return // } // [17] return rts } // euclid // Calculate least common denominator using euclids subtraction method // __register(A) char euclid(__zp(2) char a, __register(X) char b) euclid: { .label a = 2 // [19] phi from euclid euclid::@3 euclid::@4 to euclid::@1 [phi:euclid/euclid::@3/euclid::@4->euclid::@1] // [19] phi euclid::b#5 = euclid::b#9 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#0] -- register_copy // [19] phi euclid::a#5 = euclid::a#10 [phi:euclid/euclid::@3/euclid::@4->euclid::@1#1] -- register_copy // euclid::@1 __b1: // while (a!=b) // [20] if(euclid::a#5!=euclid::b#5) goto euclid::@2 -- vbuz1_neq_vbuxx_then_la1 cpx.z a bne __b2 // euclid::@return // } // [21] return rts // euclid::@2 __b2: // if(a>b) // [22] if(euclid::a#5>euclid::b#5) goto euclid::@3 -- vbuz1_gt_vbuxx_then_la1 cpx.z a bcc __b3 // euclid::@4 // b = b-a // [23] euclid::b#4 = euclid::b#5 - euclid::a#5 -- vbuxx=vbuxx_minus_vbuz1 txa sec sbc.z a tax jmp __b1 // euclid::@3 __b3: // a = a-b // [24] euclid::a#4 = euclid::a#5 - euclid::b#5 -- vbuz1=vbuz1_minus_vbuxx txa eor #$ff sec adc.z a sta.z a jmp __b1 } // File Data