Inlined call call __init CONTROL FLOW GRAPH SSA void print_uint(unsigned int w) print_uint: scope:[print_uint] from main print_char_cursor#25 = phi( main/print_char_cursor#27 ) print_uint::w#1 = phi( main/print_uint::w#0 ) print_uint::$0 = byte1 print_uint::w#1 print_uchar::b#0 = print_uint::$0 call print_uchar to:print_uint::@1 print_uint::@1: scope:[print_uint] from print_uint print_uint::w#2 = phi( print_uint/print_uint::w#1 ) print_char_cursor#13 = phi( print_uint/print_char_cursor#5 ) print_char_cursor#0 = print_char_cursor#13 print_uint::$2 = byte0 print_uint::w#2 print_uchar::b#1 = print_uint::$2 call print_uchar to:print_uint::@2 print_uint::@2: scope:[print_uint] from print_uint::@1 print_char_cursor#14 = phi( print_uint::@1/print_char_cursor#5 ) print_char_cursor#1 = print_char_cursor#14 to:print_uint::@return print_uint::@return: scope:[print_uint] from print_uint::@2 print_char_cursor#15 = phi( print_uint::@2/print_char_cursor#1 ) print_char_cursor#2 = print_char_cursor#15 return to:@return void print_uchar(char b) print_uchar: scope:[print_uchar] from print_uint print_uint::@1 print_char_cursor#26 = phi( print_uint/print_char_cursor#25, print_uint::@1/print_char_cursor#0 ) print_uchar::b#2 = phi( print_uint/print_uchar::b#0, print_uint::@1/print_uchar::b#1 ) print_uchar::$0 = print_uchar::b#2 >> 4 print_char::ch#0 = print_hextab[print_uchar::$0] call print_char to:print_uchar::@1 print_uchar::@1: scope:[print_uchar] from print_uchar print_uchar::b#3 = phi( print_uchar/print_uchar::b#2 ) print_char_cursor#16 = phi( print_uchar/print_char_cursor#7 ) print_char_cursor#3 = print_char_cursor#16 print_uchar::$2 = print_uchar::b#3 & $f print_char::ch#1 = print_hextab[print_uchar::$2] call print_char to:print_uchar::@2 print_uchar::@2: scope:[print_uchar] from print_uchar::@1 print_char_cursor#17 = phi( print_uchar::@1/print_char_cursor#7 ) print_char_cursor#4 = print_char_cursor#17 to:print_uchar::@return print_uchar::@return: scope:[print_uchar] from print_uchar::@2 print_char_cursor#18 = phi( print_uchar::@2/print_char_cursor#4 ) print_char_cursor#5 = print_char_cursor#18 return to:@return void print_char(char ch) print_char: scope:[print_char] from print_uchar print_uchar::@1 print_char_cursor#19 = phi( print_uchar/print_char_cursor#26, print_uchar::@1/print_char_cursor#3 ) print_char::ch#2 = phi( print_uchar/print_char::ch#0, print_uchar::@1/print_char::ch#1 ) *print_char_cursor#19 = print_char::ch#2 print_char_cursor#6 = ++ print_char_cursor#19 to:print_char::@return print_char::@return: scope:[print_char] from print_char print_char_cursor#20 = phi( print_char/print_char_cursor#6 ) print_char_cursor#7 = print_char_cursor#20 return to:@return void main() main: scope:[main] from __start::@1 print_char_cursor#27 = phi( __start::@1/print_char_cursor#28 ) main::file#0 = (struct fileentry *) 0 main::uSize#0 = 0 main::file#1 = (struct fileentry *)$4000 main::$4 = (char **)main::file#1 main::$2 = main::$4 + OFFSET_STRUCT_FILEENTRY_BUFEDIT *main::$2 = (char *)4 main::$5 = (char **)main::file#1 main::$3 = main::$5 + OFFSET_STRUCT_FILEENTRY_BUFEDIT main::$0 = *main::$3 + $1e main::ptrw#0 = (unsigned int *)main::$0 main::uSize#1 = *main::ptrw#0 print_uint::w#0 = main::uSize#1 call print_uint to:main::@1 main::@1: scope:[main] from main print_char_cursor#21 = phi( main/print_char_cursor#2 ) print_char_cursor#8 = print_char_cursor#21 to:main::@return main::@return: scope:[main] from main::@1 print_char_cursor#22 = phi( main::@1/print_char_cursor#8 ) print_char_cursor#9 = print_char_cursor#22 return to:@return void __start() __start: scope:[__start] from to:__start::__init1 __start::__init1: scope:[__start] from __start print_screen#0 = (char *)$400 print_line_cursor#0 = print_screen#0 print_char_cursor#10 = print_line_cursor#0 to:__start::@1 __start::@1: scope:[__start] from __start::__init1 print_line_cursor#4 = phi( __start::__init1/print_line_cursor#0 ) print_screen#4 = phi( __start::__init1/print_screen#0 ) print_char_cursor#28 = phi( __start::__init1/print_char_cursor#10 ) call main to:__start::@2 __start::@2: scope:[__start] from __start::@1 print_line_cursor#3 = phi( __start::@1/print_line_cursor#4 ) print_screen#3 = phi( __start::@1/print_screen#4 ) print_char_cursor#23 = phi( __start::@1/print_char_cursor#9 ) print_char_cursor#11 = print_char_cursor#23 to:__start::@return __start::@return: scope:[__start] from __start::@2 print_char_cursor#24 = phi( __start::@2/print_char_cursor#11 ) print_line_cursor#2 = phi( __start::@2/print_line_cursor#3 ) print_screen#2 = phi( __start::@2/print_screen#3 ) print_screen#1 = print_screen#2 print_line_cursor#1 = print_line_cursor#2 print_char_cursor#12 = print_char_cursor#24 return to:@return SYMBOL TABLE SSA __constant char OFFSET_STRUCT_FILEENTRY_BUFEDIT = 0 __constant char RADIX::BINARY = 2 __constant char RADIX::DECIMAL = $a __constant char RADIX::HEXADECIMAL = $10 __constant char RADIX::OCTAL = 8 void __start() void main() char *main::$0 char **main::$2 char **main::$3 char **main::$4 char **main::$5 struct fileentry *main::file struct fileentry *main::file#0 struct fileentry *main::file#1 unsigned int *main::ptrw unsigned int *main::ptrw#0 unsigned int main::uSize unsigned int main::uSize#0 unsigned int main::uSize#1 void print_char(char ch) char print_char::ch char print_char::ch#0 char print_char::ch#1 char print_char::ch#2 char *print_char_cursor char *print_char_cursor#0 char *print_char_cursor#1 char *print_char_cursor#10 char *print_char_cursor#11 char *print_char_cursor#12 char *print_char_cursor#13 char *print_char_cursor#14 char *print_char_cursor#15 char *print_char_cursor#16 char *print_char_cursor#17 char *print_char_cursor#18 char *print_char_cursor#19 char *print_char_cursor#2 char *print_char_cursor#20 char *print_char_cursor#21 char *print_char_cursor#22 char *print_char_cursor#23 char *print_char_cursor#24 char *print_char_cursor#25 char *print_char_cursor#26 char *print_char_cursor#27 char *print_char_cursor#28 char *print_char_cursor#3 char *print_char_cursor#4 char *print_char_cursor#5 char *print_char_cursor#6 char *print_char_cursor#7 char *print_char_cursor#8 char *print_char_cursor#9 __constant const char print_hextab[] = "0123456789abcdef"z char *print_line_cursor char *print_line_cursor#0 char *print_line_cursor#1 char *print_line_cursor#2 char *print_line_cursor#3 char *print_line_cursor#4 char *print_screen char *print_screen#0 char *print_screen#1 char *print_screen#2 char *print_screen#3 char *print_screen#4 void print_uchar(char b) char print_uchar::$0 number print_uchar::$2 char print_uchar::b char print_uchar::b#0 char print_uchar::b#1 char print_uchar::b#2 char print_uchar::b#3 void print_uint(unsigned int w) char print_uint::$0 char print_uint::$2 unsigned int print_uint::w unsigned int print_uint::w#0 unsigned int print_uint::w#1 unsigned int print_uint::w#2 Adding number conversion cast (unumber) 4 in print_uchar::$0 = print_uchar::b#2 >> 4 Adding number conversion cast (unumber) $f in print_uchar::$2 = print_uchar::b#3 & $f Adding number conversion cast (unumber) print_uchar::$2 in print_uchar::$2 = print_uchar::b#3 & (unumber)$f Adding number conversion cast (unumber) $1e in main::$0 = *main::$3 + $1e Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast 4 Simplifying constant integer cast $f Simplifying constant pointer cast (struct fileentry *) 16384 Simplifying constant pointer cast (char *) 4 Simplifying constant integer cast $1e Simplifying constant pointer cast (char *) 1024 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 4 Finalized unsigned number type (char) $f Finalized unsigned number type (char) $1e Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to char in print_uchar::$2 = print_uchar::b#3 & $f Alias print_uchar::b#0 = print_uint::$0 Alias print_uint::w#1 = print_uint::w#2 Alias print_char_cursor#0 = print_char_cursor#13 Alias print_uchar::b#1 = print_uint::$2 Alias print_char_cursor#1 = print_char_cursor#14 print_char_cursor#15 print_char_cursor#2 Alias print_uchar::b#2 = print_uchar::b#3 Alias print_char_cursor#16 = print_char_cursor#3 Alias print_char_cursor#17 = print_char_cursor#4 print_char_cursor#18 print_char_cursor#5 Alias print_char_cursor#20 = print_char_cursor#6 print_char_cursor#7 Alias print_char_cursor#21 = print_char_cursor#8 print_char_cursor#22 print_char_cursor#9 Alias print_screen#0 = print_line_cursor#0 print_char_cursor#10 print_char_cursor#28 print_screen#4 print_line_cursor#4 print_screen#3 print_line_cursor#3 print_screen#2 print_line_cursor#2 print_screen#1 print_line_cursor#1 Alias print_char_cursor#11 = print_char_cursor#23 print_char_cursor#24 print_char_cursor#12 Successful SSA optimization Pass2AliasElimination Identical Phi Values print_uint::w#1 print_uint::w#0 Identical Phi Values print_char_cursor#25 print_char_cursor#27 Identical Phi Values print_char_cursor#0 print_char_cursor#17 Identical Phi Values print_char_cursor#1 print_char_cursor#17 Identical Phi Values print_char_cursor#16 print_char_cursor#20 Identical Phi Values print_char_cursor#17 print_char_cursor#20 Identical Phi Values print_char_cursor#27 print_screen#0 Identical Phi Values print_char_cursor#21 print_char_cursor#1 Identical Phi Values print_char_cursor#11 print_char_cursor#21 Successful SSA optimization Pass2IdenticalPhiElimination Constant main::file#0 = (struct fileentry *) 0 Constant main::uSize#0 = 0 Constant main::file#1 = (struct fileentry *) 16384 Constant print_screen#0 = (char *) 1024 Successful SSA optimization Pass2ConstantIdentification Constant main::$4 = (char **)main::file#1 Constant main::$5 = (char **)main::file#1 Successful SSA optimization Pass2ConstantIdentification Converting *(pointer+n) to pointer[n] [28] *main::$2 = (char *) 4 -- main::$4[OFFSET_STRUCT_FILEENTRY_BUFEDIT] Converting *(pointer+n) to pointer[n] [31] main::$0 = *main::$3 + $1e -- main::$5[OFFSET_STRUCT_FILEENTRY_BUFEDIT] Converting *(pointer+n) to pointer[n] [33] main::uSize#1 = *main::ptrw#0 -- ((unsigned int *)main::$5[OFFSET_STRUCT_FILEENTRY_BUFEDIT])[$1e] Successful SSA optimization Pass2InlineDerefIdx Simplifying expression containing zero main::$4 in [27] main::$2 = main::$4 + OFFSET_STRUCT_FILEENTRY_BUFEDIT Simplifying expression containing zero main::$4 in [28] main::$4[OFFSET_STRUCT_FILEENTRY_BUFEDIT] = (char *) 4 Simplifying expression containing zero main::$5 in [30] main::$3 = main::$5 + OFFSET_STRUCT_FILEENTRY_BUFEDIT Simplifying expression containing zero main::$5 in [31] main::$0 = main::$5[OFFSET_STRUCT_FILEENTRY_BUFEDIT] + $1e Simplifying expression containing zero main::$5 in [33] main::uSize#1 = ((unsigned int *)main::$5[OFFSET_STRUCT_FILEENTRY_BUFEDIT])[$1e] Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable main::$2 and assignment [17] main::$2 = main::$4 Eliminating unused variable main::$3 and assignment [19] main::$3 = main::$5 Eliminating unused variable main::ptrw#0 and assignment [21] main::ptrw#0 = (unsigned int *)main::$0 Eliminating unused constant main::file#0 Eliminating unused constant main::uSize#0 Eliminating unused constant OFFSET_STRUCT_FILEENTRY_BUFEDIT Successful SSA optimization PassNEliminateUnusedVars Eliminating unused variable main::$0 and assignment [18] main::$0 = *main::$5 + $1e 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 inlined main::$5 = (char **)main::file#1 Constant inlined main::$4 = (char **)main::file#1 Successful SSA optimization Pass2ConstantInlining Finalized unsigned number type (char) 2 Finalized unsigned number type (char) 8 Finalized unsigned number type (char) $a Finalized unsigned number type (char) $10 Successful SSA optimization PassNFinalizeNumberTypeConversions Adding NOP phi() at start of main::@1 Adding NOP phi() at start of print_uint::@2 Adding NOP phi() at start of print_uchar::@2 CALL GRAPH Calls in [main] to print_uint:3 Calls in [print_uint] to print_uchar:8 print_uchar:12 Calls in [print_uchar] to print_char:20 print_char:25 Created 4 initial phi equivalence classes Coalesced [7] print_uchar::b#4 = print_uchar::b#0 Coalesced [10] print_uchar::b#5 = print_uchar::b#1 Coalesced [11] print_char_cursor#29 = print_char_cursor#20 Coalesced [18] print_char::ch#3 = print_char::ch#0 Coalesced [19] print_char_cursor#30 = print_char_cursor#26 Coalesced [23] print_char::ch#4 = print_char::ch#1 Coalesced (already) [24] print_char_cursor#31 = print_char_cursor#20 Coalesced down to 3 phi equivalence classes Culled Empty Block label main::@1 Culled Empty Block label print_uint::@2 Culled Empty Block label print_uchar::@2 FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] *((char **)main::file#1) = (char *) 4 [1] main::uSize#1 = ((unsigned int *)*((char **)main::file#1))[$1e] [2] print_uint::w#0 = main::uSize#1 [3] call print_uint to:main::@return main::@return: scope:[main] from main [4] return to:@return void print_uint(unsigned int w) print_uint: scope:[print_uint] from main [5] print_uchar::b#0 = byte1 print_uint::w#0 [6] call print_uchar to:print_uint::@1 print_uint::@1: scope:[print_uint] from print_uint [7] print_uchar::b#1 = byte0 print_uint::w#0 [8] call print_uchar to:print_uint::@return print_uint::@return: scope:[print_uint] from print_uint::@1 [9] return to:@return void print_uchar(char b) print_uchar: scope:[print_uchar] from print_uint print_uint::@1 [10] print_char_cursor#26 = phi( print_uint/print_screen#0, print_uint::@1/print_char_cursor#20 ) [10] print_uchar::b#2 = phi( print_uint/print_uchar::b#0, print_uint::@1/print_uchar::b#1 ) [11] print_uchar::$0 = print_uchar::b#2 >> 4 [12] print_char::ch#0 = print_hextab[print_uchar::$0] [13] call print_char to:print_uchar::@1 print_uchar::@1: scope:[print_uchar] from print_uchar [14] print_uchar::$2 = print_uchar::b#2 & $f [15] print_char::ch#1 = print_hextab[print_uchar::$2] [16] call print_char to:print_uchar::@return print_uchar::@return: scope:[print_uchar] from print_uchar::@1 [17] return to:@return void print_char(char ch) print_char: scope:[print_char] from print_uchar print_uchar::@1 [18] print_char_cursor#19 = phi( print_uchar/print_char_cursor#26, print_uchar::@1/print_char_cursor#20 ) [18] print_char::ch#2 = phi( print_uchar/print_char::ch#0, print_uchar::@1/print_char::ch#1 ) [19] *print_char_cursor#19 = print_char::ch#2 [20] print_char_cursor#20 = ++ print_char_cursor#19 to:print_char::@return print_char::@return: scope:[print_char] from print_char [21] return to:@return VARIABLE REGISTER WEIGHTS void main() struct fileentry *main::file unsigned int *main::ptrw unsigned int main::uSize unsigned int main::uSize#1 // 4.0 void print_char(char ch) char print_char::ch char print_char::ch#0 // 202.0 char print_char::ch#1 // 202.0 char print_char::ch#2 // 1203.0 char *print_char_cursor char *print_char_cursor#19 // 1102.0 char *print_char_cursor#20 // 123.66666666666667 char *print_char_cursor#26 // 37.33333333333333 char *print_line_cursor char *print_screen void print_uchar(char b) char print_uchar::$0 // 202.0 char print_uchar::$2 // 202.0 char print_uchar::b char print_uchar::b#0 // 22.0 char print_uchar::b#1 // 22.0 char print_uchar::b#2 // 56.0 void print_uint(unsigned int w) unsigned int print_uint::w unsigned int print_uint::w#0 // 8.0 Initial phi equivalence classes [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] Added variable main::uSize#1 to live range equivalence class [ main::uSize#1 ] Added variable print_uint::w#0 to live range equivalence class [ print_uint::w#0 ] Added variable print_uchar::$0 to live range equivalence class [ print_uchar::$0 ] Added variable print_uchar::$2 to live range equivalence class [ print_uchar::$2 ] Complete equivalence classes [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] [ main::uSize#1 ] [ print_uint::w#0 ] [ print_uchar::$0 ] [ print_uchar::$2 ] Allocated zp[1]:2 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] Allocated zp[2]:3 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] Allocated zp[1]:5 [ print_uchar::$0 ] Allocated zp[1]:6 [ print_uchar::$2 ] Allocated zp[1]:7 [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] Allocated zp[2]:8 [ print_uint::w#0 ] Allocated zp[2]:10 [ main::uSize#1 ] REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] *((char **)main::file#1) = (char *) 4 [ ] ( [ ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a Statement [1] main::uSize#1 = ((unsigned int *)*((char **)main::file#1))[$1e] [ main::uSize#1 ] ( [ main::uSize#1 ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a reg byte y Statement [2] print_uint::w#0 = main::uSize#1 [ print_uint::w#0 ] ( [ print_uint::w#0 ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a Statement [11] print_uchar::$0 = print_uchar::b#2 >> 4 [ print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] ( print_uint:3::print_uchar:6 [ print_uint::w#0 print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#0 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#26 } } print_uint:3::print_uchar:8 [ print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#0 = print_char::ch#2 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:7 [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] Statement [14] print_uchar::$2 = print_uchar::b#2 & $f [ print_char_cursor#20 print_uchar::$2 ] ( print_uint:3::print_uchar:6 [ print_uint::w#0 print_char_cursor#20 print_uchar::$2 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#1 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#20 } } print_uint:3::print_uchar:8 [ print_char_cursor#20 print_uchar::$2 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#1 = print_char::ch#2 } } ) always clobbers reg byte a Statement [19] *print_char_cursor#19 = print_char::ch#2 [ print_char_cursor#19 ] ( print_uint:3::print_uchar:6::print_char:13 [ print_uint::w#0 print_uchar::b#2 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#0 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#26 } } print_uint:3::print_uchar:8::print_char:13 [ print_uchar::b#2 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#0 = print_char::ch#2 } } print_uint:3::print_uchar:6::print_char:16 [ print_uint::w#0 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#1 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#20 } } print_uint:3::print_uchar:8::print_char:16 [ print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#1 = print_char::ch#2 } } ) always clobbers reg byte y Removing always clobbered register reg byte y as potential for zp[1]:7 [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] Statement [0] *((char **)main::file#1) = (char *) 4 [ ] ( [ ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a Statement [1] main::uSize#1 = ((unsigned int *)*((char **)main::file#1))[$1e] [ main::uSize#1 ] ( [ main::uSize#1 ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a reg byte y Statement [2] print_uint::w#0 = main::uSize#1 [ print_uint::w#0 ] ( [ print_uint::w#0 ] { { print_uint::w#0 = main::uSize#1 } } ) always clobbers reg byte a Statement [11] print_uchar::$0 = print_uchar::b#2 >> 4 [ print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] ( print_uint:3::print_uchar:6 [ print_uint::w#0 print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#0 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#26 } } print_uint:3::print_uchar:8 [ print_uchar::b#2 print_char_cursor#26 print_uchar::$0 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#0 = print_char::ch#2 } } ) always clobbers reg byte a Statement [14] print_uchar::$2 = print_uchar::b#2 & $f [ print_char_cursor#20 print_uchar::$2 ] ( print_uint:3::print_uchar:6 [ print_uint::w#0 print_char_cursor#20 print_uchar::$2 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#1 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#20 } } print_uint:3::print_uchar:8 [ print_char_cursor#20 print_uchar::$2 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#1 = print_char::ch#2 } } ) always clobbers reg byte a Statement [19] *print_char_cursor#19 = print_char::ch#2 [ print_char_cursor#19 ] ( print_uint:3::print_uchar:6::print_char:13 [ print_uint::w#0 print_uchar::b#2 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#0 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#26 } } print_uint:3::print_uchar:8::print_char:13 [ print_uchar::b#2 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#0 = print_char::ch#2 } } print_uint:3::print_uchar:6::print_char:16 [ print_uint::w#0 print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#0 = print_uchar::b#2 } { print_char::ch#1 = print_char::ch#2 } { print_char_cursor#19 = print_char_cursor#20 } } print_uint:3::print_uchar:8::print_char:16 [ print_char_cursor#19 ] { { print_uint::w#0 = main::uSize#1 } { print_uchar::b#1 = print_uchar::b#2 } { print_char_cursor#19 = print_char_cursor#26 print_char_cursor#20 } { print_char::ch#1 = print_char::ch#2 } } ) always clobbers reg byte y Potential registers zp[1]:7 [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] : zp[1]:7 , reg byte x , Potential registers zp[1]:2 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , Potential registers zp[2]:3 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] : zp[2]:3 , Potential registers zp[2]:10 [ main::uSize#1 ] : zp[2]:10 , Potential registers zp[2]:8 [ print_uint::w#0 ] : zp[2]:8 , Potential registers zp[1]:5 [ print_uchar::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:6 [ print_uchar::$2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [print_char] 1,607: zp[1]:2 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] Uplift Scope [] 1,263: zp[2]:3 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] Uplift Scope [print_uchar] 202: zp[1]:5 [ print_uchar::$0 ] 202: zp[1]:6 [ print_uchar::$2 ] 100: zp[1]:7 [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] Uplift Scope [print_uint] 8: zp[2]:8 [ print_uint::w#0 ] Uplift Scope [main] 4: zp[2]:10 [ main::uSize#1 ] Uplift Scope [RADIX] Uplift Scope [fileentry] Uplifting [print_char] best 209 combination reg byte a [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] Uplifting [] best 209 combination zp[2]:3 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] Uplifting [print_uchar] best 191 combination reg byte a [ print_uchar::$0 ] reg byte x [ print_uchar::$2 ] reg byte x [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] Uplifting [print_uint] best 191 combination zp[2]:8 [ print_uint::w#0 ] Uplifting [main] best 191 combination zp[2]:10 [ main::uSize#1 ] Uplifting [RADIX] best 191 combination Uplifting [fileentry] best 191 combination Coalescing zero page register [ zp[2]:10 [ main::uSize#1 ] ] with [ zp[2]:8 [ print_uint::w#0 ] ] - score: 1 Allocated (was zp[2]:3) zp[2]:2 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] Allocated (was zp[2]:10) zp[2]:4 [ main::uSize#1 print_uint::w#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments /// @file /// A lightweight library for printing on the C64. /// /// Printing with this library is done by calling print_ function for each element // Upstart // Commodore 64 PRG executable file .file [name="struct-ptr-26.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 print_screen = $400 .label print_char_cursor = 2 .segment Code // main main: { .label file = $4000 .label uSize = 4 // [0] *((char **)main::file#1) = (char *) 4 -- _deref_qbuc1=pbuc2 lda #<4 sta file lda #>4 sta file+1 // [1] main::uSize#1 = ((unsigned int *)*((char **)main::file#1))[$1e] -- vwuz1=(_deref_qwuc1)_derefidx_vbuc2 ldy #$1e lda file sta.z $fe lda file+1 sta.z $ff lda ($fe),y sta.z uSize iny lda ($fe),y sta.z uSize+1 // [2] print_uint::w#0 = main::uSize#1 // [3] call print_uint jsr print_uint jmp __breturn // main::@return __breturn: // [4] return rts } // print_uint // Print a unsigned int as HEX // void print_uint(__zp(4) unsigned int w) print_uint: { .label w = 4 // [5] print_uchar::b#0 = byte1 print_uint::w#0 -- vbuxx=_byte1_vwuz1 ldx.z w+1 // [6] call print_uchar // [10] phi from print_uint to print_uchar [phi:print_uint->print_uchar] print_uchar_from_print_uint: // [10] phi print_char_cursor#26 = print_screen#0 [phi:print_uint->print_uchar#0] -- pbuz1=pbuc1 lda #print_screen sta.z print_char_cursor+1 // [10] phi print_uchar::b#2 = print_uchar::b#0 [phi:print_uint->print_uchar#1] -- register_copy jsr print_uchar jmp __b1 // print_uint::@1 __b1: // [7] print_uchar::b#1 = byte0 print_uint::w#0 -- vbuxx=_byte0_vwuz1 ldx.z w // [8] call print_uchar // [10] phi from print_uint::@1 to print_uchar [phi:print_uint::@1->print_uchar] print_uchar_from___b1: // [10] phi print_char_cursor#26 = print_char_cursor#20 [phi:print_uint::@1->print_uchar#0] -- register_copy // [10] phi print_uchar::b#2 = print_uchar::b#1 [phi:print_uint::@1->print_uchar#1] -- register_copy jsr print_uchar jmp __breturn // print_uint::@return __breturn: // [9] return rts } // print_uchar // Print a char as HEX // void print_uchar(__register(X) char b) print_uchar: { // [11] print_uchar::$0 = print_uchar::b#2 >> 4 -- vbuaa=vbuxx_ror_4 txa lsr lsr lsr lsr // [12] print_char::ch#0 = print_hextab[print_uchar::$0] -- vbuaa=pbuc1_derefidx_vbuaa tay lda print_hextab,y // [13] call print_char // Table of hexadecimal digits // [18] phi from print_uchar to print_char [phi:print_uchar->print_char] print_char_from_print_uchar: // [18] phi print_char_cursor#19 = print_char_cursor#26 [phi:print_uchar->print_char#0] -- register_copy // [18] phi print_char::ch#2 = print_char::ch#0 [phi:print_uchar->print_char#1] -- register_copy jsr print_char jmp __b1 // print_uchar::@1 __b1: // [14] print_uchar::$2 = print_uchar::b#2 & $f -- vbuxx=vbuxx_band_vbuc1 lda #$f axs #0 // [15] print_char::ch#1 = print_hextab[print_uchar::$2] -- vbuaa=pbuc1_derefidx_vbuxx lda print_hextab,x // [16] call print_char // [18] phi from print_uchar::@1 to print_char [phi:print_uchar::@1->print_char] print_char_from___b1: // [18] phi print_char_cursor#19 = print_char_cursor#20 [phi:print_uchar::@1->print_char#0] -- register_copy // [18] phi print_char::ch#2 = print_char::ch#1 [phi:print_uchar::@1->print_char#1] -- register_copy jsr print_char jmp __breturn // print_uchar::@return __breturn: // [17] return rts } // print_char // Print a single char // void print_char(__register(A) char ch) print_char: { // [19] *print_char_cursor#19 = print_char::ch#2 -- _deref_pbuz1=vbuaa ldy #0 sta (print_char_cursor),y // [20] print_char_cursor#20 = ++ print_char_cursor#19 -- pbuz1=_inc_pbuz1 inc.z print_char_cursor bne !+ inc.z print_char_cursor+1 !: jmp __breturn // print_char::@return __breturn: // [21] return rts } // File Data .segment Data print_hextab: .text "0123456789abcdef" ASSEMBLER OPTIMIZATIONS Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __breturn: Removing instruction print_uchar_from_print_uint: Removing instruction __b1: Removing instruction print_uchar_from___b1: Removing instruction __breturn: Removing instruction print_char_from_print_uchar: Removing instruction __b1: Removing instruction print_char_from___b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char RADIX::BINARY = 2 __constant char RADIX::DECIMAL = $a __constant char RADIX::HEXADECIMAL = $10 __constant char RADIX::OCTAL = 8 void main() struct fileentry *main::file __constant struct fileentry *main::file#1 = (struct fileentry *) 16384 // file unsigned int *main::ptrw unsigned int main::uSize unsigned int main::uSize#1 // uSize zp[2]:4 4.0 void print_char(char ch) char print_char::ch char print_char::ch#0 // reg byte a 202.0 char print_char::ch#1 // reg byte a 202.0 char print_char::ch#2 // reg byte a 1203.0 char *print_char_cursor char *print_char_cursor#19 // print_char_cursor zp[2]:2 1102.0 char *print_char_cursor#20 // print_char_cursor zp[2]:2 123.66666666666667 char *print_char_cursor#26 // print_char_cursor zp[2]:2 37.33333333333333 __constant const char print_hextab[] = "0123456789abcdef"z char *print_line_cursor char *print_screen __constant char *print_screen#0 = (char *) 1024 // print_screen void print_uchar(char b) char print_uchar::$0 // reg byte a 202.0 char print_uchar::$2 // reg byte x 202.0 char print_uchar::b char print_uchar::b#0 // reg byte x 22.0 char print_uchar::b#1 // reg byte x 22.0 char print_uchar::b#2 // reg byte x 56.0 void print_uint(unsigned int w) unsigned int print_uint::w unsigned int print_uint::w#0 // w zp[2]:4 8.0 reg byte x [ print_uchar::b#2 print_uchar::b#0 print_uchar::b#1 ] reg byte a [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] zp[2]:2 [ print_char_cursor#19 print_char_cursor#26 print_char_cursor#20 ] zp[2]:4 [ main::uSize#1 print_uint::w#0 ] reg byte a [ print_uchar::$0 ] reg byte x [ print_uchar::$2 ] FINAL ASSEMBLER Score: 161 // File Comments /// @file /// A lightweight library for printing on the C64. /// /// Printing with this library is done by calling print_ function for each element // Upstart // Commodore 64 PRG executable file .file [name="struct-ptr-26.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 print_screen = $400 .label print_char_cursor = 2 .segment Code // main main: { .label file = $4000 .label uSize = 4 // file->bufEdit = (BYTE*)4 // [0] *((char **)main::file#1) = (char *) 4 -- _deref_qbuc1=pbuc2 lda #<4 sta file lda #>4 sta file+1 // uSize = *ptrw // [1] main::uSize#1 = ((unsigned int *)*((char **)main::file#1))[$1e] -- vwuz1=(_deref_qwuc1)_derefidx_vbuc2 ldy #$1e lda file sta.z $fe lda file+1 sta.z $ff lda ($fe),y sta.z uSize iny lda ($fe),y sta.z uSize+1 // print_uint(uSize) // [2] print_uint::w#0 = main::uSize#1 // [3] call print_uint jsr print_uint // main::@return // } // [4] return rts } // print_uint // Print a unsigned int as HEX // void print_uint(__zp(4) unsigned int w) print_uint: { .label w = 4 // print_uchar(BYTE1(w)) // [5] print_uchar::b#0 = byte1 print_uint::w#0 -- vbuxx=_byte1_vwuz1 ldx.z w+1 // [6] call print_uchar // [10] phi from print_uint to print_uchar [phi:print_uint->print_uchar] // [10] phi print_char_cursor#26 = print_screen#0 [phi:print_uint->print_uchar#0] -- pbuz1=pbuc1 lda #print_screen sta.z print_char_cursor+1 // [10] phi print_uchar::b#2 = print_uchar::b#0 [phi:print_uint->print_uchar#1] -- register_copy jsr print_uchar // print_uint::@1 // print_uchar(BYTE0(w)) // [7] print_uchar::b#1 = byte0 print_uint::w#0 -- vbuxx=_byte0_vwuz1 ldx.z w // [8] call print_uchar // [10] phi from print_uint::@1 to print_uchar [phi:print_uint::@1->print_uchar] // [10] phi print_char_cursor#26 = print_char_cursor#20 [phi:print_uint::@1->print_uchar#0] -- register_copy // [10] phi print_uchar::b#2 = print_uchar::b#1 [phi:print_uint::@1->print_uchar#1] -- register_copy jsr print_uchar // print_uint::@return // } // [9] return rts } // print_uchar // Print a char as HEX // void print_uchar(__register(X) char b) print_uchar: { // b>>4 // [11] print_uchar::$0 = print_uchar::b#2 >> 4 -- vbuaa=vbuxx_ror_4 txa lsr lsr lsr lsr // print_char(print_hextab[b>>4]) // [12] print_char::ch#0 = print_hextab[print_uchar::$0] -- vbuaa=pbuc1_derefidx_vbuaa tay lda print_hextab,y // [13] call print_char // Table of hexadecimal digits // [18] phi from print_uchar to print_char [phi:print_uchar->print_char] // [18] phi print_char_cursor#19 = print_char_cursor#26 [phi:print_uchar->print_char#0] -- register_copy // [18] phi print_char::ch#2 = print_char::ch#0 [phi:print_uchar->print_char#1] -- register_copy jsr print_char // print_uchar::@1 // b&0xf // [14] print_uchar::$2 = print_uchar::b#2 & $f -- vbuxx=vbuxx_band_vbuc1 lda #$f axs #0 // print_char(print_hextab[b&0xf]) // [15] print_char::ch#1 = print_hextab[print_uchar::$2] -- vbuaa=pbuc1_derefidx_vbuxx lda print_hextab,x // [16] call print_char // [18] phi from print_uchar::@1 to print_char [phi:print_uchar::@1->print_char] // [18] phi print_char_cursor#19 = print_char_cursor#20 [phi:print_uchar::@1->print_char#0] -- register_copy // [18] phi print_char::ch#2 = print_char::ch#1 [phi:print_uchar::@1->print_char#1] -- register_copy jsr print_char // print_uchar::@return // } // [17] return rts } // print_char // Print a single char // void print_char(__register(A) char ch) print_char: { // *(print_char_cursor++) = ch // [19] *print_char_cursor#19 = print_char::ch#2 -- _deref_pbuz1=vbuaa ldy #0 sta (print_char_cursor),y // *(print_char_cursor++) = ch; // [20] print_char_cursor#20 = ++ print_char_cursor#19 -- pbuz1=_inc_pbuz1 inc.z print_char_cursor bne !+ inc.z print_char_cursor+1 !: // print_char::@return // } // [21] return rts } // File Data .segment Data print_hextab: .text "0123456789abcdef"