Warning! Adding boolean cast to non-boolean sub-expression (number) 0 Warning! Adding boolean cast to non-boolean sub-expression (number) $3e7 Warning! Adding boolean cast to non-boolean sub-expression (byte) main::i Warning! Adding boolean cast to non-boolean sub-expression (word) main::i1 Culled Empty Block (label) main::@12 CONTROL FLOW GRAPH SSA @begin: scope:[] from (byte*) SCREEN#0 ← ((byte*)) (number) $400 to:@1 main: scope:[main] from @1 (byte) main::idx#0 ← (number) 0 (bool~) main::$0 ← ! (number) 0!=(number) 0 if((bool~) main::$0) goto main::@1 to:main::@3 main::@1: scope:[main] from main main::@3 (byte) main::idx#13 ← phi( main/(byte) main::idx#0 main::@3/(byte) main::idx#1 ) (bool~) main::$1 ← ! (number) 0!=(number) $3e7 if((bool~) main::$1) goto main::@2 to:main::@4 main::@3: scope:[main] from main (byte) main::idx#7 ← phi( main/(byte) main::idx#0 ) *((byte*) SCREEN#0 + (byte) main::idx#7) ← (byte) '0' (byte) main::idx#1 ← ++ (byte) main::idx#7 to:main::@1 main::@2: scope:[main] from main::@1 main::@4 (byte) main::idx#8 ← phi( main::@1/(byte) main::idx#13 main::@4/(byte) main::idx#3 ) *((byte*) SCREEN#0 + (byte) main::idx#8) ← (byte) ' ' (byte) main::idx#2 ← ++ (byte) main::idx#8 (byte) main::i#0 ← (byte) 0 to:main::@5 main::@4: scope:[main] from main::@1 (byte) main::idx#9 ← phi( main::@1/(byte) main::idx#13 ) *((byte*) SCREEN#0 + (byte) main::idx#9) ← (byte) '+' (byte) main::idx#3 ← ++ (byte) main::idx#9 to:main::@2 main::@5: scope:[main] from main::@2 main::@6 (byte) main::idx#14 ← phi( main::@2/(byte) main::idx#2 main::@6/(byte) main::idx#15 ) (byte) main::i#2 ← phi( main::@2/(byte) main::i#0 main::@6/(byte) main::i#1 ) (bool~) main::$6 ← (number) 0 != (byte) main::i#2 (bool~) main::$2 ← ! (bool~) main::$6 if((bool~) main::$2) goto main::@6 to:main::@7 main::@6: scope:[main] from main::@5 main::@7 (byte) main::idx#15 ← phi( main::@5/(byte) main::idx#14 main::@7/(byte) main::idx#4 ) (byte) main::i#3 ← phi( main::@5/(byte) main::i#2 main::@7/(byte) main::i#4 ) (byte) main::i#1 ← (byte) main::i#3 + rangenext(0,2) (bool~) main::$3 ← (byte) main::i#1 != rangelast(0,2) if((bool~) main::$3) goto main::@5 to:main::@8 main::@7: scope:[main] from main::@5 (byte) main::i#4 ← phi( main::@5/(byte) main::i#2 ) (byte) main::idx#10 ← phi( main::@5/(byte) main::idx#14 ) *((byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' (byte) main::idx#4 ← ++ (byte) main::idx#10 to:main::@6 main::@8: scope:[main] from main::@6 (byte) main::idx#11 ← phi( main::@6/(byte) main::idx#15 ) *((byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' (byte) main::idx#5 ← ++ (byte) main::idx#11 (word) main::i1#0 ← (word) 0 to:main::@9 main::@9: scope:[main] from main::@10 main::@8 (byte) main::idx#16 ← phi( main::@10/(byte) main::idx#17 main::@8/(byte) main::idx#5 ) (word) main::i1#2 ← phi( main::@10/(word) main::i1#1 main::@8/(word) main::i1#0 ) (bool~) main::$7 ← (number) 0 != (word) main::i1#2 (bool~) main::$4 ← ! (bool~) main::$7 if((bool~) main::$4) goto main::@10 to:main::@11 main::@10: scope:[main] from main::@11 main::@9 (byte) main::idx#17 ← phi( main::@11/(byte) main::idx#6 main::@9/(byte) main::idx#16 ) (word) main::i1#3 ← phi( main::@11/(word) main::i1#4 main::@9/(word) main::i1#2 ) (word) main::i1#1 ← (word) main::i1#3 + rangenext(0,2) (bool~) main::$5 ← (word) main::i1#1 != rangelast(0,2) if((bool~) main::$5) goto main::@9 to:main::@return main::@11: scope:[main] from main::@9 (word) main::i1#4 ← phi( main::@9/(word) main::i1#2 ) (byte) main::idx#12 ← phi( main::@9/(byte) main::idx#16 ) *((byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' (byte) main::idx#6 ← ++ (byte) main::idx#12 to:main::@10 main::@return: scope:[main] from main::@10 return to:@return @1: scope:[] from @begin call main to:@2 @2: scope:[] from @1 to:@end @end: scope:[] from @2 SYMBOL TABLE SSA (label) @1 (label) @2 (label) @begin (label) @end (byte*) SCREEN (byte*) SCREEN#0 (void()) main() (bool~) main::$0 (bool~) main::$1 (bool~) main::$2 (bool~) main::$3 (bool~) main::$4 (bool~) main::$5 (bool~) main::$6 (bool~) main::$7 (label) main::@1 (label) main::@10 (label) main::@11 (label) main::@2 (label) main::@3 (label) main::@4 (label) main::@5 (label) main::@6 (label) main::@7 (label) main::@8 (label) main::@9 (label) main::@return (byte) main::i (byte) main::i#0 (byte) main::i#1 (byte) main::i#2 (byte) main::i#3 (byte) main::i#4 (word) main::i1 (word) main::i1#0 (word) main::i1#1 (word) main::i1#2 (word) main::i1#3 (word) main::i1#4 (byte) main::idx (byte) main::idx#0 (byte) main::idx#1 (byte) main::idx#10 (byte) main::idx#11 (byte) main::idx#12 (byte) main::idx#13 (byte) main::idx#14 (byte) main::idx#15 (byte) main::idx#16 (byte) main::idx#17 (byte) main::idx#2 (byte) main::idx#3 (byte) main::idx#4 (byte) main::idx#5 (byte) main::idx#6 (byte) main::idx#7 (byte) main::idx#8 (byte) main::idx#9 Adding number conversion cast (unumber) 0 in (byte) main::idx#0 ← (number) 0 Adding number conversion cast (unumber) 0 in (bool~) main::$6 ← (number) 0 != (byte) main::i#2 Adding number conversion cast (unumber) 0 in (bool~) main::$7 ← (number) 0 != (word) main::i1#2 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400 Inlining cast (byte) main::idx#0 ← (unumber)(number) 0 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 Simplifying constant integer cast 0 Simplifying constant integer cast 0 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions Inversing boolean not [19] (bool~) main::$2 ← (byte) 0 == (byte) main::i#2 from [18] (bool~) main::$6 ← (byte) 0 != (byte) main::i#2 Inversing boolean not [34] (bool~) main::$4 ← (byte) 0 == (word) main::i1#2 from [33] (bool~) main::$7 ← (byte) 0 != (word) main::i1#2 Successful SSA optimization Pass2UnaryNotSimplification Alias (byte) main::idx#0 = (byte) main::idx#7 Alias (byte) main::idx#13 = (byte) main::idx#9 Alias (byte) main::idx#10 = (byte) main::idx#14 Alias (byte) main::i#2 = (byte) main::i#4 Alias (byte) main::idx#11 = (byte) main::idx#15 Alias (byte) main::idx#12 = (byte) main::idx#16 Alias (word) main::i1#2 = (word) main::i1#4 Successful SSA optimization Pass2AliasElimination Alias (byte) main::i#2 = (byte) main::i#3 Alias (word) main::i1#2 = (word) main::i1#3 Successful SSA optimization Pass2AliasElimination Simple Condition (bool~) main::$2 [20] if((byte) 0==(byte) main::i#2) goto main::@6 Simple Condition (bool~) main::$3 [24] if((byte) main::i#1!=rangelast(0,2)) goto main::@5 Simple Condition (bool~) main::$4 [35] if((byte) 0==(word) main::i1#2) goto main::@10 Simple Condition (bool~) main::$5 [39] if((word) main::i1#1!=rangelast(0,2)) goto main::@9 Successful SSA optimization Pass2ConditionalJumpSimplification Rewriting ! if()-condition to reversed if() [2] (bool~) main::$0 ← ! (number) 0!=(number) 0 Rewriting ! if()-condition to reversed if() [5] (bool~) main::$1 ← ! (number) 0!=(number) $3e7 Successful SSA optimization Pass2ConditionalAndOrRewriting Constant (const byte*) SCREEN#0 = (byte*) 1024 Constant (const byte) main::idx#0 = 0 Constant (const byte) main::i#0 = 0 Constant (const word) main::i1#0 = 0 Successful SSA optimization Pass2ConstantIdentification if() condition always false - eliminating [3] if((number) 0!=(number) 0) goto main::@3 Removing PHI-reference to removed block (main::@1) in block main::@2 if() condition always true - replacing block destination [6] if((number) 0!=(number) $3e7) goto main::@4 Successful SSA optimization Pass2ConstantIfs Resolved ranged next value [22] main::i#1 ← ++ main::i#2 to ++ Resolved ranged comparison value [24] if(main::i#1!=rangelast(0,2)) goto main::@5 to (number) 3 Resolved ranged next value [37] main::i1#1 ← ++ main::i1#2 to ++ Resolved ranged comparison value [39] if(main::i1#1!=rangelast(0,2)) goto main::@9 to (number) 3 Simplifying expression containing zero SCREEN#0 in [8] *((const byte*) SCREEN#0 + (const byte) main::idx#0) ← (byte) '0' Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating variable (byte) main::idx#1 from unused block main::@3 Removing PHI-reference to removed block (main::@3) in block main::@1 Removing unused block main::@3 Successful SSA optimization Pass2EliminateUnusedBlocks Adding number conversion cast (unumber) 3 in if((byte) main::i#1!=(number) 3) goto main::@5 Adding number conversion cast (unumber) 3 in if((word) main::i1#1!=(number) 3) goto main::@9 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast 3 Simplifying constant integer cast 3 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 3 Finalized unsigned number type (byte) 3 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias (byte) main::idx#3 = (byte) main::idx#8 Successful SSA optimization Pass2AliasElimination Identical Phi Values (byte) main::idx#13 (const byte) main::idx#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant right-side identified [5] (byte) main::idx#3 ← ++ (const byte) main::idx#0 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::idx#3 = ++main::idx#0 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN#0 in [4] *((const byte*) SCREEN#0 + (const byte) main::idx#0) ← (byte) '+' Successful SSA optimization PassNSimplifyExpressionWithZero Constant right-side identified [1] (byte) main::idx#2 ← ++ (const byte) main::idx#3 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::idx#2 = ++main::idx#3 Successful SSA optimization Pass2ConstantIdentification Inlining constant with var siblings (const byte) main::idx#0 Inlining constant with var siblings (const byte) main::i#0 Inlining constant with var siblings (const word) main::i1#0 Inlining constant with var siblings (const byte) main::idx#3 Inlining constant with var siblings (const byte) main::idx#2 Constant inlined main::i#0 = (byte) 0 Constant inlined main::i1#0 = (word) 0 Constant inlined main::idx#0 = (byte) 0 Constant inlined main::idx#2 = ++++(byte) 0 Constant inlined main::idx#3 = ++(byte) 0 Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN#0+++0) Successful SSA optimization Pass2ConstantAdditionElimination Simplifying constant integer increment ++0 Simplifying constant integer increment ++0 Successful SSA optimization Pass2ConstantSimplification Simplifying constant integer increment ++1 Successful SSA optimization Pass2ConstantSimplification Added new block during phi lifting main::@13(between main::@6 and main::@5) Added new block during phi lifting main::@14(between main::@5 and main::@6) Added new block during phi lifting main::@15(between main::@10 and main::@9) Added new block during phi lifting main::@16(between main::@9 and main::@10) Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @2 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::@1 CALL GRAPH Calls in [] to main:2 Created 6 initial phi equivalence classes Coalesced [13] main::idx#20 ← main::idx#4 Coalesced [19] main::idx#22 ← main::idx#5 Coalesced [24] main::idx#23 ← main::idx#6 Coalesced [29] main::i1#5 ← main::i1#1 Coalesced [30] main::idx#21 ← main::idx#17 Coalesced (already) [31] main::idx#24 ← main::idx#12 Coalesced [32] main::i#5 ← main::i#1 Coalesced [33] main::idx#18 ← main::idx#11 Coalesced (already) [34] main::idx#19 ← main::idx#10 Coalesced down to 4 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) main::@1 Culled Empty Block (label) main::@15 Culled Empty Block (label) main::@16 Culled Empty Block (label) main::@13 Culled Empty Block (label) main::@14 Renumbering block main::@2 to main::@1 Renumbering block main::@4 to main::@2 Renumbering block main::@5 to main::@3 Renumbering block main::@6 to main::@4 Renumbering block main::@7 to main::@5 Renumbering block main::@8 to main::@6 Renumbering block main::@9 to main::@7 Renumbering block main::@10 to main::@8 Renumbering block main::@11 to main::@9 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 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() main: scope:[main] from @1 [4] phi() to:main::@2 main::@2: scope:[main] from main [5] *((const byte*) SCREEN#0) ← (byte) '+' to:main::@1 main::@1: scope:[main] from main::@2 [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' to:main::@3 main::@3: scope:[main] from main::@1 main::@4 [7] (byte) main::idx#10 ← phi( main::@1/(byte) 2 main::@4/(byte) main::idx#11 ) [7] (byte) main::i#2 ← phi( main::@1/(byte) 0 main::@4/(byte) main::i#1 ) [8] if((byte) 0==(byte) main::i#2) goto main::@4 to:main::@5 main::@5: scope:[main] from main::@3 [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' [10] (byte) main::idx#4 ← ++ (byte) main::idx#10 to:main::@4 main::@4: scope:[main] from main::@3 main::@5 [11] (byte) main::idx#11 ← phi( main::@3/(byte) main::idx#10 main::@5/(byte) main::idx#4 ) [12] (byte) main::i#1 ← ++ (byte) main::i#2 [13] if((byte) main::i#1!=(byte) 3) goto main::@3 to:main::@6 main::@6: scope:[main] from main::@4 [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' [15] (byte) main::idx#5 ← ++ (byte) main::idx#11 to:main::@7 main::@7: scope:[main] from main::@6 main::@8 [16] (byte) main::idx#12 ← phi( main::@8/(byte) main::idx#17 main::@6/(byte) main::idx#5 ) [16] (word) main::i1#2 ← phi( main::@8/(word) main::i1#1 main::@6/(word) 0 ) [17] if((byte) 0==(word) main::i1#2) goto main::@8 to:main::@9 main::@9: scope:[main] from main::@7 [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' [19] (byte) main::idx#6 ← ++ (byte) main::idx#12 to:main::@8 main::@8: scope:[main] from main::@7 main::@9 [20] (byte) main::idx#17 ← phi( main::@9/(byte) main::idx#6 main::@7/(byte) main::idx#12 ) [21] (word) main::i1#1 ← ++ (word) main::i1#2 [22] if((word) main::i1#1!=(byte) 3) goto main::@7 to:main::@return main::@return: scope:[main] from main::@8 [23] return to:@return VARIABLE REGISTER WEIGHTS (byte*) SCREEN (void()) main() (byte) main::i (byte) main::i#1 16.5 (byte) main::i#2 6.6000000000000005 (word) main::i1 (word) main::i1#1 16.5 (word) main::i1#2 6.6000000000000005 (byte) main::idx (byte) main::idx#10 14.666666666666666 (byte) main::idx#11 9.25 (byte) main::idx#12 15.333333333333332 (byte) main::idx#17 11.0 (byte) main::idx#4 22.0 (byte) main::idx#5 4.0 (byte) main::idx#6 22.0 Initial phi equivalence classes [ main::i#2 main::i#1 ] [ main::idx#10 main::idx#11 main::idx#4 ] [ main::i1#2 main::i1#1 ] [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] Complete equivalence classes [ main::i#2 main::i#1 ] [ main::idx#10 main::idx#11 main::idx#4 ] [ main::i1#2 main::i1#1 ] [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] Allocated zp ZP_BYTE:3 [ main::idx#10 main::idx#11 main::idx#4 ] Allocated zp ZP_WORD:4 [ main::i1#2 main::i1#1 ] Allocated zp ZP_BYTE:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Tests using integer conditions in if() // This should produce '+ ++ ++' at the top of the screen // Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 // @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: { .label i = 2 .label idx = 3 .label idx_5 = 6 .label i1 = 4 .label idx_6 = 6 .label idx_12 = 6 .label idx_17 = 6 jmp b2 // main::@2 b2: // [5] *((const byte*) SCREEN#0) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN jmp b1 // main::@1 b1: // [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [7] phi from main::@1 to main::@3 [phi:main::@1->main::@3] b3_from_b1: // [7] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuz1=vbuc1 lda #2 sta.z idx // [7] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuz1=vbuc1 lda #0 sta.z i jmp b3 // loop byte // [7] phi from main::@4 to main::@3 [phi:main::@4->main::@3] b3_from_b4: // [7] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy jmp b3 // main::@3 b3: // [8] if((byte) 0==(byte) main::i#2) goto main::@4 -- vbuc1_eq_vbuz1_then_la1 lda #0 cmp.z i beq b4_from_b3 jmp b5 // main::@5 b5: // [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'+' ldy.z idx sta SCREEN,y // [10] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuz1=_inc_vbuz1 inc.z idx // [11] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] b4_from_b3: b4_from_b5: // [11] phi (byte) main::idx#11 = (byte) main::idx#10 [phi:main::@3/main::@5->main::@4#0] -- register_copy jmp b4 // main::@4 b4: // [12] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i // [13] if((byte) main::i#1!=(byte) 3) goto main::@3 -- vbuz1_neq_vbuc1_then_la1 lda #3 cmp.z i bne b3_from_b4 jmp b6 // main::@6 b6: // [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2 lda #' ' ldy.z idx sta SCREEN,y // [15] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuz1=_inc_vbuz2 ldy.z idx iny sty.z idx_5 // [16] phi from main::@6 to main::@7 [phi:main::@6->main::@7] b7_from_b6: // [16] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) 0 [phi:main::@6->main::@7#1] -- vwuz1=vwuc1 lda #<0 sta.z i1 lda #>0 sta.z i1+1 jmp b7 // loop word // [16] phi from main::@8 to main::@7 [phi:main::@8->main::@7] b7_from_b8: // [16] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy jmp b7 // main::@7 b7: // [17] if((byte) 0==(word) main::i1#2) goto main::@8 -- vwuc1_eq_vwuz1_then_la1 lda.z i1 cmp #<0 bne !+ lda.z i1+1 cmp #>0 beq b8_from_b7 !: jmp b9 // main::@9 b9: // [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'+' ldy.z idx_12 sta SCREEN,y // [19] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuz1=_inc_vbuz1 inc.z idx_6 // [20] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] b8_from_b7: b8_from_b9: // [20] phi (byte) main::idx#17 = (byte) main::idx#12 [phi:main::@7/main::@9->main::@8#0] -- register_copy jmp b8 // main::@8 b8: // [21] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [22] if((word) main::i1#1!=(byte) 3) goto main::@7 -- vwuz1_neq_vwuc1_then_la1 lda.z i1+1 cmp #>3 bne b7_from_b8 lda.z i1 cmp #<3 bne b7_from_b8 jmp breturn // main::@return breturn: // [23] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] *((const byte*) SCREEN#0) ← (byte) '+' [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' [ main::i#2 main::idx#10 ] ( main:2 [ main::i#2 main::idx#10 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::idx#10 main::idx#11 main::idx#4 ] Statement [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' [ main::idx#11 ] ( main:2 [ main::idx#11 ] ) always clobbers reg byte a Statement [17] if((byte) 0==(word) main::i1#2) goto main::@8 [ main::i1#2 main::idx#12 ] ( main:2 [ main::i1#2 main::idx#12 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] Statement [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' [ main::i1#2 main::idx#12 ] ( main:2 [ main::i1#2 main::idx#12 ] ) always clobbers reg byte a Statement [22] if((word) main::i1#1!=(byte) 3) goto main::@7 [ main::i1#1 main::idx#17 ] ( main:2 [ main::i1#1 main::idx#17 ] ) always clobbers reg byte a Statement [5] *((const byte*) SCREEN#0) ← (byte) '+' [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' [ main::i#2 main::idx#10 ] ( main:2 [ main::i#2 main::idx#10 ] ) always clobbers reg byte a Statement [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' [ main::idx#11 ] ( main:2 [ main::idx#11 ] ) always clobbers reg byte a Statement [17] if((byte) 0==(word) main::i1#2) goto main::@8 [ main::i1#2 main::idx#12 ] ( main:2 [ main::i1#2 main::idx#12 ] ) always clobbers reg byte a Statement [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' [ main::i1#2 main::idx#12 ] ( main:2 [ main::i1#2 main::idx#12 ] ) always clobbers reg byte a Statement [22] if((word) main::i1#1!=(byte) 3) goto main::@7 [ main::i1#1 main::idx#17 ] ( main:2 [ main::i1#1 main::idx#17 ] ) always clobbers reg byte a Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , Potential registers zp ZP_BYTE:3 [ main::idx#10 main::idx#11 main::idx#4 ] : zp ZP_BYTE:3 , reg byte x , reg byte y , Potential registers zp ZP_WORD:4 [ main::i1#2 main::i1#1 ] : zp ZP_WORD:4 , Potential registers zp ZP_BYTE:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] : zp ZP_BYTE:6 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [main] 52.33: zp ZP_BYTE:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] 45.92: zp ZP_BYTE:3 [ main::idx#10 main::idx#11 main::idx#4 ] 23.1: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 23.1: zp ZP_WORD:4 [ main::i1#2 main::i1#1 ] Uplift Scope [] Uplifting [main] best 1227 combination reg byte y [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] reg byte y [ main::idx#10 main::idx#11 main::idx#4 ] reg byte x [ main::i#2 main::i#1 ] zp ZP_WORD:4 [ main::i1#2 main::i1#1 ] Uplifting [] best 1227 combination Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ main::i1#2 main::i1#1 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments // Tests using integer conditions in if() // This should produce '+ ++ ++' at the top of the screen // Upstart .pc = $801 "Basic" :BasicUpstart(bbegin) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 // @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: { .label i1 = 2 jmp b2 // main::@2 b2: // [5] *((const byte*) SCREEN#0) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN jmp b1 // main::@1 b1: // [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [7] phi from main::@1 to main::@3 [phi:main::@1->main::@3] b3_from_b1: // [7] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuyy=vbuc1 ldy #2 // [7] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuxx=vbuc1 ldx #0 jmp b3 // loop byte // [7] phi from main::@4 to main::@3 [phi:main::@4->main::@3] b3_from_b4: // [7] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy jmp b3 // main::@3 b3: // [8] if((byte) 0==(byte) main::i#2) goto main::@4 -- vbuc1_eq_vbuxx_then_la1 cpx #0 beq b4_from_b3 jmp b5 // main::@5 b5: // [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // [10] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuyy=_inc_vbuyy iny // [11] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] b4_from_b3: b4_from_b5: // [11] phi (byte) main::idx#11 = (byte) main::idx#10 [phi:main::@3/main::@5->main::@4#0] -- register_copy jmp b4 // main::@4 b4: // [12] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx // [13] if((byte) main::i#1!=(byte) 3) goto main::@3 -- vbuxx_neq_vbuc1_then_la1 cpx #3 bne b3_from_b4 jmp b6 // main::@6 b6: // [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2 lda #' ' sta SCREEN,y // [15] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuyy=_inc_vbuyy iny // [16] phi from main::@6 to main::@7 [phi:main::@6->main::@7] b7_from_b6: // [16] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) 0 [phi:main::@6->main::@7#1] -- vwuz1=vwuc1 lda #<0 sta.z i1 lda #>0 sta.z i1+1 jmp b7 // loop word // [16] phi from main::@8 to main::@7 [phi:main::@8->main::@7] b7_from_b8: // [16] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy jmp b7 // main::@7 b7: // [17] if((byte) 0==(word) main::i1#2) goto main::@8 -- vwuc1_eq_vwuz1_then_la1 lda.z i1 cmp #<0 bne !+ lda.z i1+1 cmp #>0 beq b8_from_b7 !: jmp b9 // main::@9 b9: // [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // [19] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuyy=_inc_vbuyy iny // [20] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] b8_from_b7: b8_from_b9: // [20] phi (byte) main::idx#17 = (byte) main::idx#12 [phi:main::@7/main::@9->main::@8#0] -- register_copy jmp b8 // main::@8 b8: // [21] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [22] if((word) main::i1#1!=(byte) 3) goto main::@7 -- vwuz1_neq_vwuc1_then_la1 lda.z i1+1 cmp #>3 bne b7_from_b8 lda.z i1 cmp #<3 bne b7_from_b8 jmp breturn // main::@return breturn: // [23] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp b1 Removing instruction jmp bend Removing instruction jmp b2 Removing instruction jmp b1 Removing instruction jmp b3 Removing instruction jmp b5 Removing instruction jmp b4 Removing instruction jmp b6 Removing instruction jmp b7 Removing instruction jmp b9 Removing instruction jmp b8 Removing instruction jmp breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction lda #>0 Succesful ASM optimization Pass5UnnecesaryLoadElimination Replacing label b4_from_b3 with b4 Replacing label b3_from_b4 with b3 Replacing label b8_from_b7 with b8 Replacing label b7_from_b8 with b7 Replacing label b7_from_b8 with b7 Removing instruction b1_from_bbegin: Removing instruction b1: Removing instruction main_from_b1: Removing instruction bend_from_b1: Removing instruction b3_from_b4: Removing instruction b4_from_b3: Removing instruction b4_from_b5: Removing instruction b7_from_b8: Removing instruction b8_from_b7: Removing instruction b8_from_b9: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction bend: Removing instruction b2: Removing instruction b1: Removing instruction b3_from_b1: Removing instruction b5: Removing instruction b6: Removing instruction b7_from_b6: Removing instruction b9: Removing instruction breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly Removing instruction jsr main Succesful ASM optimization Pass5SkipBegin Removing instruction jmp b3 Removing instruction jmp b7 Succesful ASM optimization Pass5NextJumpElimination Removing instruction bbegin: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (byte*) SCREEN (const byte*) SCREEN#0 SCREEN = (byte*) 1024 (void()) main() (label) main::@1 (label) main::@2 (label) main::@3 (label) main::@4 (label) main::@5 (label) main::@6 (label) main::@7 (label) main::@8 (label) main::@9 (label) main::@return (byte) main::i (byte) main::i#1 reg byte x 16.5 (byte) main::i#2 reg byte x 6.6000000000000005 (word) main::i1 (word) main::i1#1 i1 zp ZP_WORD:2 16.5 (word) main::i1#2 i1 zp ZP_WORD:2 6.6000000000000005 (byte) main::idx (byte) main::idx#10 reg byte y 14.666666666666666 (byte) main::idx#11 reg byte y 9.25 (byte) main::idx#12 reg byte y 15.333333333333332 (byte) main::idx#17 reg byte y 11.0 (byte) main::idx#4 reg byte y 22.0 (byte) main::idx#5 reg byte y 4.0 (byte) main::idx#6 reg byte y 22.0 reg byte x [ main::i#2 main::i#1 ] reg byte y [ main::idx#10 main::idx#11 main::idx#4 ] zp ZP_WORD:2 [ main::i1#2 main::i1#1 ] reg byte y [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] FINAL ASSEMBLER Score: 862 // File Comments // Tests using integer conditions in if() // This should produce '+ ++ ++' at the top of the screen // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 // @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: { .label i1 = 2 // main::@2 // SCREEN[idx++] = '+' // [5] *((const byte*) SCREEN#0) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN // main::@1 // SCREEN[idx++] = ' ' // [6] *((const byte*) SCREEN#0+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [7] phi from main::@1 to main::@3 [phi:main::@1->main::@3] // [7] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuyy=vbuc1 ldy #2 // [7] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuxx=vbuc1 ldx #0 // loop byte // [7] phi from main::@4 to main::@3 [phi:main::@4->main::@3] // [7] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [7] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy // main::@3 b3: // if(i) // [8] if((byte) 0==(byte) main::i#2) goto main::@4 -- vbuc1_eq_vbuxx_then_la1 cpx #0 beq b4 // main::@5 // SCREEN[idx++] = '+' // [9] *((const byte*) SCREEN#0 + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // SCREEN[idx++] = '+'; // [10] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuyy=_inc_vbuyy iny // [11] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] // [11] phi (byte) main::idx#11 = (byte) main::idx#10 [phi:main::@3/main::@5->main::@4#0] -- register_copy // main::@4 b4: // for( byte i:0..2) // [12] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx // [13] if((byte) main::i#1!=(byte) 3) goto main::@3 -- vbuxx_neq_vbuc1_then_la1 cpx #3 bne b3 // main::@6 // SCREEN[idx++] = ' ' // [14] *((const byte*) SCREEN#0 + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2 lda #' ' sta SCREEN,y // SCREEN[idx++] = ' '; // [15] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuyy=_inc_vbuyy iny // [16] phi from main::@6 to main::@7 [phi:main::@6->main::@7] // [16] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) 0 [phi:main::@6->main::@7#1] -- vwuz1=vwuc1 lda #<0 sta.z i1 sta.z i1+1 // loop word // [16] phi from main::@8 to main::@7 [phi:main::@8->main::@7] // [16] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [16] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy // main::@7 b7: // if(i) // [17] if((byte) 0==(word) main::i1#2) goto main::@8 -- vwuc1_eq_vwuz1_then_la1 lda.z i1 cmp #<0 bne !+ lda.z i1+1 cmp #>0 beq b8 !: // main::@9 // SCREEN[idx++] = '+' // [18] *((const byte*) SCREEN#0 + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // SCREEN[idx++] = '+'; // [19] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuyy=_inc_vbuyy iny // [20] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] // [20] phi (byte) main::idx#17 = (byte) main::idx#12 [phi:main::@7/main::@9->main::@8#0] -- register_copy // main::@8 b8: // for( word i:0..2) // [21] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [22] if((word) main::i1#1!=(byte) 3) goto main::@7 -- vwuz1_neq_vwuc1_then_la1 lda.z i1+1 cmp #>3 bne b7 lda.z i1 cmp #<3 bne b7 // main::@return // } // [23] return rts } // File Data