diff --git a/src/test/ref/liverange-10.asm b/src/test/ref/liverange-10.asm new file mode 100644 index 000000000..201b65fde --- /dev/null +++ b/src/test/ref/liverange-10.asm @@ -0,0 +1,130 @@ +// Test effective live range and register allocation +// Here outsw::sw and outw::w should have the same allocation +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + .label sw = 2 + .label w = 4 + ldx #0 + lda #<-$14 + sta.z sw + lda #>-$14 + sta.z sw+1 + __b1: + // outsw(sw) + lda.z sw + sta.z outsw.sw + lda.z sw+1 + sta.z outsw.sw+1 + jsr outsw + // for(signed int sw: -20..19 ) + inc.z sw + bne !+ + inc.z sw+1 + !: + lda.z sw+1 + cmp #>$14 + bne __b1 + lda.z sw + cmp #<$14 + bne __b1 + lda #<0 + sta.z w + sta.z w+1 + __b2: + // outw(w) + jsr outw + // for(unsigned int w: 0..39 ) + inc.z w + bne !+ + inc.z w+1 + !: + lda.z w+1 + cmp #>$28 + bne __b2 + lda.z w + cmp #<$28 + bne __b2 + // } + rts +} +// outw(word zp(4) w) +outw: { + .label w = 4 + // >w + lda.z w+1 + // (>w)<<4 + asl + asl + asl + asl + // out(HEXTAB[(>w)<<4]) + tay + lda HEXTAB,y + jsr out + // >w + lda.z w+1 + // (>w)&0x0f + and #$f + // out(HEXTAB[(>w)&0x0f]) + tay + lda HEXTAB,y + jsr out + // (word) outw::w#2 + [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 + [19] (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) + [20] call out + to:outw::@1 +outw::@1: scope:[outw] from outw + [21] (byte~) outw::$3 ← > (word) outw::w#2 + [22] (byte~) outw::$4 ← (byte~) outw::$3 & (byte) $f + [23] (byte) out::c#2 ← *((const byte*) HEXTAB + (byte~) outw::$4) + [24] call out + to:outw::@2 +outw::@2: scope:[outw] from outw::@1 + [25] (byte~) outw::$6 ← < (word) outw::w#2 + [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 + [27] (byte) out::c#3 ← *((const byte*) HEXTAB + (byte~) outw::$7) + [28] call out + to:outw::@3 +outw::@3: scope:[outw] from outw::@2 + [29] (byte~) outw::$9 ← < (word) outw::w#2 + [30] (byte~) outw::$10 ← (byte~) outw::$9 & (byte) $f + [31] (byte) out::c#4 ← *((const byte*) HEXTAB + (byte~) outw::$10) + [32] call out + to:outw::@return +outw::@return: scope:[outw] from outw::@3 + [33] return + to:@return + +(void()) out((byte) out::c) +out: scope:[out] from outsw::@2 outw outw::@1 outw::@2 outw::@3 + [34] (byte) out::c#5 ← phi( outsw::@2/(byte) '-' outw/(byte) out::c#1 outw::@1/(byte) out::c#2 outw::@2/(byte) out::c#3 outw::@3/(byte) out::c#4 ) + [34] (byte) idx#26 ← phi( outsw::@2/(byte) idx#29 outw/(byte) idx#33 outw::@1/(byte) idx#12 outw::@2/(byte) idx#12 outw::@3/(byte) idx#12 ) + [35] (byte) idx#12 ← ++ (byte) idx#26 + [36] *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 + to:out::@return +out::@return: scope:[out] from out + [37] return + to:@return + +(void()) outsw((signed word) outsw::sw) +outsw: scope:[outsw] from main::@1 + [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 + to:outsw::@2 +outsw::@2: scope:[outsw] from outsw + [39] phi() + [40] call out + to:outsw::@3 +outsw::@3: scope:[outsw] from outsw::@2 + [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 + to:outsw::@1 +outsw::@1: scope:[outsw] from outsw outsw::@3 + [42] (byte) idx#31 ← phi( outsw/(byte) idx#29 outsw::@3/(byte) idx#12 ) + [42] (signed word) outsw::sw#3 ← phi( outsw/(signed word) outsw::sw#0 outsw::@3/(signed word) outsw::sw#1 ) + [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 + [44] call outw + to:outsw::@return +outsw::@return: scope:[outsw] from outsw::@1 + [45] return + to:@return diff --git a/src/test/ref/liverange-10.log b/src/test/ref/liverange-10.log new file mode 100644 index 000000000..9c49ee794 --- /dev/null +++ b/src/test/ref/liverange-10.log @@ -0,0 +1,1590 @@ +Culled Empty Block (label) main::@4 +Culled Empty Block (label) @1 +Culled Empty Block (label) @2 +Culled Empty Block (label) @3 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte) idx#0 ← (byte) 0 + to:@4 + +(void()) main() +main: scope:[main] from @4 + (byte) idx#35 ← phi( @4/(byte) idx#34 ) + (signed word) main::sw#0 ← (signed word) -$14 + to:main::@1 +main::@1: scope:[main] from main main::@5 + (byte) idx#29 ← phi( main/(byte) idx#35 main::@5/(byte) idx#1 ) + (signed word) main::sw#2 ← phi( main/(signed word) main::sw#0 main::@5/(signed word) main::sw#1 ) + (signed word) outsw::sw#0 ← (signed word) main::sw#2 + call outsw + to:main::@5 +main::@5: scope:[main] from main::@1 + (signed word) main::sw#3 ← phi( main::@1/(signed word) main::sw#2 ) + (byte) idx#15 ← phi( main::@1/(byte) idx#6 ) + (byte) idx#1 ← (byte) idx#15 + (signed word) main::sw#1 ← (signed word) main::sw#3 + rangenext(-$14,$13) + (bool~) main::$1 ← (signed word) main::sw#1 != rangelast(-$14,$13) + if((bool~) main::$1) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@5 + (byte) idx#36 ← phi( main::@5/(byte) idx#1 ) + (word) main::w#0 ← (word) 0 + to:main::@3 +main::@3: scope:[main] from main::@2 main::@6 + (byte) idx#30 ← phi( main::@2/(byte) idx#36 main::@6/(byte) idx#2 ) + (word) main::w#2 ← phi( main::@2/(word) main::w#0 main::@6/(word) main::w#1 ) + (word) outw::w#0 ← (word) main::w#2 + call outw + to:main::@6 +main::@6: scope:[main] from main::@3 + (word) main::w#3 ← phi( main::@3/(word) main::w#2 ) + (byte) idx#16 ← phi( main::@3/(byte) idx#11 ) + (byte) idx#2 ← (byte) idx#16 + (word) main::w#1 ← (word) main::w#3 + rangenext(0,$27) + (bool~) main::$3 ← (word) main::w#1 != rangelast(0,$27) + if((bool~) main::$3) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@6 + (byte) idx#17 ← phi( main::@6/(byte) idx#2 ) + (byte) idx#3 ← (byte) idx#17 + return + to:@return + +(void()) outsw((signed word) outsw::sw) +outsw: scope:[outsw] from main::@1 + (byte) idx#37 ← phi( main::@1/(byte) idx#29 ) + (signed word) outsw::sw#2 ← phi( main::@1/(signed word) outsw::sw#0 ) + (bool~) outsw::$0 ← (signed word) outsw::sw#2 < (number) 0 + (bool~) outsw::$1 ← ! (bool~) outsw::$0 + if((bool~) outsw::$1) goto outsw::@1 + to:outsw::@2 +outsw::@1: scope:[outsw] from outsw outsw::@4 + (byte) idx#31 ← phi( outsw/(byte) idx#37 outsw::@4/(byte) idx#5 ) + (signed word) outsw::sw#3 ← phi( outsw/(signed word) outsw::sw#2 outsw::@4/(signed word) outsw::sw#1 ) + (word~) outsw::$2 ← ((word)) (signed word) outsw::sw#3 + (word) outw::w#1 ← (word~) outsw::$2 + call outw + to:outsw::@3 +outsw::@3: scope:[outsw] from outsw::@1 + (byte) idx#18 ← phi( outsw::@1/(byte) idx#11 ) + (byte) idx#4 ← (byte) idx#18 + to:outsw::@return +outsw::@2: scope:[outsw] from outsw + (signed word) outsw::sw#5 ← phi( outsw/(signed word) outsw::sw#2 ) + (byte) idx#32 ← phi( outsw/(byte) idx#37 ) + (byte) out::c#0 ← (byte) '-' + call out + to:outsw::@4 +outsw::@4: scope:[outsw] from outsw::@2 + (signed word) outsw::sw#4 ← phi( outsw::@2/(signed word) outsw::sw#5 ) + (byte) idx#19 ← phi( outsw::@2/(byte) idx#13 ) + (byte) idx#5 ← (byte) idx#19 + (signed word~) outsw::$5 ← - (signed word) outsw::sw#4 + (signed word) outsw::sw#1 ← (signed word~) outsw::$5 + to:outsw::@1 +outsw::@return: scope:[outsw] from outsw::@3 + (byte) idx#20 ← phi( outsw::@3/(byte) idx#4 ) + (byte) idx#6 ← (byte) idx#20 + return + to:@return + +(void()) outw((word) outw::w) +outw: scope:[outw] from main::@3 outsw::@1 + (byte) idx#33 ← phi( main::@3/(byte) idx#30 outsw::@1/(byte) idx#31 ) + (word) outw::w#2 ← phi( main::@3/(word) outw::w#0 outsw::@1/(word) outw::w#1 ) + (byte~) outw::$0 ← > (word) outw::w#2 + (byte~) outw::$1 ← (byte~) outw::$0 << (number) 4 + (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) + call out + to:outw::@1 +outw::@1: scope:[outw] from outw + (word) outw::w#3 ← phi( outw/(word) outw::w#2 ) + (byte) idx#21 ← phi( outw/(byte) idx#13 ) + (byte) idx#7 ← (byte) idx#21 + (byte~) outw::$3 ← > (word) outw::w#3 + (number~) outw::$4 ← (byte~) outw::$3 & (number) $f + (byte) out::c#2 ← *((const byte*) HEXTAB + (number~) outw::$4) + call out + to:outw::@2 +outw::@2: scope:[outw] from outw::@1 + (word) outw::w#4 ← phi( outw::@1/(word) outw::w#3 ) + (byte) idx#22 ← phi( outw::@1/(byte) idx#13 ) + (byte) idx#8 ← (byte) idx#22 + (byte~) outw::$6 ← < (word) outw::w#4 + (byte~) outw::$7 ← (byte~) outw::$6 << (number) 4 + (byte) out::c#3 ← *((const byte*) HEXTAB + (byte~) outw::$7) + call out + to:outw::@3 +outw::@3: scope:[outw] from outw::@2 + (word) outw::w#5 ← phi( outw::@2/(word) outw::w#4 ) + (byte) idx#23 ← phi( outw::@2/(byte) idx#13 ) + (byte) idx#9 ← (byte) idx#23 + (byte~) outw::$9 ← < (word) outw::w#5 + (number~) outw::$10 ← (byte~) outw::$9 & (number) $f + (byte) out::c#4 ← *((const byte*) HEXTAB + (number~) outw::$10) + call out + to:outw::@4 +outw::@4: scope:[outw] from outw::@3 + (byte) idx#24 ← phi( outw::@3/(byte) idx#13 ) + (byte) idx#10 ← (byte) idx#24 + to:outw::@return +outw::@return: scope:[outw] from outw::@4 + (byte) idx#25 ← phi( outw::@4/(byte) idx#10 ) + (byte) idx#11 ← (byte) idx#25 + return + to:@return + +(void()) out((byte) out::c) +out: scope:[out] from outsw::@2 outw outw::@1 outw::@2 outw::@3 + (byte) out::c#5 ← phi( outsw::@2/(byte) out::c#0 outw/(byte) out::c#1 outw::@1/(byte) out::c#2 outw::@2/(byte) out::c#3 outw::@3/(byte) out::c#4 ) + (byte) idx#26 ← phi( outsw::@2/(byte) idx#32 outw/(byte) idx#33 outw::@1/(byte) idx#7 outw::@2/(byte) idx#8 outw::@3/(byte) idx#9 ) + (byte) idx#12 ← ++ (byte) idx#26 + *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 + to:out::@return +out::@return: scope:[out] from out + (byte) idx#27 ← phi( out/(byte) idx#12 ) + (byte) idx#13 ← (byte) idx#27 + return + to:@return +@4: scope:[] from @begin + (byte) idx#34 ← phi( @begin/(byte) idx#0 ) + call main + to:@5 +@5: scope:[] from @4 + (byte) idx#28 ← phi( @4/(byte) idx#3 ) + (byte) idx#14 ← (byte) idx#28 + to:@end +@end: scope:[] from @5 + +SYMBOL TABLE SSA +(label) @4 +(label) @5 +(label) @begin +(label) @end +(const byte*) HEXTAB[] = (byte*) "0123456789abcdef" +(const byte*) SCREEN = (byte*)(number) $400 +(byte) idx +(byte) idx#0 +(byte) idx#1 +(byte) idx#10 +(byte) idx#11 +(byte) idx#12 +(byte) idx#13 +(byte) idx#14 +(byte) idx#15 +(byte) idx#16 +(byte) idx#17 +(byte) idx#18 +(byte) idx#19 +(byte) idx#2 +(byte) idx#20 +(byte) idx#21 +(byte) idx#22 +(byte) idx#23 +(byte) idx#24 +(byte) idx#25 +(byte) idx#26 +(byte) idx#27 +(byte) idx#28 +(byte) idx#29 +(byte) idx#3 +(byte) idx#30 +(byte) idx#31 +(byte) idx#32 +(byte) idx#33 +(byte) idx#34 +(byte) idx#35 +(byte) idx#36 +(byte) idx#37 +(byte) idx#4 +(byte) idx#5 +(byte) idx#6 +(byte) idx#7 +(byte) idx#8 +(byte) idx#9 +(void()) main() +(bool~) main::$1 +(bool~) main::$3 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@5 +(label) main::@6 +(label) main::@return +(signed word) main::sw +(signed word) main::sw#0 +(signed word) main::sw#1 +(signed word) main::sw#2 +(signed word) main::sw#3 +(word) main::w +(word) main::w#0 +(word) main::w#1 +(word) main::w#2 +(word) main::w#3 +(void()) out((byte) out::c) +(label) out::@return +(byte) out::c +(byte) out::c#0 +(byte) out::c#1 +(byte) out::c#2 +(byte) out::c#3 +(byte) out::c#4 +(byte) out::c#5 +(void()) outsw((signed word) outsw::sw) +(bool~) outsw::$0 +(bool~) outsw::$1 +(word~) outsw::$2 +(signed word~) outsw::$5 +(label) outsw::@1 +(label) outsw::@2 +(label) outsw::@3 +(label) outsw::@4 +(label) outsw::@return +(signed word) outsw::sw +(signed word) outsw::sw#0 +(signed word) outsw::sw#1 +(signed word) outsw::sw#2 +(signed word) outsw::sw#3 +(signed word) outsw::sw#4 +(signed word) outsw::sw#5 +(void()) outw((word) outw::w) +(byte~) outw::$0 +(byte~) outw::$1 +(number~) outw::$10 +(byte~) outw::$3 +(number~) outw::$4 +(byte~) outw::$6 +(byte~) outw::$7 +(byte~) outw::$9 +(label) outw::@1 +(label) outw::@2 +(label) outw::@3 +(label) outw::@4 +(label) outw::@return +(word) outw::w +(word) outw::w#0 +(word) outw::w#1 +(word) outw::w#2 +(word) outw::w#3 +(word) outw::w#4 +(word) outw::w#5 + +Adding number conversion cast (snumber) 0 in (bool~) outsw::$0 ← (signed word) outsw::sw#2 < (number) 0 +Adding number conversion cast (unumber) 4 in (byte~) outw::$1 ← (byte~) outw::$0 << (number) 4 +Adding number conversion cast (unumber) $f in (number~) outw::$4 ← (byte~) outw::$3 & (number) $f +Adding number conversion cast (unumber) outw::$4 in (number~) outw::$4 ← (byte~) outw::$3 & (unumber)(number) $f +Adding number conversion cast (unumber) 4 in (byte~) outw::$7 ← (byte~) outw::$6 << (number) 4 +Adding number conversion cast (unumber) $f in (number~) outw::$10 ← (byte~) outw::$9 & (number) $f +Adding number conversion cast (unumber) outw::$10 in (number~) outw::$10 ← (byte~) outw::$9 & (unumber)(number) $f +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (word~) outsw::$2 ← (word)(signed word) outsw::sw#3 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast 4 +Simplifying constant integer cast $f +Simplifying constant integer cast 4 +Simplifying constant integer cast $f +Successful SSA optimization PassNCastSimplification +Finalized signed number type (signed byte) 0 +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) $f +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) $f +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in (unumber~) outw::$4 ← (byte~) outw::$3 & (byte) $f +Inferred type updated to byte in (unumber~) outw::$10 ← (byte~) outw::$9 & (byte) $f +Inversing boolean not [26] (bool~) outsw::$1 ← (signed word) outsw::sw#2 >= (signed byte) 0 from [25] (bool~) outsw::$0 ← (signed word) outsw::sw#2 < (signed byte) 0 +Successful SSA optimization Pass2UnaryNotSimplification +Alias main::sw#2 = main::sw#3 +Alias idx#1 = idx#15 idx#36 +Alias main::w#2 = main::w#3 +Alias idx#16 = idx#2 idx#17 idx#3 +Alias outw::w#1 = outsw::$2 +Alias idx#18 = idx#4 idx#20 idx#6 +Alias idx#32 = idx#37 +Alias outsw::sw#2 = outsw::sw#5 outsw::sw#4 +Alias idx#19 = idx#5 +Alias outsw::sw#1 = outsw::$5 +Alias outw::w#2 = outw::w#3 outw::w#4 outw::w#5 +Alias idx#21 = idx#7 +Alias idx#22 = idx#8 +Alias idx#23 = idx#9 +Alias idx#10 = idx#24 idx#25 idx#11 +Alias idx#12 = idx#27 idx#13 +Alias idx#0 = idx#34 +Alias idx#14 = idx#28 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (byte) idx#35 (byte) idx#0 +Identical Phi Values (byte) idx#1 (byte) idx#18 +Identical Phi Values (byte) idx#16 (byte) idx#10 +Identical Phi Values (signed word) outsw::sw#2 (signed word) outsw::sw#0 +Identical Phi Values (byte) idx#32 (byte) idx#29 +Identical Phi Values (byte) idx#18 (byte) idx#10 +Identical Phi Values (byte) idx#19 (byte) idx#12 +Identical Phi Values (byte) idx#21 (byte) idx#12 +Identical Phi Values (byte) idx#22 (byte) idx#12 +Identical Phi Values (byte) idx#23 (byte) idx#12 +Identical Phi Values (byte) idx#10 (byte) idx#12 +Identical Phi Values (byte) idx#14 (byte) idx#16 +Successful SSA optimization Pass2IdenticalPhiElimination +Identical Phi Values (byte) idx#30 (byte) idx#12 +Successful SSA optimization Pass2IdenticalPhiElimination +Simple Condition (bool~) main::$1 [9] if((signed word) main::sw#1!=rangelast(-$14,$13)) goto main::@1 +Simple Condition (bool~) main::$3 [17] if((word) main::w#1!=rangelast(0,$27)) goto main::@3 +Simple Condition (bool~) outsw::$1 [21] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) idx#0 = 0 +Constant (const signed word) main::sw#0 = -$14 +Constant (const word) main::w#0 = 0 +Constant (const byte) out::c#0 = '-' +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [7] main::sw#1 ← ++ main::sw#2 to ++ +Resolved ranged comparison value [9] if(main::sw#1!=rangelast(-$14,$13)) goto main::@1 to (number) $14 +Resolved ranged next value [15] main::w#1 ← ++ main::w#2 to ++ +Resolved ranged comparison value [17] if(main::w#1!=rangelast(0,$27)) goto main::@3 to (number) $28 +Adding number conversion cast (snumber) $14 in if((signed word) main::sw#1!=(number) $14) goto main::@1 +Adding number conversion cast (unumber) $28 in if((word) main::w#1!=(number) $28) goto main::@3 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast $14 +Simplifying constant integer cast $28 +Successful SSA optimization PassNCastSimplification +Finalized signed number type (signed byte) $14 +Finalized unsigned number type (byte) $28 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inlining constant with var siblings (const signed word) main::sw#0 +Inlining constant with var siblings (const word) main::w#0 +Inlining constant with var siblings (const byte) out::c#0 +Inlining constant with var siblings (const byte) idx#0 +Constant inlined out::c#0 = (byte) '-' +Constant inlined idx#0 = (byte) 0 +Constant inlined main::w#0 = (word) 0 +Constant inlined main::sw#0 = (signed word) -$14 +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@7(between main::@5 and main::@1) +Added new block during phi lifting main::@8(between main::@6 and main::@3) +Added new block during phi lifting outsw::@5(between outsw and outsw::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @4 +Adding NOP phi() at start of @5 +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 outw::@4 +Adding NOP phi() at start of outsw::@3 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to outsw:8 outw:16 +Calls in [outw] to out:29 out:35 out:41 out:47 +Calls in [outsw] to out:56 outw:64 + +Created 9 initial phi equivalence classes +Coalesced [14] outw::w#6 ← outw::w#0 +Coalesced [15] idx#41 ← idx#12 +Coalesced [20] main::w#4 ← main::w#1 +Coalesced [21] main::sw#4 ← main::sw#1 +Coalesced [22] idx#38 ← idx#12 +Coalesced [27] idx#44 ← idx#33 +Coalesced [28] out::c#6 ← out::c#1 +Coalesced (already) [33] idx#45 ← idx#12 +Coalesced [34] out::c#7 ← out::c#2 +Coalesced (already) [39] idx#46 ← idx#12 +Coalesced [40] out::c#8 ← out::c#3 +Coalesced (already) [45] idx#47 ← idx#12 +Coalesced [46] out::c#9 ← out::c#4 +Coalesced (already) [55] idx#43 ← idx#29 +Coalesced [58] outsw::sw#7 ← outsw::sw#1 +Coalesced [59] idx#40 ← idx#12 +Coalesced [62] outw::w#7 ← outw::w#1 +Coalesced (already) [63] idx#42 ← idx#31 +Coalesced [67] outsw::sw#6 ← outsw::sw#0 +Coalesced (already) [68] idx#39 ← idx#29 +Coalesced down to 6 phi equivalence classes +Culled Empty Block (label) @5 +Culled Empty Block (label) main::@2 +Culled Empty Block (label) main::@8 +Culled Empty Block (label) main::@7 +Culled Empty Block (label) outw::@4 +Culled Empty Block (label) outsw::@3 +Culled Empty Block (label) outsw::@5 +Renumbering block @4 to @1 +Renumbering block main::@3 to main::@2 +Renumbering block main::@5 to main::@3 +Renumbering block main::@6 to main::@4 +Renumbering block outsw::@4 to outsw::@3 +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 outsw::@2 + +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() + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (byte) idx#29 ← phi( main/(byte) 0 main::@3/(byte) idx#12 ) + [5] (signed word) main::sw#2 ← phi( main/(signed word) -$14 main::@3/(signed word) main::sw#1 ) + [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 + [7] call outsw + to:main::@3 +main::@3: scope:[main] from main::@1 + [8] (signed word) main::sw#1 ← ++ (signed word) main::sw#2 + [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@3 main::@4 + [10] (word) main::w#2 ← phi( main::@3/(word) 0 main::@4/(word) main::w#1 ) + [11] (word) outw::w#0 ← (word) main::w#2 + [12] call outw + to:main::@4 +main::@4: scope:[main] from main::@2 + [13] (word) main::w#1 ← ++ (word) main::w#2 + [14] if((word) main::w#1!=(byte) $28) goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@4 + [15] return + to:@return + +(void()) outw((word) outw::w) +outw: scope:[outw] from main::@2 outsw::@1 + [16] (byte) idx#33 ← phi( main::@2/(byte) idx#12 outsw::@1/(byte) idx#31 ) + [16] (word) outw::w#2 ← phi( main::@2/(word) outw::w#0 outsw::@1/(word) outw::w#1 ) + [17] (byte~) outw::$0 ← > (word) outw::w#2 + [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 + [19] (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) + [20] call out + to:outw::@1 +outw::@1: scope:[outw] from outw + [21] (byte~) outw::$3 ← > (word) outw::w#2 + [22] (byte~) outw::$4 ← (byte~) outw::$3 & (byte) $f + [23] (byte) out::c#2 ← *((const byte*) HEXTAB + (byte~) outw::$4) + [24] call out + to:outw::@2 +outw::@2: scope:[outw] from outw::@1 + [25] (byte~) outw::$6 ← < (word) outw::w#2 + [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 + [27] (byte) out::c#3 ← *((const byte*) HEXTAB + (byte~) outw::$7) + [28] call out + to:outw::@3 +outw::@3: scope:[outw] from outw::@2 + [29] (byte~) outw::$9 ← < (word) outw::w#2 + [30] (byte~) outw::$10 ← (byte~) outw::$9 & (byte) $f + [31] (byte) out::c#4 ← *((const byte*) HEXTAB + (byte~) outw::$10) + [32] call out + to:outw::@return +outw::@return: scope:[outw] from outw::@3 + [33] return + to:@return + +(void()) out((byte) out::c) +out: scope:[out] from outsw::@2 outw outw::@1 outw::@2 outw::@3 + [34] (byte) out::c#5 ← phi( outsw::@2/(byte) '-' outw/(byte) out::c#1 outw::@1/(byte) out::c#2 outw::@2/(byte) out::c#3 outw::@3/(byte) out::c#4 ) + [34] (byte) idx#26 ← phi( outsw::@2/(byte) idx#29 outw/(byte) idx#33 outw::@1/(byte) idx#12 outw::@2/(byte) idx#12 outw::@3/(byte) idx#12 ) + [35] (byte) idx#12 ← ++ (byte) idx#26 + [36] *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 + to:out::@return +out::@return: scope:[out] from out + [37] return + to:@return + +(void()) outsw((signed word) outsw::sw) +outsw: scope:[outsw] from main::@1 + [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 + to:outsw::@2 +outsw::@2: scope:[outsw] from outsw + [39] phi() + [40] call out + to:outsw::@3 +outsw::@3: scope:[outsw] from outsw::@2 + [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 + to:outsw::@1 +outsw::@1: scope:[outsw] from outsw outsw::@3 + [42] (byte) idx#31 ← phi( outsw/(byte) idx#29 outsw::@3/(byte) idx#12 ) + [42] (signed word) outsw::sw#3 ← phi( outsw/(signed word) outsw::sw#0 outsw::@3/(signed word) outsw::sw#1 ) + [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 + [44] call outw + to:outsw::@return +outsw::@return: scope:[outsw] from outsw::@1 + [45] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) idx +(byte) idx#12 7972.689655172414 +(byte) idx#26 141006.0 +(byte) idx#29 525.75 +(byte) idx#31 1501.5 +(byte) idx#33 2775.75 +(void()) main() +(signed word) main::sw +(signed word) main::sw#1 151.5 +(signed word) main::sw#2 101.0 +(word) main::w +(word) main::w#1 151.5 +(word) main::w#2 101.0 +(void()) out((byte) out::c) +(byte) out::c +(byte) out::c#1 20002.0 +(byte) out::c#2 20002.0 +(byte) out::c#3 20002.0 +(byte) out::c#4 20002.0 +(byte) out::c#5 70002.5 +(void()) outsw((signed word) outsw::sw) +(signed word) outsw::sw +(signed word) outsw::sw#0 776.0 +(signed word) outsw::sw#1 2002.0 +(signed word) outsw::sw#3 2002.0 +(void()) outw((word) outw::w) +(byte~) outw::$0 20002.0 +(byte~) outw::$1 20002.0 +(byte~) outw::$10 20002.0 +(byte~) outw::$3 20002.0 +(byte~) outw::$4 20002.0 +(byte~) outw::$6 20002.0 +(byte~) outw::$7 20002.0 +(byte~) outw::$9 20002.0 +(word) outw::w +(word) outw::w#0 202.0 +(word) outw::w#1 2002.0 +(word) outw::w#2 3162.0 + +Initial phi equivalence classes +[ main::sw#2 main::sw#1 ] +[ main::w#2 main::w#1 ] +[ outw::w#2 outw::w#0 outw::w#1 ] +[ idx#26 idx#33 idx#29 idx#12 idx#31 ] +[ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +[ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +Added variable outw::$0 to live range equivalence class [ outw::$0 ] +Added variable outw::$1 to live range equivalence class [ outw::$1 ] +Added variable outw::$3 to live range equivalence class [ outw::$3 ] +Added variable outw::$4 to live range equivalence class [ outw::$4 ] +Added variable outw::$6 to live range equivalence class [ outw::$6 ] +Added variable outw::$7 to live range equivalence class [ outw::$7 ] +Added variable outw::$9 to live range equivalence class [ outw::$9 ] +Added variable outw::$10 to live range equivalence class [ outw::$10 ] +Complete equivalence classes +[ main::sw#2 main::sw#1 ] +[ main::w#2 main::w#1 ] +[ outw::w#2 outw::w#0 outw::w#1 ] +[ idx#26 idx#33 idx#29 idx#12 idx#31 ] +[ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +[ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +[ outw::$0 ] +[ outw::$1 ] +[ outw::$3 ] +[ outw::$4 ] +[ outw::$6 ] +[ outw::$7 ] +[ outw::$9 ] +[ outw::$10 ] +Allocated zp[2]:2 [ main::sw#2 main::sw#1 ] +Allocated zp[2]:4 [ main::w#2 main::w#1 ] +Allocated zp[2]:6 [ outw::w#2 outw::w#0 outw::w#1 ] +Allocated zp[1]:8 [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +Allocated zp[1]:9 [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +Allocated zp[2]:10 [ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +Allocated zp[1]:12 [ outw::$0 ] +Allocated zp[1]:13 [ outw::$1 ] +Allocated zp[1]:14 [ outw::$3 ] +Allocated zp[1]:15 [ outw::$4 ] +Allocated zp[1]:16 [ outw::$6 ] +Allocated zp[1]:17 [ outw::$7 ] +Allocated zp[1]:18 [ outw::$9 ] +Allocated zp[1]:19 [ outw::$10 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test effective live range and register allocation +// Here outsw::sw and outw::w should have the same allocation + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 8 + // @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 sw = 2 + .label w = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) idx#29 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [5] phi (signed word) main::sw#2 = (signed word) -$14 [phi:main->main::@1#1] -- vwsz1=vwsc1 + lda #<-$14 + sta.z sw + lda #>-$14 + sta.z sw+1 + jmp __b1 + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + __b1_from___b3: + // [5] phi (byte) idx#29 = (byte) idx#12 [phi:main::@3->main::@1#0] -- register_copy + // [5] phi (signed word) main::sw#2 = (signed word) main::sw#1 [phi:main::@3->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 -- vwsz1=vwsz2 + lda.z sw + sta.z outsw.sw + lda.z sw+1 + sta.z outsw.sw+1 + // [7] call outsw + jsr outsw + jmp __b3 + // main::@3 + __b3: + // [8] (signed word) main::sw#1 ← ++ (signed word) main::sw#2 -- vwsz1=_inc_vwsz1 + inc.z sw + bne !+ + inc.z sw+1 + !: + // [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 -- vwsz1_neq_vwuc1_then_la1 + lda.z sw+1 + cmp #>$14 + bne __b1_from___b3 + lda.z sw + cmp #<$14 + bne __b1_from___b3 + // [10] phi from main::@3 to main::@2 [phi:main::@3->main::@2] + __b2_from___b3: + // [10] phi (word) main::w#2 = (word) 0 [phi:main::@3->main::@2#0] -- vwuz1=vwuc1 + lda #<0 + sta.z w + lda #>0 + sta.z w+1 + jmp __b2 + // [10] phi from main::@4 to main::@2 [phi:main::@4->main::@2] + __b2_from___b4: + // [10] phi (word) main::w#2 = (word) main::w#1 [phi:main::@4->main::@2#0] -- register_copy + jmp __b2 + // main::@2 + __b2: + // [11] (word) outw::w#0 ← (word) main::w#2 -- vwuz1=vwuz2 + lda.z w + sta.z outw.w + lda.z w+1 + sta.z outw.w+1 + // [12] call outw + // [16] phi from main::@2 to outw [phi:main::@2->outw] + outw_from___b2: + // [16] phi (byte) idx#33 = (byte) idx#12 [phi:main::@2->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#0 [phi:main::@2->outw#1] -- register_copy + jsr outw + jmp __b4 + // main::@4 + __b4: + // [13] (word) main::w#1 ← ++ (word) main::w#2 -- vwuz1=_inc_vwuz1 + inc.z w + bne !+ + inc.z w+1 + !: + // [14] if((word) main::w#1!=(byte) $28) goto main::@2 -- vwuz1_neq_vwuc1_then_la1 + lda.z w+1 + cmp #>$28 + bne __b2_from___b4 + lda.z w + cmp #<$28 + bne __b2_from___b4 + jmp __breturn + // main::@return + __breturn: + // [15] return + rts +} + // outw +// outw(word zp(6) w) +outw: { + .label __0 = $c + .label __1 = $d + .label __3 = $e + .label __4 = $f + .label __6 = $10 + .label __7 = $11 + .label __9 = $12 + .label __10 = $13 + .label w = 6 + // [17] (byte~) outw::$0 ← > (word) outw::w#2 -- vbuz1=_hi_vwuz2 + lda.z w+1 + sta.z __0 + // [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 -- vbuz1=vbuz2_rol_4 + lda.z __0 + asl + asl + asl + asl + sta.z __1 + // [19] (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __1 + lda HEXTAB,y + sta.z out.c + // [20] call out + // [34] phi from outw to out [phi:outw->out] + out_from_outw: + // [34] phi (byte) out::c#5 = (byte) out::c#1 [phi:outw->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#33 [phi:outw->out#1] -- register_copy + jsr out + jmp __b1 + // outw::@1 + __b1: + // [21] (byte~) outw::$3 ← > (word) outw::w#2 -- vbuz1=_hi_vwuz2 + lda.z w+1 + sta.z __3 + // [22] (byte~) outw::$4 ← (byte~) outw::$3 & (byte) $f -- vbuz1=vbuz2_band_vbuc1 + lda #$f + and.z __3 + sta.z __4 + // [23] (byte) out::c#2 ← *((const byte*) HEXTAB + (byte~) outw::$4) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __4 + lda HEXTAB,y + sta.z out.c + // [24] call out + // [34] phi from outw::@1 to out [phi:outw::@1->out] + out_from___b1: + // [34] phi (byte) out::c#5 = (byte) out::c#2 [phi:outw::@1->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@1->out#1] -- register_copy + jsr out + jmp __b2 + // outw::@2 + __b2: + // [25] (byte~) outw::$6 ← < (word) outw::w#2 -- vbuz1=_lo_vwuz2 + lda.z w + sta.z __6 + // [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 -- vbuz1=vbuz2_rol_4 + lda.z __6 + asl + asl + asl + asl + sta.z __7 + // [27] (byte) out::c#3 ← *((const byte*) HEXTAB + (byte~) outw::$7) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __7 + lda HEXTAB,y + sta.z out.c + // [28] call out + // [34] phi from outw::@2 to out [phi:outw::@2->out] + out_from___b2: + // [34] phi (byte) out::c#5 = (byte) out::c#3 [phi:outw::@2->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@2->out#1] -- register_copy + jsr out + jmp __b3 + // outw::@3 + __b3: + // [29] (byte~) outw::$9 ← < (word) outw::w#2 -- vbuz1=_lo_vwuz2 + lda.z w + sta.z __9 + // [30] (byte~) outw::$10 ← (byte~) outw::$9 & (byte) $f -- vbuz1=vbuz2_band_vbuc1 + lda #$f + and.z __9 + sta.z __10 + // [31] (byte) out::c#4 ← *((const byte*) HEXTAB + (byte~) outw::$10) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __10 + lda HEXTAB,y + sta.z out.c + // [32] call out + // [34] phi from outw::@3 to out [phi:outw::@3->out] + out_from___b3: + // [34] phi (byte) out::c#5 = (byte) out::c#4 [phi:outw::@3->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@3->out#1] -- register_copy + jsr out + jmp __breturn + // outw::@return + __breturn: + // [33] return + rts +} + // out +// out(byte zp(9) c) +out: { + .label c = 9 + // [35] (byte) idx#12 ← ++ (byte) idx#26 -- vbuz1=_inc_vbuz1 + inc.z idx + // [36] *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z c + ldy.z idx + sta SCREEN,y + jmp __breturn + // out::@return + __breturn: + // [37] return + rts +} + // outsw +// outsw(signed word zp($a) sw) +outsw: { + .label sw = $a + // [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 -- vwsz1_ge_0_then_la1 + lda.z sw+1 + bpl __b1_from_outsw + // [39] phi from outsw to outsw::@2 [phi:outsw->outsw::@2] + __b2_from_outsw: + jmp __b2 + // outsw::@2 + __b2: + // [40] call out + // [34] phi from outsw::@2 to out [phi:outsw::@2->out] + out_from___b2: + // [34] phi (byte) out::c#5 = (byte) '-' [phi:outsw::@2->out#0] -- vbuz1=vbuc1 + lda #'-' + sta.z out.c + // [34] phi (byte) idx#26 = (byte) idx#29 [phi:outsw::@2->out#1] -- register_copy + jsr out + jmp __b3 + // outsw::@3 + __b3: + // [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 -- vwsz1=_neg_vwsz1 + sec + lda #0 + sbc.z sw + sta.z sw + lda #0 + sbc.z sw+1 + sta.z sw+1 + // [42] phi from outsw outsw::@3 to outsw::@1 [phi:outsw/outsw::@3->outsw::@1] + __b1_from_outsw: + __b1_from___b3: + // [42] phi (byte) idx#31 = (byte) idx#29 [phi:outsw/outsw::@3->outsw::@1#0] -- register_copy + // [42] phi (signed word) outsw::sw#3 = (signed word) outsw::sw#0 [phi:outsw/outsw::@3->outsw::@1#1] -- register_copy + jmp __b1 + // outsw::@1 + __b1: + // [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 -- vwuz1=vwuz2 + lda.z sw + sta.z outw.w + lda.z sw+1 + sta.z outw.w+1 + // [44] call outw + // [16] phi from outsw::@1 to outw [phi:outsw::@1->outw] + outw_from___b1: + // [16] phi (byte) idx#33 = (byte) idx#31 [phi:outsw::@1->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#1 [phi:outsw::@1->outw#1] -- register_copy + jsr outw + jmp __breturn + // outsw::@return + __breturn: + // [45] return + rts +} + // File Data + HEXTAB: .text "0123456789abcdef" + .byte 0 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 [ main::sw#2 idx#29 outsw::sw#0 ] ( main:2 [ main::sw#2 idx#29 outsw::sw#0 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +Statement [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 [ main::sw#1 idx#12 ] ( main:2 [ main::sw#1 idx#12 ] { } ) always clobbers reg byte a +Statement [11] (word) outw::w#0 ← (word) main::w#2 [ idx#12 main::w#2 outw::w#0 ] ( main:2 [ idx#12 main::w#2 outw::w#0 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 } } ) always clobbers reg byte a +Statement [14] if((word) main::w#1!=(byte) $28) goto main::@2 [ idx#12 main::w#1 ] ( main:2 [ idx#12 main::w#1 ] { } ) always clobbers reg byte a +Statement [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 [ outw::w#2 idx#33 outw::$1 ] ( main:2::outw:12 [ main::w#2 outw::w#2 idx#33 outw::$1 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 idx#26 } { out::c#1 = out::c#5 } } main:2::outsw:7::outw:44 [ main::sw#2 outw::w#2 idx#33 outw::$1 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#26 = idx#33 idx#31 } { out::c#1 = out::c#5 } } ) always clobbers reg byte a +Statement [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 [ idx#12 outw::w#2 outw::$7 ] ( main:2::outw:12 [ main::w#2 idx#12 outw::w#2 outw::$7 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 idx#26 } { out::c#3 = out::c#5 } } main:2::outsw:7::outw:44 [ main::sw#2 idx#12 outw::w#2 outw::$7 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#31 = idx#33 } { idx#12 = idx#26 } { out::c#3 = out::c#5 } } ) always clobbers reg byte a +Statement [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 [ idx#29 outsw::sw#0 ] ( main:2::outsw:7 [ main::sw#2 idx#29 outsw::sw#0 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Statement [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 [ idx#12 outsw::sw#1 ] ( main:2::outsw:7 [ main::sw#2 idx#12 outsw::sw#1 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Statement [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 [ outw::w#1 idx#31 ] ( main:2::outsw:7 [ main::sw#2 outw::w#1 idx#31 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#31 = idx#33 } } ) always clobbers reg byte a +Statement [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 [ main::sw#2 idx#29 outsw::sw#0 ] ( main:2 [ main::sw#2 idx#29 outsw::sw#0 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Statement [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 [ main::sw#1 idx#12 ] ( main:2 [ main::sw#1 idx#12 ] { } ) always clobbers reg byte a +Statement [11] (word) outw::w#0 ← (word) main::w#2 [ idx#12 main::w#2 outw::w#0 ] ( main:2 [ idx#12 main::w#2 outw::w#0 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 } } ) always clobbers reg byte a +Statement [14] if((word) main::w#1!=(byte) $28) goto main::@2 [ idx#12 main::w#1 ] ( main:2 [ idx#12 main::w#1 ] { } ) always clobbers reg byte a +Statement [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 [ outw::w#2 idx#33 outw::$1 ] ( main:2::outw:12 [ main::w#2 outw::w#2 idx#33 outw::$1 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 idx#26 } { out::c#1 = out::c#5 } } main:2::outsw:7::outw:44 [ main::sw#2 outw::w#2 idx#33 outw::$1 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#26 = idx#33 idx#31 } { out::c#1 = out::c#5 } } ) always clobbers reg byte a +Statement [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 [ idx#12 outw::w#2 outw::$7 ] ( main:2::outw:12 [ main::w#2 idx#12 outw::w#2 outw::$7 ] { { outw::w#0 = outw::w#2 main::w#2 } { idx#12 = idx#33 idx#26 } { out::c#3 = out::c#5 } } main:2::outsw:7::outw:44 [ main::sw#2 idx#12 outw::w#2 outw::$7 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#31 = idx#33 } { idx#12 = idx#26 } { out::c#3 = out::c#5 } } ) always clobbers reg byte a +Statement [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 [ idx#29 outsw::sw#0 ] ( main:2::outsw:7 [ main::sw#2 idx#29 outsw::sw#0 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Statement [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 [ idx#12 outsw::sw#1 ] ( main:2::outsw:7 [ main::sw#2 idx#12 outsw::sw#1 ] { { outsw::sw#0 = main::sw#2 } } ) always clobbers reg byte a +Statement [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 [ outw::w#1 idx#31 ] ( main:2::outsw:7 [ main::sw#2 outw::w#1 idx#31 ] { { outsw::sw#0 = main::sw#2 } { outw::w#1 = outw::w#2 } { idx#31 = idx#33 } } ) always clobbers reg byte a +Potential registers zp[2]:2 [ main::sw#2 main::sw#1 ] : zp[2]:2 , +Potential registers zp[2]:4 [ main::w#2 main::w#1 ] : zp[2]:4 , +Potential registers zp[2]:6 [ outw::w#2 outw::w#0 outw::w#1 ] : zp[2]:6 , +Potential registers zp[1]:8 [ idx#26 idx#33 idx#29 idx#12 idx#31 ] : zp[1]:8 , reg byte x , reg byte y , +Potential registers zp[1]:9 [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[2]:10 [ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] : zp[2]:10 , +Potential registers zp[1]:12 [ outw::$0 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:13 [ outw::$1 ] : zp[1]:13 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:14 [ outw::$3 ] : zp[1]:14 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:15 [ outw::$4 ] : zp[1]:15 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:16 [ outw::$6 ] : zp[1]:16 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:17 [ outw::$7 ] : zp[1]:17 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:18 [ outw::$9 ] : zp[1]:18 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:19 [ outw::$10 ] : zp[1]:19 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [outw] 20,002: zp[1]:12 [ outw::$0 ] 20,002: zp[1]:13 [ outw::$1 ] 20,002: zp[1]:14 [ outw::$3 ] 20,002: zp[1]:15 [ outw::$4 ] 20,002: zp[1]:16 [ outw::$6 ] 20,002: zp[1]:17 [ outw::$7 ] 20,002: zp[1]:18 [ outw::$9 ] 20,002: zp[1]:19 [ outw::$10 ] 5,366: zp[2]:6 [ outw::w#2 outw::w#0 outw::w#1 ] +Uplift Scope [] 153,781.69: zp[1]:8 [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +Uplift Scope [out] 150,010.5: zp[1]:9 [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +Uplift Scope [outsw] 4,780: zp[2]:10 [ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +Uplift Scope [main] 252.5: zp[2]:2 [ main::sw#2 main::sw#1 ] 252.5: zp[2]:4 [ main::w#2 main::w#1 ] + +Uplifting [outw] best 1532 combination reg byte a [ outw::$0 ] reg byte a [ outw::$1 ] reg byte a [ outw::$3 ] reg byte a [ outw::$4 ] zp[1]:16 [ outw::$6 ] zp[1]:17 [ outw::$7 ] zp[1]:18 [ outw::$9 ] zp[1]:19 [ outw::$10 ] zp[2]:6 [ outw::w#2 outw::w#0 outw::w#1 ] +Limited combination testing to 100 combinations of 65536 possible. +Uplifting [] best 1496 combination reg byte x [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +Uplifting [out] best 1478 combination reg byte a [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +Uplifting [outsw] best 1478 combination zp[2]:10 [ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +Uplifting [main] best 1478 combination zp[2]:2 [ main::sw#2 main::sw#1 ] zp[2]:4 [ main::w#2 main::w#1 ] +Attempting to uplift remaining variables inzp[1]:16 [ outw::$6 ] +Uplifting [outw] best 1472 combination reg byte a [ outw::$6 ] +Attempting to uplift remaining variables inzp[1]:17 [ outw::$7 ] +Uplifting [outw] best 1468 combination reg byte a [ outw::$7 ] +Attempting to uplift remaining variables inzp[1]:18 [ outw::$9 ] +Uplifting [outw] best 1462 combination reg byte a [ outw::$9 ] +Attempting to uplift remaining variables inzp[1]:19 [ outw::$10 ] +Uplifting [outw] best 1458 combination reg byte a [ outw::$10 ] +Coalescing zero page register [ zp[2]:4 [ main::w#2 main::w#1 ] ] with [ zp[2]:6 [ outw::w#2 outw::w#0 outw::w#1 ] ] - score: 1 +Coalescing zero page register [ zp[2]:4 [ main::w#2 main::w#1 outw::w#2 outw::w#0 outw::w#1 ] ] with [ zp[2]:10 [ outsw::sw#3 outsw::sw#0 outsw::sw#1 ] ] - score: 1 + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test effective live range and register allocation +// Here outsw::sw and outw::w should have the same allocation + // 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 sw = 2 + .label w = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) idx#29 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [5] phi (signed word) main::sw#2 = (signed word) -$14 [phi:main->main::@1#1] -- vwsz1=vwsc1 + lda #<-$14 + sta.z sw + lda #>-$14 + sta.z sw+1 + jmp __b1 + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + __b1_from___b3: + // [5] phi (byte) idx#29 = (byte) idx#12 [phi:main::@3->main::@1#0] -- register_copy + // [5] phi (signed word) main::sw#2 = (signed word) main::sw#1 [phi:main::@3->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 -- vwsz1=vwsz2 + lda.z sw + sta.z outsw.sw + lda.z sw+1 + sta.z outsw.sw+1 + // [7] call outsw + jsr outsw + jmp __b3 + // main::@3 + __b3: + // [8] (signed word) main::sw#1 ← ++ (signed word) main::sw#2 -- vwsz1=_inc_vwsz1 + inc.z sw + bne !+ + inc.z sw+1 + !: + // [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 -- vwsz1_neq_vwuc1_then_la1 + lda.z sw+1 + cmp #>$14 + bne __b1_from___b3 + lda.z sw + cmp #<$14 + bne __b1_from___b3 + // [10] phi from main::@3 to main::@2 [phi:main::@3->main::@2] + __b2_from___b3: + // [10] phi (word) main::w#2 = (word) 0 [phi:main::@3->main::@2#0] -- vwuz1=vwuc1 + lda #<0 + sta.z w + lda #>0 + sta.z w+1 + jmp __b2 + // [10] phi from main::@4 to main::@2 [phi:main::@4->main::@2] + __b2_from___b4: + // [10] phi (word) main::w#2 = (word) main::w#1 [phi:main::@4->main::@2#0] -- register_copy + jmp __b2 + // main::@2 + __b2: + // [11] (word) outw::w#0 ← (word) main::w#2 + // [12] call outw + // [16] phi from main::@2 to outw [phi:main::@2->outw] + outw_from___b2: + // [16] phi (byte) idx#33 = (byte) idx#12 [phi:main::@2->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#0 [phi:main::@2->outw#1] -- register_copy + jsr outw + jmp __b4 + // main::@4 + __b4: + // [13] (word) main::w#1 ← ++ (word) main::w#2 -- vwuz1=_inc_vwuz1 + inc.z w + bne !+ + inc.z w+1 + !: + // [14] if((word) main::w#1!=(byte) $28) goto main::@2 -- vwuz1_neq_vwuc1_then_la1 + lda.z w+1 + cmp #>$28 + bne __b2_from___b4 + lda.z w + cmp #<$28 + bne __b2_from___b4 + jmp __breturn + // main::@return + __breturn: + // [15] return + rts +} + // outw +// outw(word zp(4) w) +outw: { + .label w = 4 + // [17] (byte~) outw::$0 ← > (word) outw::w#2 -- vbuaa=_hi_vwuz1 + lda.z w+1 + // [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 -- vbuaa=vbuaa_rol_4 + asl + asl + asl + asl + // [19] (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [20] call out + // [34] phi from outw to out [phi:outw->out] + out_from_outw: + // [34] phi (byte) out::c#5 = (byte) out::c#1 [phi:outw->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#33 [phi:outw->out#1] -- register_copy + jsr out + jmp __b1 + // outw::@1 + __b1: + // [21] (byte~) outw::$3 ← > (word) outw::w#2 -- vbuaa=_hi_vwuz1 + lda.z w+1 + // [22] (byte~) outw::$4 ← (byte~) outw::$3 & (byte) $f -- vbuaa=vbuaa_band_vbuc1 + and #$f + // [23] (byte) out::c#2 ← *((const byte*) HEXTAB + (byte~) outw::$4) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [24] call out + // [34] phi from outw::@1 to out [phi:outw::@1->out] + out_from___b1: + // [34] phi (byte) out::c#5 = (byte) out::c#2 [phi:outw::@1->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@1->out#1] -- register_copy + jsr out + jmp __b2 + // outw::@2 + __b2: + // [25] (byte~) outw::$6 ← < (word) outw::w#2 -- vbuaa=_lo_vwuz1 + lda.z w + // [26] (byte~) outw::$7 ← (byte~) outw::$6 << (byte) 4 -- vbuaa=vbuaa_rol_4 + asl + asl + asl + asl + // [27] (byte) out::c#3 ← *((const byte*) HEXTAB + (byte~) outw::$7) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [28] call out + // [34] phi from outw::@2 to out [phi:outw::@2->out] + out_from___b2: + // [34] phi (byte) out::c#5 = (byte) out::c#3 [phi:outw::@2->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@2->out#1] -- register_copy + jsr out + jmp __b3 + // outw::@3 + __b3: + // [29] (byte~) outw::$9 ← < (word) outw::w#2 -- vbuaa=_lo_vwuz1 + lda.z w + // [30] (byte~) outw::$10 ← (byte~) outw::$9 & (byte) $f -- vbuaa=vbuaa_band_vbuc1 + and #$f + // [31] (byte) out::c#4 ← *((const byte*) HEXTAB + (byte~) outw::$10) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [32] call out + // [34] phi from outw::@3 to out [phi:outw::@3->out] + out_from___b3: + // [34] phi (byte) out::c#5 = (byte) out::c#4 [phi:outw::@3->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@3->out#1] -- register_copy + jsr out + jmp __breturn + // outw::@return + __breturn: + // [33] return + rts +} + // out +// out(byte register(A) c) +out: { + // [35] (byte) idx#12 ← ++ (byte) idx#26 -- vbuxx=_inc_vbuxx + inx + // [36] *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 -- pbuc1_derefidx_vbuxx=vbuaa + sta SCREEN,x + jmp __breturn + // out::@return + __breturn: + // [37] return + rts +} + // outsw +// outsw(signed word zp(4) sw) +outsw: { + .label sw = 4 + // [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 -- vwsz1_ge_0_then_la1 + lda.z sw+1 + bpl __b1_from_outsw + // [39] phi from outsw to outsw::@2 [phi:outsw->outsw::@2] + __b2_from_outsw: + jmp __b2 + // outsw::@2 + __b2: + // [40] call out + // [34] phi from outsw::@2 to out [phi:outsw::@2->out] + out_from___b2: + // [34] phi (byte) out::c#5 = (byte) '-' [phi:outsw::@2->out#0] -- vbuaa=vbuc1 + lda #'-' + // [34] phi (byte) idx#26 = (byte) idx#29 [phi:outsw::@2->out#1] -- register_copy + jsr out + jmp __b3 + // outsw::@3 + __b3: + // [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 -- vwsz1=_neg_vwsz1 + sec + lda #0 + sbc.z sw + sta.z sw + lda #0 + sbc.z sw+1 + sta.z sw+1 + // [42] phi from outsw outsw::@3 to outsw::@1 [phi:outsw/outsw::@3->outsw::@1] + __b1_from_outsw: + __b1_from___b3: + // [42] phi (byte) idx#31 = (byte) idx#29 [phi:outsw/outsw::@3->outsw::@1#0] -- register_copy + // [42] phi (signed word) outsw::sw#3 = (signed word) outsw::sw#0 [phi:outsw/outsw::@3->outsw::@1#1] -- register_copy + jmp __b1 + // outsw::@1 + __b1: + // [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 + // [44] call outw + // [16] phi from outsw::@1 to outw [phi:outsw::@1->outw] + outw_from___b1: + // [16] phi (byte) idx#33 = (byte) idx#31 [phi:outsw::@1->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#1 [phi:outsw::@1->outw#1] -- register_copy + jsr outw + jmp __breturn + // outsw::@return + __breturn: + // [45] return + rts +} + // File Data + HEXTAB: .text "0123456789abcdef" + .byte 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __b3 +Removing instruction jmp __b2 +Removing instruction jmp __b4 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #>0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label __b1_from___b3 with __b1 +Replacing label __b1_from___b3 with __b1 +Replacing label __b2_from___b4 with __b2 +Replacing label __b2_from___b4 with __b2 +Replacing label __b1_from_outsw with __b1 +Removing instruction __b1_from___bbegin: +Removing instruction __b1: +Removing instruction main_from___b1: +Removing instruction __bend_from___b1: +Removing instruction __b1_from___b3: +Removing instruction __b2_from___b4: +Removing instruction outw_from___b2: +Removing instruction __b2_from_outsw: +Removing instruction out_from___b2: +Removing instruction __b1_from_outsw: +Removing instruction __b1_from___b3: +Removing instruction outw_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __b1_from_main: +Removing instruction __b3: +Removing instruction __b2_from___b3: +Removing instruction __b4: +Removing instruction __breturn: +Removing instruction out_from_outw: +Removing instruction __b1: +Removing instruction out_from___b1: +Removing instruction __b2: +Removing instruction out_from___b2: +Removing instruction __b3: +Removing instruction out_from___b3: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __b2: +Removing instruction __b3: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte*) HEXTAB[] = (byte*) "0123456789abcdef" +(const byte*) SCREEN = (byte*) 1024 +(byte) idx +(byte) idx#12 reg byte x 7972.689655172414 +(byte) idx#26 reg byte x 141006.0 +(byte) idx#29 reg byte x 525.75 +(byte) idx#31 reg byte x 1501.5 +(byte) idx#33 reg byte x 2775.75 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@return +(signed word) main::sw +(signed word) main::sw#1 sw zp[2]:2 151.5 +(signed word) main::sw#2 sw zp[2]:2 101.0 +(word) main::w +(word) main::w#1 w zp[2]:4 151.5 +(word) main::w#2 w zp[2]:4 101.0 +(void()) out((byte) out::c) +(label) out::@return +(byte) out::c +(byte) out::c#1 reg byte a 20002.0 +(byte) out::c#2 reg byte a 20002.0 +(byte) out::c#3 reg byte a 20002.0 +(byte) out::c#4 reg byte a 20002.0 +(byte) out::c#5 reg byte a 70002.5 +(void()) outsw((signed word) outsw::sw) +(label) outsw::@1 +(label) outsw::@2 +(label) outsw::@3 +(label) outsw::@return +(signed word) outsw::sw +(signed word) outsw::sw#0 sw zp[2]:4 776.0 +(signed word) outsw::sw#1 sw zp[2]:4 2002.0 +(signed word) outsw::sw#3 sw zp[2]:4 2002.0 +(void()) outw((word) outw::w) +(byte~) outw::$0 reg byte a 20002.0 +(byte~) outw::$1 reg byte a 20002.0 +(byte~) outw::$10 reg byte a 20002.0 +(byte~) outw::$3 reg byte a 20002.0 +(byte~) outw::$4 reg byte a 20002.0 +(byte~) outw::$6 reg byte a 20002.0 +(byte~) outw::$7 reg byte a 20002.0 +(byte~) outw::$9 reg byte a 20002.0 +(label) outw::@1 +(label) outw::@2 +(label) outw::@3 +(label) outw::@return +(word) outw::w +(word) outw::w#0 w zp[2]:4 202.0 +(word) outw::w#1 w zp[2]:4 2002.0 +(word) outw::w#2 w zp[2]:4 3162.0 + +zp[2]:2 [ main::sw#2 main::sw#1 ] +zp[2]:4 [ main::w#2 main::w#1 outw::w#2 outw::w#0 outw::w#1 outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +reg byte x [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +reg byte a [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +reg byte a [ outw::$0 ] +reg byte a [ outw::$1 ] +reg byte a [ outw::$3 ] +reg byte a [ outw::$4 ] +reg byte a [ outw::$6 ] +reg byte a [ outw::$7 ] +reg byte a [ outw::$9 ] +reg byte a [ outw::$10 ] + + +FINAL ASSEMBLER +Score: 1084 + + // File Comments +// Test effective live range and register allocation +// Here outsw::sw and outw::w should have the same allocation + // 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 sw = 2 + .label w = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) idx#29 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [5] phi (signed word) main::sw#2 = (signed word) -$14 [phi:main->main::@1#1] -- vwsz1=vwsc1 + lda #<-$14 + sta.z sw + lda #>-$14 + sta.z sw+1 + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + // [5] phi (byte) idx#29 = (byte) idx#12 [phi:main::@3->main::@1#0] -- register_copy + // [5] phi (signed word) main::sw#2 = (signed word) main::sw#1 [phi:main::@3->main::@1#1] -- register_copy + // main::@1 + __b1: + // outsw(sw) + // [6] (signed word) outsw::sw#0 ← (signed word) main::sw#2 -- vwsz1=vwsz2 + lda.z sw + sta.z outsw.sw + lda.z sw+1 + sta.z outsw.sw+1 + // [7] call outsw + jsr outsw + // main::@3 + // for(signed int sw: -20..19 ) + // [8] (signed word) main::sw#1 ← ++ (signed word) main::sw#2 -- vwsz1=_inc_vwsz1 + inc.z sw + bne !+ + inc.z sw+1 + !: + // [9] if((signed word) main::sw#1!=(signed byte) $14) goto main::@1 -- vwsz1_neq_vwuc1_then_la1 + lda.z sw+1 + cmp #>$14 + bne __b1 + lda.z sw + cmp #<$14 + bne __b1 + // [10] phi from main::@3 to main::@2 [phi:main::@3->main::@2] + // [10] phi (word) main::w#2 = (word) 0 [phi:main::@3->main::@2#0] -- vwuz1=vwuc1 + lda #<0 + sta.z w + sta.z w+1 + // [10] phi from main::@4 to main::@2 [phi:main::@4->main::@2] + // [10] phi (word) main::w#2 = (word) main::w#1 [phi:main::@4->main::@2#0] -- register_copy + // main::@2 + __b2: + // outw(w) + // [11] (word) outw::w#0 ← (word) main::w#2 + // [12] call outw + // [16] phi from main::@2 to outw [phi:main::@2->outw] + // [16] phi (byte) idx#33 = (byte) idx#12 [phi:main::@2->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#0 [phi:main::@2->outw#1] -- register_copy + jsr outw + // main::@4 + // for(unsigned int w: 0..39 ) + // [13] (word) main::w#1 ← ++ (word) main::w#2 -- vwuz1=_inc_vwuz1 + inc.z w + bne !+ + inc.z w+1 + !: + // [14] if((word) main::w#1!=(byte) $28) goto main::@2 -- vwuz1_neq_vwuc1_then_la1 + lda.z w+1 + cmp #>$28 + bne __b2 + lda.z w + cmp #<$28 + bne __b2 + // main::@return + // } + // [15] return + rts +} + // outw +// outw(word zp(4) w) +outw: { + .label w = 4 + // >w + // [17] (byte~) outw::$0 ← > (word) outw::w#2 -- vbuaa=_hi_vwuz1 + lda.z w+1 + // (>w)<<4 + // [18] (byte~) outw::$1 ← (byte~) outw::$0 << (byte) 4 -- vbuaa=vbuaa_rol_4 + asl + asl + asl + asl + // out(HEXTAB[(>w)<<4]) + // [19] (byte) out::c#1 ← *((const byte*) HEXTAB + (byte~) outw::$1) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [20] call out + // [34] phi from outw to out [phi:outw->out] + // [34] phi (byte) out::c#5 = (byte) out::c#1 [phi:outw->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#33 [phi:outw->out#1] -- register_copy + jsr out + // outw::@1 + // >w + // [21] (byte~) outw::$3 ← > (word) outw::w#2 -- vbuaa=_hi_vwuz1 + lda.z w+1 + // (>w)&0x0f + // [22] (byte~) outw::$4 ← (byte~) outw::$3 & (byte) $f -- vbuaa=vbuaa_band_vbuc1 + and #$f + // out(HEXTAB[(>w)&0x0f]) + // [23] (byte) out::c#2 ← *((const byte*) HEXTAB + (byte~) outw::$4) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda HEXTAB,y + // [24] call out + // [34] phi from outw::@1 to out [phi:outw::@1->out] + // [34] phi (byte) out::c#5 = (byte) out::c#2 [phi:outw::@1->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@1->out#1] -- register_copy + jsr out + // outw::@2 + // out] + // [34] phi (byte) out::c#5 = (byte) out::c#3 [phi:outw::@2->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@2->out#1] -- register_copy + jsr out + // outw::@3 + // out] + // [34] phi (byte) out::c#5 = (byte) out::c#4 [phi:outw::@3->out#0] -- register_copy + // [34] phi (byte) idx#26 = (byte) idx#12 [phi:outw::@3->out#1] -- register_copy + jsr out + // outw::@return + // } + // [33] return + rts +} + // out +// out(byte register(A) c) +out: { + // idx++; + // [35] (byte) idx#12 ← ++ (byte) idx#26 -- vbuxx=_inc_vbuxx + inx + // SCREEN[idx] = c + // [36] *((const byte*) SCREEN + (byte) idx#12) ← (byte) out::c#5 -- pbuc1_derefidx_vbuxx=vbuaa + sta SCREEN,x + // out::@return + // } + // [37] return + rts +} + // outsw +// outsw(signed word zp(4) sw) +outsw: { + .label sw = 4 + // if(sw<0) + // [38] if((signed word) outsw::sw#0>=(signed byte) 0) goto outsw::@1 -- vwsz1_ge_0_then_la1 + lda.z sw+1 + bpl __b1 + // [39] phi from outsw to outsw::@2 [phi:outsw->outsw::@2] + // outsw::@2 + // out('-') + // [40] call out + // [34] phi from outsw::@2 to out [phi:outsw::@2->out] + // [34] phi (byte) out::c#5 = (byte) '-' [phi:outsw::@2->out#0] -- vbuaa=vbuc1 + lda #'-' + // [34] phi (byte) idx#26 = (byte) idx#29 [phi:outsw::@2->out#1] -- register_copy + jsr out + // outsw::@3 + // sw = -sw + // [41] (signed word) outsw::sw#1 ← - (signed word) outsw::sw#0 -- vwsz1=_neg_vwsz1 + sec + lda #0 + sbc.z sw + sta.z sw + lda #0 + sbc.z sw+1 + sta.z sw+1 + // [42] phi from outsw outsw::@3 to outsw::@1 [phi:outsw/outsw::@3->outsw::@1] + // [42] phi (byte) idx#31 = (byte) idx#29 [phi:outsw/outsw::@3->outsw::@1#0] -- register_copy + // [42] phi (signed word) outsw::sw#3 = (signed word) outsw::sw#0 [phi:outsw/outsw::@3->outsw::@1#1] -- register_copy + // outsw::@1 + __b1: + // outw((unsigned int)sw) + // [43] (word) outw::w#1 ← (word)(signed word) outsw::sw#3 + // [44] call outw + // [16] phi from outsw::@1 to outw [phi:outsw::@1->outw] + // [16] phi (byte) idx#33 = (byte) idx#31 [phi:outsw::@1->outw#0] -- register_copy + // [16] phi (word) outw::w#2 = (word) outw::w#1 [phi:outsw::@1->outw#1] -- register_copy + jsr outw + // outsw::@return + // } + // [45] return + rts +} + // File Data + HEXTAB: .text "0123456789abcdef" + .byte 0 + diff --git a/src/test/ref/liverange-10.sym b/src/test/ref/liverange-10.sym new file mode 100644 index 000000000..07a6a9538 --- /dev/null +++ b/src/test/ref/liverange-10.sym @@ -0,0 +1,70 @@ +(label) @1 +(label) @begin +(label) @end +(const byte*) HEXTAB[] = (byte*) "0123456789abcdef" +(const byte*) SCREEN = (byte*) 1024 +(byte) idx +(byte) idx#12 reg byte x 7972.689655172414 +(byte) idx#26 reg byte x 141006.0 +(byte) idx#29 reg byte x 525.75 +(byte) idx#31 reg byte x 1501.5 +(byte) idx#33 reg byte x 2775.75 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@return +(signed word) main::sw +(signed word) main::sw#1 sw zp[2]:2 151.5 +(signed word) main::sw#2 sw zp[2]:2 101.0 +(word) main::w +(word) main::w#1 w zp[2]:4 151.5 +(word) main::w#2 w zp[2]:4 101.0 +(void()) out((byte) out::c) +(label) out::@return +(byte) out::c +(byte) out::c#1 reg byte a 20002.0 +(byte) out::c#2 reg byte a 20002.0 +(byte) out::c#3 reg byte a 20002.0 +(byte) out::c#4 reg byte a 20002.0 +(byte) out::c#5 reg byte a 70002.5 +(void()) outsw((signed word) outsw::sw) +(label) outsw::@1 +(label) outsw::@2 +(label) outsw::@3 +(label) outsw::@return +(signed word) outsw::sw +(signed word) outsw::sw#0 sw zp[2]:4 776.0 +(signed word) outsw::sw#1 sw zp[2]:4 2002.0 +(signed word) outsw::sw#3 sw zp[2]:4 2002.0 +(void()) outw((word) outw::w) +(byte~) outw::$0 reg byte a 20002.0 +(byte~) outw::$1 reg byte a 20002.0 +(byte~) outw::$10 reg byte a 20002.0 +(byte~) outw::$3 reg byte a 20002.0 +(byte~) outw::$4 reg byte a 20002.0 +(byte~) outw::$6 reg byte a 20002.0 +(byte~) outw::$7 reg byte a 20002.0 +(byte~) outw::$9 reg byte a 20002.0 +(label) outw::@1 +(label) outw::@2 +(label) outw::@3 +(label) outw::@return +(word) outw::w +(word) outw::w#0 w zp[2]:4 202.0 +(word) outw::w#1 w zp[2]:4 2002.0 +(word) outw::w#2 w zp[2]:4 3162.0 + +zp[2]:2 [ main::sw#2 main::sw#1 ] +zp[2]:4 [ main::w#2 main::w#1 outw::w#2 outw::w#0 outw::w#1 outsw::sw#3 outsw::sw#0 outsw::sw#1 ] +reg byte x [ idx#26 idx#33 idx#29 idx#12 idx#31 ] +reg byte a [ out::c#5 out::c#1 out::c#2 out::c#3 out::c#4 ] +reg byte a [ outw::$0 ] +reg byte a [ outw::$1 ] +reg byte a [ outw::$3 ] +reg byte a [ outw::$4 ] +reg byte a [ outw::$6 ] +reg byte a [ outw::$7 ] +reg byte a [ outw::$9 ] +reg byte a [ outw::$10 ]