Warning! Adding boolean cast to non-boolean condition *((byte*) print::msg) Culled Empty Block (label) @1 Culled Empty Block (label) print_msg::@4 Culled Empty Block (label) print::@4 Culled Empty Block (label) print::@3 Culled Empty Block (label) print::@5 Culled Empty Block (label) print::@6 CONTROL FLOW GRAPH SSA @begin: scope:[] from to:@2 (void()) main() main: scope:[main] from @3 (byte*) screen#17 ← phi( @3/(byte*) screen#20 ) (byte) print_msg::idx#0 ← (number) 1 call print_msg to:main::@1 main::@1: scope:[main] from main (byte*) screen#9 ← phi( main/(byte*) screen#4 ) (byte*) screen#0 ← (byte*) screen#9 (byte) print_msg::idx#1 ← (number) 2 call print_msg to:main::@2 main::@2: scope:[main] from main::@1 (byte*) screen#10 ← phi( main::@1/(byte*) screen#4 ) (byte*) screen#1 ← (byte*) screen#10 to:main::@return main::@return: scope:[main] from main::@2 (byte*) screen#11 ← phi( main::@2/(byte*) screen#1 ) (byte*) screen#2 ← (byte*) screen#11 return to:@return (void()) print_msg((byte) print_msg::idx) print_msg: scope:[print_msg] from main main::@1 (byte*) screen#24 ← phi( main/(byte*) screen#17 main::@1/(byte*) screen#0 ) (byte) print_msg::idx#2 ← phi( main/(byte) print_msg::idx#0 main::@1/(byte) print_msg::idx#1 ) (byte*) print_msg::msg#0 ← (byte*) 0 (bool~) print_msg::$0 ← (byte) print_msg::idx#2 == (number) 1 if((bool~) print_msg::$0) goto print_msg::@1 to:print_msg::@3 print_msg::@1: scope:[print_msg] from print_msg (byte*) screen#21 ← phi( print_msg/(byte*) screen#24 ) (byte*) print_msg::msg#1 ← (const string) print_msg::$2 to:print_msg::@2 print_msg::@3: scope:[print_msg] from print_msg (byte*) screen#22 ← phi( print_msg/(byte*) screen#24 ) (byte*) print_msg::msg#2 ← (const string) print_msg::$3 to:print_msg::@2 print_msg::@2: scope:[print_msg] from print_msg::@1 print_msg::@3 (byte*) screen#18 ← phi( print_msg::@1/(byte*) screen#21 print_msg::@3/(byte*) screen#22 ) (byte*) print_msg::msg#3 ← phi( print_msg::@1/(byte*) print_msg::msg#1 print_msg::@3/(byte*) print_msg::msg#2 ) (byte*) print::msg#0 ← (byte*) print_msg::msg#3 call print to:print_msg::@5 print_msg::@5: scope:[print_msg] from print_msg::@2 (byte*) screen#12 ← phi( print_msg::@2/(byte*) screen#7 ) (byte*) screen#3 ← (byte*) screen#12 to:print_msg::@return print_msg::@return: scope:[print_msg] from print_msg::@5 (byte*) screen#13 ← phi( print_msg::@5/(byte*) screen#3 ) (byte*) screen#4 ← (byte*) screen#13 return to:@return @2: scope:[] from @begin (byte*) screen#5 ← ((byte*)) (number) $400 to:@3 (void()) print((byte*) print::msg) print: scope:[print] from print_msg::@2 (byte*) screen#23 ← phi( print_msg::@2/(byte*) screen#18 ) (byte*) print::msg#4 ← phi( print_msg::@2/(byte*) print::msg#0 ) to:print::@1 print::@1: scope:[print] from print print::@2 (byte*) screen#19 ← phi( print/(byte*) screen#23 print::@2/(byte*) screen#6 ) (byte*) print::msg#2 ← phi( print/(byte*) print::msg#4 print::@2/(byte*) print::msg#1 ) (bool~) print::$0 ← (number) 0 != *((byte*) print::msg#2) if((bool~) print::$0) goto print::@2 to:print::@return print::@2: scope:[print] from print::@1 (byte*) screen#14 ← phi( print::@1/(byte*) screen#19 ) (byte*) print::msg#3 ← phi( print::@1/(byte*) print::msg#2 ) *((byte*) screen#14) ← *((byte*) print::msg#3) (byte*) screen#6 ← ++ (byte*) screen#14 (byte*) print::msg#1 ← ++ (byte*) print::msg#3 to:print::@1 print::@return: scope:[print] from print::@1 (byte*) screen#15 ← phi( print::@1/(byte*) screen#19 ) (byte*) screen#7 ← (byte*) screen#15 return to:@return @3: scope:[] from @2 (byte*) screen#20 ← phi( @2/(byte*) screen#5 ) call main to:@4 @4: scope:[] from @3 (byte*) screen#16 ← phi( @3/(byte*) screen#2 ) (byte*) screen#8 ← (byte*) screen#16 to:@end @end: scope:[] from @4 SYMBOL TABLE SSA (label) @2 (label) @3 (label) @4 (label) @begin (label) @end (void()) main() (label) main::@1 (label) main::@2 (label) main::@return (void()) print((byte*) print::msg) (bool~) print::$0 (label) print::@1 (label) print::@2 (label) print::@return (byte*) print::msg (byte*) print::msg#0 (byte*) print::msg#1 (byte*) print::msg#2 (byte*) print::msg#3 (byte*) print::msg#4 (void()) print_msg((byte) print_msg::idx) (bool~) print_msg::$0 (const string) print_msg::$2 = (string) "Hello " (const string) print_msg::$3 = (string) "World!" (label) print_msg::@1 (label) print_msg::@2 (label) print_msg::@3 (label) print_msg::@5 (label) print_msg::@return (byte) print_msg::idx (byte) print_msg::idx#0 (byte) print_msg::idx#1 (byte) print_msg::idx#2 (byte*) print_msg::msg (byte*) print_msg::msg#0 (byte*) print_msg::msg#1 (byte*) print_msg::msg#2 (byte*) print_msg::msg#3 (byte*) screen (byte*) screen#0 (byte*) screen#1 (byte*) screen#10 (byte*) screen#11 (byte*) screen#12 (byte*) screen#13 (byte*) screen#14 (byte*) screen#15 (byte*) screen#16 (byte*) screen#17 (byte*) screen#18 (byte*) screen#19 (byte*) screen#2 (byte*) screen#20 (byte*) screen#21 (byte*) screen#22 (byte*) screen#23 (byte*) screen#24 (byte*) screen#3 (byte*) screen#4 (byte*) screen#5 (byte*) screen#6 (byte*) screen#7 (byte*) screen#8 (byte*) screen#9 Adding number conversion cast (unumber) 1 in (byte) print_msg::idx#0 ← (number) 1 Adding number conversion cast (unumber) 2 in (byte) print_msg::idx#1 ← (number) 2 Adding number conversion cast (unumber) 1 in (bool~) print_msg::$0 ← (byte) print_msg::idx#2 == (number) 1 Adding number conversion cast (unumber) 0 in (bool~) print::$0 ← (number) 0 != *((byte*) print::msg#2) Successful SSA optimization PassNAddNumberTypeConversions Inlining cast (byte) print_msg::idx#0 ← (unumber)(number) 1 Inlining cast (byte) print_msg::idx#1 ← (unumber)(number) 2 Inlining cast (byte*) screen#5 ← (byte*)(number) $400 Successful SSA optimization Pass2InlineCast Simplifying constant integer cast 1 Simplifying constant integer cast 2 Simplifying constant integer cast 1 Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 1 Finalized unsigned number type (byte) 2 Finalized unsigned number type (byte) 1 Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias (byte*) screen#0 = (byte*) screen#9 Alias (byte*) screen#1 = (byte*) screen#10 (byte*) screen#11 (byte*) screen#2 Alias (byte*) screen#21 = (byte*) screen#24 (byte*) screen#22 Alias (byte*) screen#12 = (byte*) screen#3 (byte*) screen#13 (byte*) screen#4 Alias (byte*) print::msg#2 = (byte*) print::msg#3 Alias (byte*) screen#14 = (byte*) screen#19 (byte*) screen#15 (byte*) screen#7 Alias (byte*) screen#20 = (byte*) screen#5 Alias (byte*) screen#16 = (byte*) screen#8 Successful SSA optimization Pass2AliasElimination Alias (byte*) screen#18 = (byte*) screen#21 Successful SSA optimization Pass2AliasElimination Identical Phi Values (byte*) screen#17 (byte*) screen#20 Identical Phi Values (byte*) screen#0 (byte*) screen#12 Identical Phi Values (byte*) screen#1 (byte*) screen#12 Identical Phi Values (byte*) screen#12 (byte*) screen#14 Identical Phi Values (byte*) print::msg#4 (byte*) print::msg#0 Identical Phi Values (byte*) screen#23 (byte*) screen#18 Identical Phi Values (byte*) screen#16 (byte*) screen#1 Successful SSA optimization Pass2IdenticalPhiElimination Simple Condition (bool~) print_msg::$0 [15] if((byte) print_msg::idx#2==(byte) 1) goto print_msg::@1 Simple Condition (bool~) print::$0 [32] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 Successful SSA optimization Pass2ConditionalJumpSimplification Constant (const byte) print_msg::idx#0 = 1 Constant (const byte) print_msg::idx#1 = 2 Constant (const byte*) print_msg::msg#0 = (byte*) 0 Constant (const byte*) print_msg::msg#1 = print_msg::$2 Constant (const byte*) print_msg::msg#2 = print_msg::$3 Constant (const byte*) screen#20 = (byte*) 1024 Successful SSA optimization Pass2ConstantIdentification Eliminating unused constant (const byte*) print_msg::msg#0 Successful SSA optimization PassNEliminateUnusedVars Inlining constant with var siblings (const byte) print_msg::idx#0 Inlining constant with var siblings (const byte) print_msg::idx#1 Inlining constant with var siblings (const byte*) print_msg::msg#1 Inlining constant with var siblings (const byte*) print_msg::msg#2 Inlining constant with var siblings (const byte*) screen#20 Constant inlined print_msg::idx#1 = (byte) 2 Constant inlined print_msg::idx#0 = (byte) 1 Constant inlined screen#20 = (byte*) 1024 Constant inlined print_msg::$3 = (const byte*) print_msg::msg#2 Constant inlined print_msg::$2 = (const byte*) print_msg::msg#1 Successful SSA optimization Pass2ConstantInlining Inlining constant with var siblings (const byte*) print_msg::msg#1 Inlining constant with var siblings (const byte*) print_msg::msg#2 Inlining constant with var siblings (const byte*) print_msg::msg#1 Inlining constant with var siblings (const byte*) print_msg::msg#2 Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 Adding NOP phi() at start of @4 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::@2 Adding NOP phi() at start of print_msg::@3 Adding NOP phi() at start of print_msg::@5 Adding NOP phi() at start of print_msg::@1 CALL GRAPH Calls in [] to main:3 Calls in [main] to print_msg:7 print_msg:9 Calls in [print_msg] to print:17 Created 5 initial phi equivalence classes Coalesced [8] screen#25 ← screen#14 Coalesced [21] print::msg#5 ← print::msg#0 Coalesced (already) [22] screen#26 ← screen#18 Coalesced [29] print::msg#6 ← print::msg#1 Coalesced [30] screen#27 ← screen#6 Coalesced down to 4 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) @4 Culled Empty Block (label) main::@2 Culled Empty Block (label) print_msg::@3 Culled Empty Block (label) print_msg::@5 Renumbering block @3 to @1 Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::@1 Adding NOP phi() at start of print_msg::@1 Adding NOP phi() at start of print FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] phi() to:@1 @1: scope:[] from @begin [1] phi() [2] call main to:@end @end: scope:[] from @1 [3] phi() (void()) main() main: scope:[main] from @1 [4] phi() [5] call print_msg to:main::@1 main::@1: scope:[main] from main [6] phi() [7] call print_msg to:main::@return main::@return: scope:[main] from main::@1 [8] return to:@return (void()) print_msg((byte) print_msg::idx) print_msg: scope:[print_msg] from main main::@1 [9] (byte*) screen#18 ← phi( main/(byte*) 1024 main::@1/(byte*) screen#14 ) [9] (byte) print_msg::idx#2 ← phi( main/(byte) 1 main::@1/(byte) 2 ) [10] if((byte) print_msg::idx#2==(byte) 1) goto print_msg::@1 to:print_msg::@2 print_msg::@1: scope:[print_msg] from print_msg [11] phi() to:print_msg::@2 print_msg::@2: scope:[print_msg] from print_msg print_msg::@1 [12] (byte*) print_msg::msg#3 ← phi( print_msg::@1/(const byte*) print_msg::msg#1 print_msg/(const byte*) print_msg::msg#2 ) [13] (byte*) print::msg#0 ← (byte*) print_msg::msg#3 [14] call print to:print_msg::@return print_msg::@return: scope:[print_msg] from print_msg::@2 [15] return to:@return (void()) print((byte*) print::msg) print: scope:[print] from print_msg::@2 [16] phi() to:print::@1 print::@1: scope:[print] from print print::@2 [17] (byte*) screen#14 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#6 ) [17] (byte*) print::msg#2 ← phi( print/(byte*) print::msg#0 print::@2/(byte*) print::msg#1 ) [18] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 to:print::@return print::@return: scope:[print] from print::@1 [19] return to:@return print::@2: scope:[print] from print::@1 [20] *((byte*) screen#14) ← *((byte*) print::msg#2) [21] (byte*) screen#6 ← ++ (byte*) screen#14 [22] (byte*) print::msg#1 ← ++ (byte*) print::msg#2 to:print::@1 VARIABLE REGISTER WEIGHTS (void()) main() (void()) print((byte*) print::msg) (byte*) print::msg (byte*) print::msg#0 2.0 (byte*) print::msg#1 22.0 (byte*) print::msg#2 11.5 (void()) print_msg((byte) print_msg::idx) (byte) print_msg::idx (byte) print_msg::idx#2 2.0 (byte*) print_msg::msg (byte*) print_msg::msg#3 2.0 (byte*) screen (byte*) screen#14 4.625 (byte*) screen#18 0.6666666666666666 (byte*) screen#6 11.0 Initial phi equivalence classes [ print_msg::idx#2 ] [ screen#18 screen#14 screen#6 ] [ print_msg::msg#3 ] [ print::msg#2 print::msg#0 print::msg#1 ] Complete equivalence classes [ print_msg::idx#2 ] [ screen#18 screen#14 screen#6 ] [ print_msg::msg#3 ] [ print::msg#2 print::msg#0 print::msg#1 ] Allocated zp[1]:2 [ print_msg::idx#2 ] Allocated zp[2]:3 [ screen#18 screen#14 screen#6 ] Allocated zp[2]:5 [ print_msg::msg#3 ] Allocated zp[2]:7 [ print::msg#2 print::msg#0 print::msg#1 ] INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Inline Strings in assignments // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label screen = 3 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main // [4] phi from @1 to main [phi:@1->main] main_from___b1: jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { // [5] call print_msg // [9] phi from main to print_msg [phi:main->print_msg] print_msg_from_main: // [9] phi (byte*) screen#18 = (byte*) 1024 [phi:main->print_msg#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 // [9] phi (byte) print_msg::idx#2 = (byte) 1 [phi:main->print_msg#1] -- vbuz1=vbuc1 lda #1 sta.z print_msg.idx jsr print_msg // [6] phi from main to main::@1 [phi:main->main::@1] __b1_from_main: jmp __b1 // main::@1 __b1: // [7] call print_msg // [9] phi from main::@1 to print_msg [phi:main::@1->print_msg] print_msg_from___b1: // [9] phi (byte*) screen#18 = (byte*) screen#14 [phi:main::@1->print_msg#0] -- register_copy // [9] phi (byte) print_msg::idx#2 = (byte) 2 [phi:main::@1->print_msg#1] -- vbuz1=vbuc1 lda #2 sta.z print_msg.idx jsr print_msg jmp __breturn // main::@return __breturn: // [8] return rts } // print_msg // print_msg(byte zeropage(2) idx) print_msg: { .label idx = 2 .label msg = 5 // [10] if((byte) print_msg::idx#2==(byte) 1) goto print_msg::@1 -- vbuz1_eq_vbuc1_then_la1 lda #1 cmp.z idx beq __b1_from_print_msg // [12] phi from print_msg to print_msg::@2 [phi:print_msg->print_msg::@2] __b2_from_print_msg: // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#2 [phi:print_msg->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_2 sta.z msg+1 jmp __b2 // [11] phi from print_msg to print_msg::@1 [phi:print_msg->print_msg::@1] __b1_from_print_msg: jmp __b1 // print_msg::@1 __b1: // [12] phi from print_msg::@1 to print_msg::@2 [phi:print_msg::@1->print_msg::@2] __b2_from___b1: // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#1 [phi:print_msg::@1->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_1 sta.z msg+1 jmp __b2 // print_msg::@2 __b2: // [13] (byte*) print::msg#0 ← (byte*) print_msg::msg#3 -- pbuz1=pbuz2 lda.z msg sta.z print.msg lda.z msg+1 sta.z print.msg+1 // [14] call print // [16] phi from print_msg::@2 to print [phi:print_msg::@2->print] print_from___b2: jsr print jmp __breturn // print_msg::@return __breturn: // [15] return rts msg_1: .text "Hello " .byte 0 msg_2: .text "World!" .byte 0 } // print // print(byte* zeropage(7) msg) print: { .label msg = 7 // [17] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] __b1_from_print: __b1_from___b2: // [17] phi (byte*) screen#14 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy // [17] phi (byte*) print::msg#2 = (byte*) print::msg#0 [phi:print/print::@2->print::@1#1] -- register_copy jmp __b1 // print::@1 __b1: // [18] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (msg),y cmp #0 bne __b2 jmp __breturn // print::@return __breturn: // [19] return rts // print::@2 __b2: // [20] *((byte*) screen#14) ← *((byte*) print::msg#2) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (msg),y ldy #0 sta (screen),y // [21] (byte*) screen#6 ← ++ (byte*) screen#14 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // [22] (byte*) print::msg#1 ← ++ (byte*) print::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: jmp __b1_from___b2 } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [13] (byte*) print::msg#0 ← (byte*) print_msg::msg#3 [ screen#18 print::msg#0 ] ( main:2::print_msg:5 [ screen#18 print::msg#0 ] main:2::print_msg:7 [ screen#18 print::msg#0 ] ) always clobbers reg byte a Statement [18] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 [ screen#14 print::msg#2 ] ( main:2::print_msg:5::print:14 [ screen#14 print::msg#2 ] main:2::print_msg:7::print:14 [ screen#14 print::msg#2 ] ) always clobbers reg byte a reg byte y Statement [20] *((byte*) screen#14) ← *((byte*) print::msg#2) [ screen#14 print::msg#2 ] ( main:2::print_msg:5::print:14 [ screen#14 print::msg#2 ] main:2::print_msg:7::print:14 [ screen#14 print::msg#2 ] ) always clobbers reg byte a reg byte y Potential registers zp[1]:2 [ print_msg::idx#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , Potential registers zp[2]:3 [ screen#18 screen#14 screen#6 ] : zp[2]:3 , Potential registers zp[2]:5 [ print_msg::msg#3 ] : zp[2]:5 , Potential registers zp[2]:7 [ print::msg#2 print::msg#0 print::msg#1 ] : zp[2]:7 , REGISTER UPLIFT SCOPES Uplift Scope [print] 35.5: zp[2]:7 [ print::msg#2 print::msg#0 print::msg#1 ] Uplift Scope [] 16.29: zp[2]:3 [ screen#18 screen#14 screen#6 ] Uplift Scope [print_msg] 2: zp[1]:2 [ print_msg::idx#2 ] 2: zp[2]:5 [ print_msg::msg#3 ] Uplift Scope [main] Uplifting [print] best 740 combination zp[2]:7 [ print::msg#2 print::msg#0 print::msg#1 ] Uplifting [] best 740 combination zp[2]:3 [ screen#18 screen#14 screen#6 ] Uplifting [print_msg] best 731 combination reg byte x [ print_msg::idx#2 ] zp[2]:5 [ print_msg::msg#3 ] Uplifting [main] best 731 combination Coalescing zero page register [ zp[2]:5 [ print_msg::msg#3 ] ] with [ zp[2]:7 [ print::msg#2 print::msg#0 print::msg#1 ] ] - score: 1 Allocated (was zp[2]:3) zp[2]:2 [ screen#18 screen#14 screen#6 ] Allocated (was zp[2]:5) zp[2]:4 [ print_msg::msg#3 print::msg#2 print::msg#0 print::msg#1 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments // Inline Strings in assignments // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label screen = 2 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main // [4] phi from @1 to main [phi:@1->main] main_from___b1: jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { // [5] call print_msg // [9] phi from main to print_msg [phi:main->print_msg] print_msg_from_main: // [9] phi (byte*) screen#18 = (byte*) 1024 [phi:main->print_msg#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 // [9] phi (byte) print_msg::idx#2 = (byte) 1 [phi:main->print_msg#1] -- vbuxx=vbuc1 ldx #1 jsr print_msg // [6] phi from main to main::@1 [phi:main->main::@1] __b1_from_main: jmp __b1 // main::@1 __b1: // [7] call print_msg // [9] phi from main::@1 to print_msg [phi:main::@1->print_msg] print_msg_from___b1: // [9] phi (byte*) screen#18 = (byte*) screen#14 [phi:main::@1->print_msg#0] -- register_copy // [9] phi (byte) print_msg::idx#2 = (byte) 2 [phi:main::@1->print_msg#1] -- vbuxx=vbuc1 ldx #2 jsr print_msg jmp __breturn // main::@return __breturn: // [8] return rts } // print_msg // print_msg(byte register(X) idx) print_msg: { .label msg = 4 // [10] if((byte) print_msg::idx#2==(byte) 1) goto print_msg::@1 -- vbuxx_eq_vbuc1_then_la1 cpx #1 beq __b1_from_print_msg // [12] phi from print_msg to print_msg::@2 [phi:print_msg->print_msg::@2] __b2_from_print_msg: // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#2 [phi:print_msg->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_2 sta.z msg+1 jmp __b2 // [11] phi from print_msg to print_msg::@1 [phi:print_msg->print_msg::@1] __b1_from_print_msg: jmp __b1 // print_msg::@1 __b1: // [12] phi from print_msg::@1 to print_msg::@2 [phi:print_msg::@1->print_msg::@2] __b2_from___b1: // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#1 [phi:print_msg::@1->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_1 sta.z msg+1 jmp __b2 // print_msg::@2 __b2: // [13] (byte*) print::msg#0 ← (byte*) print_msg::msg#3 // [14] call print // [16] phi from print_msg::@2 to print [phi:print_msg::@2->print] print_from___b2: jsr print jmp __breturn // print_msg::@return __breturn: // [15] return rts msg_1: .text "Hello " .byte 0 msg_2: .text "World!" .byte 0 } // print // print(byte* zeropage(4) msg) print: { .label msg = 4 // [17] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] __b1_from_print: __b1_from___b2: // [17] phi (byte*) screen#14 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy // [17] phi (byte*) print::msg#2 = (byte*) print::msg#0 [phi:print/print::@2->print::@1#1] -- register_copy jmp __b1 // print::@1 __b1: // [18] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (msg),y cmp #0 bne __b2 jmp __breturn // print::@return __breturn: // [19] return rts // print::@2 __b2: // [20] *((byte*) screen#14) ← *((byte*) print::msg#2) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (msg),y ldy #0 sta (screen),y // [21] (byte*) screen#6 ← ++ (byte*) screen#14 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // [22] (byte*) print::msg#1 ← ++ (byte*) print::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: jmp __b1_from___b2 } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction ldy #0 Succesful ASM optimization Pass5UnnecesaryLoadElimination Replacing label __bbegin with __b1 Replacing label __b1_from_print_msg with __b1 Replacing label __b1_from___b2 with __b1 Removing instruction __bbegin: Removing instruction __b1_from___bbegin: Removing instruction main_from___b1: Removing instruction __bend_from___b1: Removing instruction __b1_from_main: Removing instruction print_msg_from___b1: Removing instruction __b1_from_print_msg: Removing instruction __b2_from___b1: Removing instruction print_from___b2: Removing instruction __b1_from_print: Removing instruction __b1_from___b2: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __bend: Removing instruction print_msg_from_main: Removing instruction __b1: Removing instruction __breturn: Removing instruction __b2_from_print_msg: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly Removing instruction jsr main Succesful ASM optimization Pass5SkipBegin Removing instruction __b1: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (void()) main() (label) main::@1 (label) main::@return (void()) print((byte*) print::msg) (label) print::@1 (label) print::@2 (label) print::@return (byte*) print::msg (byte*) print::msg#0 msg zp[2]:4 2.0 (byte*) print::msg#1 msg zp[2]:4 22.0 (byte*) print::msg#2 msg zp[2]:4 11.5 (void()) print_msg((byte) print_msg::idx) (label) print_msg::@1 (label) print_msg::@2 (label) print_msg::@return (byte) print_msg::idx (byte) print_msg::idx#2 reg byte x 2.0 (byte*) print_msg::msg (const byte*) print_msg::msg#1 msg_1 = (string) "Hello " (const byte*) print_msg::msg#2 msg_2 = (string) "World!" (byte*) print_msg::msg#3 msg zp[2]:4 2.0 (byte*) screen (byte*) screen#14 screen zp[2]:2 4.625 (byte*) screen#18 screen zp[2]:2 0.6666666666666666 (byte*) screen#6 screen zp[2]:2 11.0 reg byte x [ print_msg::idx#2 ] zp[2]:2 [ screen#18 screen#14 screen#6 ] zp[2]:4 [ print_msg::msg#3 print::msg#2 print::msg#0 print::msg#1 ] FINAL ASSEMBLER Score: 612 // File Comments // Inline Strings in assignments // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .label screen = 2 // @begin // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main // [4] phi from @1 to main [phi:@1->main] // [3] phi from @1 to @end [phi:@1->@end] // @end // main main: { // print_msg(1) // [5] call print_msg // [9] phi from main to print_msg [phi:main->print_msg] // [9] phi (byte*) screen#18 = (byte*) 1024 [phi:main->print_msg#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 // [9] phi (byte) print_msg::idx#2 = (byte) 1 [phi:main->print_msg#1] -- vbuxx=vbuc1 ldx #1 jsr print_msg // [6] phi from main to main::@1 [phi:main->main::@1] // main::@1 // print_msg(2) // [7] call print_msg // [9] phi from main::@1 to print_msg [phi:main::@1->print_msg] // [9] phi (byte*) screen#18 = (byte*) screen#14 [phi:main::@1->print_msg#0] -- register_copy // [9] phi (byte) print_msg::idx#2 = (byte) 2 [phi:main::@1->print_msg#1] -- vbuxx=vbuc1 ldx #2 jsr print_msg // main::@return // } // [8] return rts } // print_msg // print_msg(byte register(X) idx) print_msg: { .label msg = 4 // if(idx==1) // [10] if((byte) print_msg::idx#2==(byte) 1) goto print_msg::@1 -- vbuxx_eq_vbuc1_then_la1 cpx #1 beq __b1 // [12] phi from print_msg to print_msg::@2 [phi:print_msg->print_msg::@2] // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#2 [phi:print_msg->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_2 sta.z msg+1 jmp __b2 // [11] phi from print_msg to print_msg::@1 [phi:print_msg->print_msg::@1] // print_msg::@1 __b1: // [12] phi from print_msg::@1 to print_msg::@2 [phi:print_msg::@1->print_msg::@2] // [12] phi (byte*) print_msg::msg#3 = (const byte*) print_msg::msg#1 [phi:print_msg::@1->print_msg::@2#0] -- pbuz1=pbuc1 lda #msg_1 sta.z msg+1 // print_msg::@2 __b2: // print(msg) // [13] (byte*) print::msg#0 ← (byte*) print_msg::msg#3 // [14] call print // [16] phi from print_msg::@2 to print [phi:print_msg::@2->print] jsr print // print_msg::@return // } // [15] return rts msg_1: .text "Hello " .byte 0 msg_2: .text "World!" .byte 0 } // print // print(byte* zeropage(4) msg) print: { .label msg = 4 // [17] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] // [17] phi (byte*) screen#14 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy // [17] phi (byte*) print::msg#2 = (byte*) print::msg#0 [phi:print/print::@2->print::@1#1] -- register_copy // print::@1 __b1: // while(*msg) // [18] if((byte) 0!=*((byte*) print::msg#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (msg),y cmp #0 bne __b2 // print::@return // } // [19] return rts // print::@2 __b2: // *(screen++) = *(msg++) // [20] *((byte*) screen#14) ← *((byte*) print::msg#2) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (msg),y sta (screen),y // *(screen++) = *(msg++); // [21] (byte*) screen#6 ← ++ (byte*) screen#14 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // [22] (byte*) print::msg#1 ← ++ (byte*) print::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: jmp __b1 } // File Data