CONTROL FLOW GRAPH SSA (void()) main() main: scope:[main] from _start (byte) main::idx#0 ← (byte) 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 ) *((const nomodify byte*) SCREEN + (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 ) *((const nomodify byte*) SCREEN + (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 ) *((const nomodify byte*) SCREEN + (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 ) *((const nomodify byte*) SCREEN + (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 ) *((const nomodify byte*) SCREEN + (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 ) *((const nomodify byte*) SCREEN + (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 (void()) _start() _start: scope:[_start] from call main to:_start::@1 _start::@1: scope:[_start] from _start to:_start::@return _start::@return: scope:[_start] from _start::@1 return to:@return SYMBOL TABLE SSA (const nomodify byte*) SCREEN = (byte*)(number) $400 (void()) _start() (label) _start::@1 (label) _start::@return (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 (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 Simplifying constant pointer cast (byte*) 1024 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 Successful SSA optimization PassNFinalizeNumberTypeConversions Inversing boolean not [18] (bool~) main::$2 ← (byte) 0 == (byte) main::i#2 from [17] (bool~) main::$6 ← (byte) 0 != (byte) main::i#2 Inversing boolean not [33] (bool~) main::$4 ← (byte) 0 == (word) main::i1#2 from [32] (bool~) main::$7 ← (byte) 0 != (word) main::i1#2 Successful SSA optimization Pass2UnaryNotSimplification Alias main::idx#0 = main::idx#7 Alias main::idx#13 = main::idx#9 Alias main::idx#10 = main::idx#14 Alias main::i#2 = main::i#4 Alias main::idx#11 = main::idx#15 Alias main::idx#12 = main::idx#16 Alias main::i1#2 = main::i1#4 Successful SSA optimization Pass2AliasElimination Alias main::i#2 = main::i#3 Alias main::i1#2 = main::i1#3 Successful SSA optimization Pass2AliasElimination Simple Condition (bool~) main::$2 [16] if((byte) 0==(byte) main::i#2) goto main::@6 Simple Condition (bool~) main::$3 [20] if((byte) main::i#1!=rangelast(0,2)) goto main::@5 Simple Condition (bool~) main::$4 [28] if((byte) 0==(word) main::i1#2) goto main::@10 Simple Condition (bool~) main::$5 [32] if((word) main::i1#1!=rangelast(0,2)) goto main::@9 Successful SSA optimization Pass2ConditionalJumpSimplification Rewriting ! if()-condition to reversed if() [1] (bool~) main::$0 ← ! (number) 0!=(number) 0 Rewriting ! if()-condition to reversed if() [4] (bool~) main::$1 ← ! (number) 0!=(number) $3e7 Successful SSA optimization Pass2ConditionalAndOrRewriting 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 [2] 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 [5] if((number) 0!=(number) $3e7) goto main::@4 Successful SSA optimization Pass2ConstantIfs Resolved ranged next value [18] main::i#1 ← ++ main::i#2 to ++ Resolved ranged comparison value [20] if(main::i#1!=rangelast(0,2)) goto main::@5 to (number) 3 Resolved ranged next value [30] main::i1#1 ← ++ main::i1#2 to ++ Resolved ranged comparison value [32] if(main::i1#1!=rangelast(0,2)) goto main::@9 to (number) 3 Simplifying expression containing zero SCREEN in [6] *((const nomodify byte*) SCREEN + (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 Removing unused procedure _start Removing unused procedure block _start Removing unused procedure block _start::@1 Removing unused procedure block _start::@return Successful SSA optimization PassNEliminateEmptyStart Adding number conversion cast (unumber) 3 in [10] if((byte) main::i#1!=(number) 3) goto main::@5 Adding number conversion cast (unumber) 3 in [19] 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 main::idx#3 = 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 [4] (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 in [3] *((const nomodify byte*) SCREEN + (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) 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::@12(between main::@6 and main::@5) Added new block during phi lifting main::@13(between main::@5 and main::@6) Added new block during phi lifting main::@14(between main::@10 and main::@9) Added new block during phi lifting main::@15(between main::@9 and main::@10) Adding NOP phi() at start of main Adding NOP phi() at start of main::@1 CALL GRAPH Created 6 initial phi equivalence classes Coalesced [8] main::idx#20 ← main::idx#4 Coalesced [14] main::idx#22 ← main::idx#5 Coalesced [19] main::idx#23 ← main::idx#6 Coalesced [24] main::i1#5 ← main::i1#1 Coalesced [25] main::idx#21 ← main::idx#17 Coalesced (already) [26] main::idx#24 ← main::idx#12 Coalesced [27] main::i#5 ← main::i#1 Coalesced [28] main::idx#18 ← main::idx#11 Coalesced (already) [29] main::idx#19 ← main::idx#10 Coalesced down to 4 phi equivalence classes Culled Empty Block (label) main::@1 Culled Empty Block (label) main::@14 Culled Empty Block (label) main::@15 Culled Empty Block (label) main::@12 Culled Empty Block (label) main::@13 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 main FINAL CONTROL FLOW GRAPH (void()) main() main: scope:[main] from [0] phi() to:main::@2 main::@2: scope:[main] from main [1] *((const nomodify byte*) SCREEN) ← (byte) '+' to:main::@1 main::@1: scope:[main] from main::@2 [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' to:main::@3 main::@3: scope:[main] from main::@1 main::@4 [3] (byte) main::idx#10 ← phi( main::@1/(byte) 2 main::@4/(byte) main::idx#11 ) [3] (byte) main::i#2 ← phi( main::@1/(byte) 0 main::@4/(byte) main::i#1 ) [4] if((byte) 0==(byte) main::i#2) goto main::@4 to:main::@5 main::@5: scope:[main] from main::@3 [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' [6] (byte) main::idx#4 ← ++ (byte) main::idx#10 to:main::@4 main::@4: scope:[main] from main::@3 main::@5 [7] (byte) main::idx#11 ← phi( main::@3/(byte) main::idx#10 main::@5/(byte) main::idx#4 ) [8] (byte) main::i#1 ← ++ (byte) main::i#2 [9] if((byte) main::i#1!=(byte) 3) goto main::@3 to:main::@6 main::@6: scope:[main] from main::@4 [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' [11] (byte) main::idx#5 ← ++ (byte) main::idx#11 to:main::@7 main::@7: scope:[main] from main::@6 main::@8 [12] (byte) main::idx#12 ← phi( main::@8/(byte) main::idx#17 main::@6/(byte) main::idx#5 ) [12] (word) main::i1#2 ← phi( main::@8/(word) main::i1#1 main::@6/(word) 0 ) [13] if((byte) 0==(word) main::i1#2) goto main::@8 to:main::@9 main::@9: scope:[main] from main::@7 [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' [15] (byte) main::idx#6 ← ++ (byte) main::idx#12 to:main::@8 main::@8: scope:[main] from main::@7 main::@9 [16] (byte) main::idx#17 ← phi( main::@9/(byte) main::idx#6 main::@7/(byte) main::idx#12 ) [17] (word) main::i1#1 ← ++ (word) main::i1#2 [18] if((word) main::i1#1!=(byte) 3) goto main::@7 to:main::@return main::@return: scope:[main] from main::@8 [19] return to:@return VARIABLE REGISTER WEIGHTS (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[1]:2 [ main::i#2 main::i#1 ] Allocated zp[1]:3 [ main::idx#10 main::idx#11 main::idx#4 ] Allocated zp[2]:4 [ main::i1#2 main::i1#1 ] Allocated zp[1]: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(main) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 // main main: { .label i = 2 .label idx = 3 .label idx_1 = 6 .label i1 = 4 jmp __b2 // main::@2 __b2: // [1] *((const nomodify byte*) SCREEN) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN jmp __b1 // main::@1 __b1: // [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [3] phi from main::@1 to main::@3 [phi:main::@1->main::@3] __b3_from___b1: // [3] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuz1=vbuc1 lda #2 sta.z idx // [3] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b3 // loop byte // [3] phi from main::@4 to main::@3 [phi:main::@4->main::@3] __b3_from___b4: // [3] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [3] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy jmp __b3 // main::@3 __b3: // [4] 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: // [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'+' ldy.z idx sta SCREEN,y // [6] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuz1=_inc_vbuz1 inc.z idx // [7] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] __b4_from___b3: __b4_from___b5: // [7] phi (byte) main::idx#11 = (byte) main::idx#10 [phi:main::@3/main::@5->main::@4#0] -- register_copy jmp __b4 // main::@4 __b4: // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i // [9] 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: // [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2 lda #' ' ldy.z idx sta SCREEN,y // [11] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuz1=_inc_vbuz2 ldy.z idx iny sty.z idx_1 // [12] phi from main::@6 to main::@7 [phi:main::@6->main::@7] __b7_from___b6: // [12] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [12] 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 // [12] phi from main::@8 to main::@7 [phi:main::@8->main::@7] __b7_from___b8: // [12] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [12] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy jmp __b7 // main::@7 __b7: // [13] if((byte) 0==(word) main::i1#2) goto main::@8 -- vbuc1_eq_vwuz1_then_la1 lda #0 cmp.z i1 bne !+ lda.z i1+1 bne !+ jmp __b8_from___b7 !: jmp __b9 // main::@9 __b9: // [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'+' ldy.z idx_1 sta SCREEN,y // [15] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuz1=_inc_vbuz1 inc.z idx_1 // [16] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] __b8_from___b7: __b8_from___b9: // [16] phi (byte) main::idx#17 = (byte) main::idx#12 [phi:main::@7/main::@9->main::@8#0] -- register_copy jmp __b8 // main::@8 __b8: // [17] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [18] 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: // [19] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [1] *((const nomodify byte*) SCREEN) ← (byte) '+' [ ] ( [ ] { } ) always clobbers reg byte a Statement [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' [ ] ( [ ] { } ) always clobbers reg byte a Statement [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' [ main::i#2 main::idx#10 ] ( [ main::i#2 main::idx#10 ] { } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::idx#10 main::idx#11 main::idx#4 ] Statement [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' [ main::idx#11 ] ( [ main::idx#11 ] { } ) always clobbers reg byte a Statement [13] if((byte) 0==(word) main::i1#2) goto main::@8 [ main::i1#2 main::idx#12 ] ( [ main::i1#2 main::idx#12 ] { } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] Statement [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' [ main::i1#2 main::idx#12 ] ( [ main::i1#2 main::idx#12 ] { } ) always clobbers reg byte a Statement [18] if((word) main::i1#1!=(byte) 3) goto main::@7 [ main::i1#1 main::idx#17 ] ( [ main::i1#1 main::idx#17 ] { } ) always clobbers reg byte a Statement [1] *((const nomodify byte*) SCREEN) ← (byte) '+' [ ] ( [ ] { } ) always clobbers reg byte a Statement [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' [ ] ( [ ] { } ) always clobbers reg byte a Statement [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' [ main::i#2 main::idx#10 ] ( [ main::i#2 main::idx#10 ] { } ) always clobbers reg byte a Statement [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' [ main::idx#11 ] ( [ main::idx#11 ] { } ) always clobbers reg byte a Statement [13] if((byte) 0==(word) main::i1#2) goto main::@8 [ main::i1#2 main::idx#12 ] ( [ main::i1#2 main::idx#12 ] { } ) always clobbers reg byte a Statement [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' [ main::i1#2 main::idx#12 ] ( [ main::i1#2 main::idx#12 ] { } ) always clobbers reg byte a Statement [18] if((word) main::i1#1!=(byte) 3) goto main::@7 [ main::i1#1 main::idx#17 ] ( [ main::i1#1 main::idx#17 ] { } ) always clobbers reg byte a Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y , Potential registers zp[1]:3 [ main::idx#10 main::idx#11 main::idx#4 ] : zp[1]:3 , reg byte x , reg byte y , Potential registers zp[2]:4 [ main::i1#2 main::i1#1 ] : zp[2]:4 , Potential registers zp[1]:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] : zp[1]:6 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [main] 52.33: zp[1]:6 [ main::idx#12 main::idx#17 main::idx#5 main::idx#6 ] 45.92: zp[1]:3 [ main::idx#10 main::idx#11 main::idx#4 ] 23.1: zp[1]:2 [ main::i#2 main::i#1 ] 23.1: zp[2]:4 [ main::i1#2 main::i1#1 ] Uplift Scope [] Uplifting [main] best 1225 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[2]:4 [ main::i1#2 main::i1#1 ] Uplifting [] best 1225 combination Allocated (was zp[2]:4) zp[2]: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(main) .pc = $80d "Program" // Global Constants & labels .label SCREEN = $400 // main main: { .label i1 = 2 jmp __b2 // main::@2 __b2: // [1] *((const nomodify byte*) SCREEN) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN jmp __b1 // main::@1 __b1: // [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [3] phi from main::@1 to main::@3 [phi:main::@1->main::@3] __b3_from___b1: // [3] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuyy=vbuc1 ldy #2 // [3] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuxx=vbuc1 ldx #0 jmp __b3 // loop byte // [3] phi from main::@4 to main::@3 [phi:main::@4->main::@3] __b3_from___b4: // [3] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [3] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy jmp __b3 // main::@3 __b3: // [4] 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: // [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // [6] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuyy=_inc_vbuyy iny // [7] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] __b4_from___b3: __b4_from___b5: // [7] phi (byte) main::idx#11 = (byte) main::idx#10 [phi:main::@3/main::@5->main::@4#0] -- register_copy jmp __b4 // main::@4 __b4: // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx // [9] 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: // [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2 lda #' ' sta SCREEN,y // [11] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuyy=_inc_vbuyy iny // [12] phi from main::@6 to main::@7 [phi:main::@6->main::@7] __b7_from___b6: // [12] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [12] 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 // [12] phi from main::@8 to main::@7 [phi:main::@8->main::@7] __b7_from___b8: // [12] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [12] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy jmp __b7 // main::@7 __b7: // [13] if((byte) 0==(word) main::i1#2) goto main::@8 -- vbuc1_eq_vwuz1_then_la1 lda #0 cmp.z i1 bne !+ lda.z i1+1 bne !+ jmp __b8_from___b7 !: jmp __b9 // main::@9 __b9: // [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // [15] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuyy=_inc_vbuyy iny // [16] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] __b8_from___b7: __b8_from___b9: // [16] phi (byte) main::idx#17 = (byte) main::idx#12 [phi:main::@7/main::@9->main::@8#0] -- register_copy jmp __b8 // main::@8 __b8: // [17] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [18] 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: // [19] return rts } // File Data ASSEMBLER OPTIMIZATIONS 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 __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 __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 Removing instruction jmp __b3 Removing instruction jmp __b7 Succesful ASM optimization Pass5NextJumpElimination FINAL SYMBOL TABLE (const nomodify byte*) 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[2]:2 16.5 (word) main::i1#2 i1 zp[2]: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[2]: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: 872 // 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 // main main: { .label i1 = 2 // main::@2 // SCREEN[idx++] = '+' // [1] *((const nomodify byte*) SCREEN) ← (byte) '+' -- _deref_pbuc1=vbuc2 lda #'+' sta SCREEN // main::@1 // SCREEN[idx++] = ' ' // [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte) ' ' -- _deref_pbuc1=vbuc2 lda #' ' sta SCREEN+1 // [3] phi from main::@1 to main::@3 [phi:main::@1->main::@3] // [3] phi (byte) main::idx#10 = (byte) 2 [phi:main::@1->main::@3#0] -- vbuyy=vbuc1 ldy #2 // [3] phi (byte) main::i#2 = (byte) 0 [phi:main::@1->main::@3#1] -- vbuxx=vbuc1 ldx #0 // loop byte // [3] phi from main::@4 to main::@3 [phi:main::@4->main::@3] // [3] phi (byte) main::idx#10 = (byte) main::idx#11 [phi:main::@4->main::@3#0] -- register_copy // [3] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#1] -- register_copy // main::@3 __b3: // if(i) // [4] if((byte) 0==(byte) main::i#2) goto main::@4 -- vbuc1_eq_vbuxx_then_la1 cpx #0 beq __b4 // main::@5 // SCREEN[idx++] = '+' // [5] *((const nomodify byte*) SCREEN + (byte) main::idx#10) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // SCREEN[idx++] = '+'; // [6] (byte) main::idx#4 ← ++ (byte) main::idx#10 -- vbuyy=_inc_vbuyy iny // [7] phi from main::@3 main::@5 to main::@4 [phi:main::@3/main::@5->main::@4] // [7] 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) // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx // [9] if((byte) main::i#1!=(byte) 3) goto main::@3 -- vbuxx_neq_vbuc1_then_la1 cpx #3 bne __b3 // main::@6 // SCREEN[idx++] = ' ' // [10] *((const nomodify byte*) SCREEN + (byte) main::idx#11) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2 lda #' ' sta SCREEN,y // SCREEN[idx++] = ' '; // [11] (byte) main::idx#5 ← ++ (byte) main::idx#11 -- vbuyy=_inc_vbuyy iny // [12] phi from main::@6 to main::@7 [phi:main::@6->main::@7] // [12] phi (byte) main::idx#12 = (byte) main::idx#5 [phi:main::@6->main::@7#0] -- register_copy // [12] 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 // [12] phi from main::@8 to main::@7 [phi:main::@8->main::@7] // [12] phi (byte) main::idx#12 = (byte) main::idx#17 [phi:main::@8->main::@7#0] -- register_copy // [12] phi (word) main::i1#2 = (word) main::i1#1 [phi:main::@8->main::@7#1] -- register_copy // main::@7 __b7: // if(i) // [13] if((byte) 0==(word) main::i1#2) goto main::@8 -- vbuc1_eq_vwuz1_then_la1 lda #0 cmp.z i1 bne !+ lda.z i1+1 bne !+ jmp __b8 !: // main::@9 // SCREEN[idx++] = '+' // [14] *((const nomodify byte*) SCREEN + (byte) main::idx#12) ← (byte) '+' -- pbuc1_derefidx_vbuyy=vbuc2 lda #'+' sta SCREEN,y // SCREEN[idx++] = '+'; // [15] (byte) main::idx#6 ← ++ (byte) main::idx#12 -- vbuyy=_inc_vbuyy iny // [16] phi from main::@7 main::@9 to main::@8 [phi:main::@7/main::@9->main::@8] // [16] 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) // [17] (word) main::i1#1 ← ++ (word) main::i1#2 -- vwuz1=_inc_vwuz1 inc.z i1 bne !+ inc.z i1+1 !: // [18] 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 // } // [19] return rts } // File Data