From d9fab8eb23678ef24bd16cefc37359a5873b9d8c Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Fri, 30 Oct 2020 09:17:34 +0100 Subject: [PATCH] Fixed problem where zp_reserve is not being honoured after using __address. Closes #550 --- .../kickc/passes/Pass4MemoryCoalesce.java | 83 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/zp-reserve-coalesce-problem.c | 47 + src/test/ref/zp-reserve-coalesce-problem.asm | 173 +++ src/test/ref/zp-reserve-coalesce-problem.cfg | 95 ++ src/test/ref/zp-reserve-coalesce-problem.log | 1277 +++++++++++++++++ src/test/ref/zp-reserve-coalesce-problem.sym | 50 + 7 files changed, 1694 insertions(+), 36 deletions(-) create mode 100644 src/test/kc/zp-reserve-coalesce-problem.c create mode 100644 src/test/ref/zp-reserve-coalesce-problem.asm create mode 100644 src/test/ref/zp-reserve-coalesce-problem.cfg create mode 100644 src/test/ref/zp-reserve-coalesce-problem.log create mode 100644 src/test/ref/zp-reserve-coalesce-problem.sym diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java index 4c163ee71..c229e98fe 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4MemoryCoalesce.java @@ -146,8 +146,19 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base { // Check the both registers have the same size if(register1.getBytes() != register2.getBytes()) return false; + // check if either are in the reserved zp registers + if(register1 instanceof Registers.RegisterZpMem) { + int zp = ((Registers.RegisterZpMem) register1).getZp(); + if(program.getReservedZps().contains(zp)) + return false; + } + if(register2 instanceof Registers.RegisterZpMem) { + int zp = ((Registers.RegisterZpMem) register2).getZp(); + if(program.getReservedZps().contains(zp)) + return false; + } return true; - } +} /** * Determines if two live range equivalence classes can be coalesced without clobber. @@ -220,46 +231,46 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base { } - /** - * A pair of live range equivalence classes that are candidates for coalescing. - * The pair is unordered - meaning it is equal to the pair with the same classes in opposite order. - */ - static class LiveRangeEquivalenceClassCoalesceCandidate { - private LiveRangeEquivalenceClass ec1; - private LiveRangeEquivalenceClass ec2; - private Integer score; +/** + * A pair of live range equivalence classes that are candidates for coalescing. + * The pair is unordered - meaning it is equal to the pair with the same classes in opposite order. + */ +static class LiveRangeEquivalenceClassCoalesceCandidate { + private LiveRangeEquivalenceClass ec1; + private LiveRangeEquivalenceClass ec2; + private Integer score; - public LiveRangeEquivalenceClassCoalesceCandidate(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Integer score) { - this.ec1 = ec1; - this.ec2 = ec2; - this.score = score; - } + public LiveRangeEquivalenceClassCoalesceCandidate(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Integer score) { + this.ec1 = ec1; + this.ec2 = ec2; + this.score = score; + } - @Override - public boolean equals(Object o) { - if(this == o) return true; - if(o == null || getClass() != o.getClass()) return false; - LiveRangeEquivalenceClassCoalesceCandidate that = (LiveRangeEquivalenceClassCoalesceCandidate) o; - if(ec1.equals(that.ec1) && ec2.equals(that.ec2)) return true; - if(ec1.equals(that.ec2) && ec2.equals(that.ec1)) return true; - return false; - } + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + LiveRangeEquivalenceClassCoalesceCandidate that = (LiveRangeEquivalenceClassCoalesceCandidate) o; + if(ec1.equals(that.ec1) && ec2.equals(that.ec2)) return true; + if(ec1.equals(that.ec2) && ec2.equals(that.ec1)) return true; + return false; + } - @Override - public int hashCode() { - return ec1.hashCode() + ec2.hashCode(); - } + @Override + public int hashCode() { + return ec1.hashCode() + ec2.hashCode(); + } - public Integer getScore() { - return score; - } + public Integer getScore() { + return score; + } - public LiveRangeEquivalenceClass getEc1() { - return ec1; - } + public LiveRangeEquivalenceClass getEc1() { + return ec1; + } - public LiveRangeEquivalenceClass getEc2() { - return ec2; - } + public LiveRangeEquivalenceClass getEc2() { + return ec2; } } +} diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 8c9c47c24..72dd036aa 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -44,6 +44,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testZpReserveCoalesceProblem() throws IOException, URISyntaxException { + compileAndCompare("zp-reserve-coalesce-problem.c"); + } + @Test public void testChipsetTest() throws IOException, URISyntaxException { compileAndCompare("chipset-test.c"); diff --git a/src/test/kc/zp-reserve-coalesce-problem.c b/src/test/kc/zp-reserve-coalesce-problem.c new file mode 100644 index 000000000..ce33740c8 --- /dev/null +++ b/src/test/kc/zp-reserve-coalesce-problem.c @@ -0,0 +1,47 @@ +// Demonstrates problem where reserved ZP addresses can still be coalesced if they are explicitly __address() assigned to variables +// https://gitlab.com/camelot/kickc/-/issues/550 + +#pragma target(atarixl) +#pragma zp_reserve(0x00..0x7f) + +void main() { + benchmarkCountdownFor(); + benchmarkLandscape(); +} + +char landscapeBase[] = kickasm {{ + .fill 14, 0 + }}; + +char * const lms = 0xa000; + +void benchmarkCountdownFor() { + __address(0x41) signed char a; + __address(0x4b) signed char b; + for(a = 1; a >= 0; a--) { + for(b = 9; b >= 0; b--) { + } + } +} + +void benchmarkLandscape() { + char colHeight[14]; + + for(char z: 0..9) { + for (char i: 0..13) { colHeight[i] = landscapeBase[i]; } + for (signed char x = 39; x >= 0; x--) { + char *screenAddress = lms + x; + char start = 0; + for (signed char c = 13; c >= 0; c--) { + char uc = (char) c; + char stop = colHeight[uc]; + while (start < stop) { + *screenAddress = ((*screenAddress) & 0xf) | (uc << 4); + screenAddress += 40; + start++; + } + start = stop; + } + } + } +} diff --git a/src/test/ref/zp-reserve-coalesce-problem.asm b/src/test/ref/zp-reserve-coalesce-problem.asm new file mode 100644 index 000000000..03bad8206 --- /dev/null +++ b/src/test/ref/zp-reserve-coalesce-problem.asm @@ -0,0 +1,173 @@ +// Demonstrates problem where reserved ZP addresses can still be coalesced if they are explicitly __address() assigned to variables +// https://gitlab.com/camelot/kickc/-/issues/550 + // Atari XL/XE executable XEX file with a single segment +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="zp-reserve-coalesce-problem.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + .label lms = $a000 +.segment Code +main: { + // benchmarkCountdownFor() + jsr benchmarkCountdownFor + // benchmarkLandscape() + jsr benchmarkLandscape + // } + rts +} +benchmarkCountdownFor: { + .label a = $41 + .label b = $4b + // a + lda #0 + sta.z a + // b + sta.z b + // a = 1 + lda #1 + sta.z a + __b1: + // for(a = 1; a >= 0; a--) + lda.z a + cmp #0 + bpl __b2 + // } + rts + __b2: + // b = 9 + lda #9 + sta.z b + __b3: + // for(b = 9; b >= 0; b--) + lda.z b + cmp #0 + bpl __b4 + // for(a = 1; a >= 0; a--) + dec.z a + jmp __b1 + __b4: + // for(b = 9; b >= 0; b--) + dec.z b + jmp __b3 +} +benchmarkLandscape: { + .label __5 = $86 + .label screenAddress = $83 + .label z = $80 + .label stop = $85 + .label x = $81 + .label c = $82 + lda #0 + sta.z z + __b1: + ldx #0 + __b2: + // colHeight[i] = landscapeBase[i] + lda landscapeBase,x + sta colHeight,x + // for (char i: 0..13) + inx + cpx #$e + bne __b2 + lda #$27 + sta.z x + __b3: + // for (signed char x = 39; x >= 0; x--) + lda.z x + cmp #0 + bpl __b4 + // for(char z: 0..9) + inc.z z + lda #$a + cmp.z z + bne __b1 + // } + rts + __b4: + // screenAddress = lms + x + lda.z x + clc + adc #lms + sta.z screenAddress+1 + ldx #0 + lda #$d + sta.z c + __b6: + // for (signed char c = 13; c >= 0; c--) + lda.z c + cmp #0 + bpl __b7 + // for (signed char x = 39; x >= 0; x--) + dec.z x + jmp __b3 + __b7: + // stop = colHeight[uc] + ldy.z c + lda colHeight,y + sta.z stop + __b9: + // while (start < stop) + cpx.z stop + bcc __b10 + // for (signed char c = 13; c >= 0; c--) + dec.z c + ldx.z stop + jmp __b6 + __b10: + // (*screenAddress) & 0xf + lda #$f + ldy #0 + and (screenAddress),y + sta.z __5 + // uc << 4 + lda.z c + asl + asl + asl + asl + // ((*screenAddress) & 0xf) | (uc << 4) + ora.z __5 + // *screenAddress = ((*screenAddress) & 0xf) | (uc << 4) + sta (screenAddress),y + // screenAddress += 40 + lda #$28 + clc + adc.z screenAddress + sta.z screenAddress + bcc !+ + inc.z screenAddress+1 + !: + // start++; + inx + jmp __b9 + .segment Data + colHeight: .fill $e, 0 +} +landscapeBase: +.fill 14, 0 + diff --git a/src/test/ref/zp-reserve-coalesce-problem.cfg b/src/test/ref/zp-reserve-coalesce-problem.cfg new file mode 100644 index 000000000..9e48799cd --- /dev/null +++ b/src/test/ref/zp-reserve-coalesce-problem.cfg @@ -0,0 +1,95 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call benchmarkCountdownFor + to:main::@1 +main::@1: scope:[main] from main + [2] phi() + [3] call benchmarkLandscape + to:main::@return +main::@return: scope:[main] from main::@1 + [4] return + to:@return + +void benchmarkCountdownFor() +benchmarkCountdownFor: scope:[benchmarkCountdownFor] from main + [5] benchmarkCountdownFor::a = 0 + [6] benchmarkCountdownFor::b = 0 + [7] benchmarkCountdownFor::a = 1 + to:benchmarkCountdownFor::@1 +benchmarkCountdownFor::@1: scope:[benchmarkCountdownFor] from benchmarkCountdownFor benchmarkCountdownFor::@5 + [8] if(benchmarkCountdownFor::a>=0) goto benchmarkCountdownFor::@2 + to:benchmarkCountdownFor::@return +benchmarkCountdownFor::@return: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + [9] return + to:@return +benchmarkCountdownFor::@2: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + [10] benchmarkCountdownFor::b = 9 + to:benchmarkCountdownFor::@3 +benchmarkCountdownFor::@3: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@2 benchmarkCountdownFor::@4 + [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 + to:benchmarkCountdownFor::@5 +benchmarkCountdownFor::@5: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + [12] benchmarkCountdownFor::a = -- benchmarkCountdownFor::a + to:benchmarkCountdownFor::@1 +benchmarkCountdownFor::@4: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + [13] benchmarkCountdownFor::b = -- benchmarkCountdownFor::b + to:benchmarkCountdownFor::@3 + +void benchmarkLandscape() +benchmarkLandscape: scope:[benchmarkLandscape] from main::@1 + [14] phi() + to:benchmarkLandscape::@1 +benchmarkLandscape::@1: scope:[benchmarkLandscape] from benchmarkLandscape benchmarkLandscape::@5 + [15] benchmarkLandscape::z#8 = phi( benchmarkLandscape/0, benchmarkLandscape::@5/benchmarkLandscape::z#1 ) + to:benchmarkLandscape::@2 +benchmarkLandscape::@2: scope:[benchmarkLandscape] from benchmarkLandscape::@1 benchmarkLandscape::@2 + [16] benchmarkLandscape::i#2 = phi( benchmarkLandscape::@1/0, benchmarkLandscape::@2/benchmarkLandscape::i#1 ) + [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] + [18] benchmarkLandscape::i#1 = ++ benchmarkLandscape::i#2 + [19] if(benchmarkLandscape::i#1!=$e) goto benchmarkLandscape::@2 + to:benchmarkLandscape::@3 +benchmarkLandscape::@3: scope:[benchmarkLandscape] from benchmarkLandscape::@2 benchmarkLandscape::@8 + [20] benchmarkLandscape::x#2 = phi( benchmarkLandscape::@2/$27, benchmarkLandscape::@8/benchmarkLandscape::x#1 ) + [21] if(benchmarkLandscape::x#2>=0) goto benchmarkLandscape::@4 + to:benchmarkLandscape::@5 +benchmarkLandscape::@5: scope:[benchmarkLandscape] from benchmarkLandscape::@3 + [22] benchmarkLandscape::z#1 = ++ benchmarkLandscape::z#8 + [23] if(benchmarkLandscape::z#1!=$a) goto benchmarkLandscape::@1 + to:benchmarkLandscape::@return +benchmarkLandscape::@return: scope:[benchmarkLandscape] from benchmarkLandscape::@5 + [24] return + to:@return +benchmarkLandscape::@4: scope:[benchmarkLandscape] from benchmarkLandscape::@3 + [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 + to:benchmarkLandscape::@6 +benchmarkLandscape::@6: scope:[benchmarkLandscape] from benchmarkLandscape::@11 benchmarkLandscape::@4 + [26] benchmarkLandscape::screenAddress#4 = phi( benchmarkLandscape::@11/benchmarkLandscape::screenAddress#2, benchmarkLandscape::@4/benchmarkLandscape::screenAddress#0 ) + [26] benchmarkLandscape::start#5 = phi( benchmarkLandscape::@11/benchmarkLandscape::start#7, benchmarkLandscape::@4/0 ) + [26] benchmarkLandscape::c#2 = phi( benchmarkLandscape::@11/benchmarkLandscape::c#1, benchmarkLandscape::@4/$d ) + [27] if(benchmarkLandscape::c#2>=0) goto benchmarkLandscape::@7 + to:benchmarkLandscape::@8 +benchmarkLandscape::@8: scope:[benchmarkLandscape] from benchmarkLandscape::@6 + [28] benchmarkLandscape::x#1 = -- benchmarkLandscape::x#2 + to:benchmarkLandscape::@3 +benchmarkLandscape::@7: scope:[benchmarkLandscape] from benchmarkLandscape::@6 + [29] benchmarkLandscape::stop#0 = benchmarkLandscape::colHeight[(byte)benchmarkLandscape::c#2] + to:benchmarkLandscape::@9 +benchmarkLandscape::@9: scope:[benchmarkLandscape] from benchmarkLandscape::@10 benchmarkLandscape::@7 + [30] benchmarkLandscape::screenAddress#2 = phi( benchmarkLandscape::@10/benchmarkLandscape::screenAddress#1, benchmarkLandscape::@7/benchmarkLandscape::screenAddress#4 ) + [30] benchmarkLandscape::start#3 = phi( benchmarkLandscape::@10/benchmarkLandscape::start#1, benchmarkLandscape::@7/benchmarkLandscape::start#5 ) + [31] if(benchmarkLandscape::start#3= 0 + if(benchmarkCountdownFor::$0) goto benchmarkCountdownFor::@2 + to:benchmarkCountdownFor::@return +benchmarkCountdownFor::@2: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + benchmarkCountdownFor::b = 9 + to:benchmarkCountdownFor::@3 +benchmarkCountdownFor::@3: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@2 benchmarkCountdownFor::@4 + benchmarkCountdownFor::$1 = benchmarkCountdownFor::b >= 0 + if(benchmarkCountdownFor::$1) goto benchmarkCountdownFor::@4 + to:benchmarkCountdownFor::@5 +benchmarkCountdownFor::@4: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + benchmarkCountdownFor::b = -- benchmarkCountdownFor::b + to:benchmarkCountdownFor::@3 +benchmarkCountdownFor::@5: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + benchmarkCountdownFor::a = -- benchmarkCountdownFor::a + to:benchmarkCountdownFor::@1 +benchmarkCountdownFor::@return: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + return + to:@return + +void benchmarkLandscape() +benchmarkLandscape: scope:[benchmarkLandscape] from main::@1 + benchmarkLandscape::z#0 = 0 + to:benchmarkLandscape::@1 +benchmarkLandscape::@1: scope:[benchmarkLandscape] from benchmarkLandscape benchmarkLandscape::@6 + benchmarkLandscape::z#8 = phi( benchmarkLandscape/benchmarkLandscape::z#0, benchmarkLandscape::@6/benchmarkLandscape::z#1 ) + benchmarkLandscape::i#0 = 0 + to:benchmarkLandscape::@2 +benchmarkLandscape::@2: scope:[benchmarkLandscape] from benchmarkLandscape::@1 benchmarkLandscape::@2 + benchmarkLandscape::z#6 = phi( benchmarkLandscape::@1/benchmarkLandscape::z#8, benchmarkLandscape::@2/benchmarkLandscape::z#6 ) + benchmarkLandscape::i#2 = phi( benchmarkLandscape::@1/benchmarkLandscape::i#0, benchmarkLandscape::@2/benchmarkLandscape::i#1 ) + benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] + benchmarkLandscape::i#1 = benchmarkLandscape::i#2 + rangenext(0,$d) + benchmarkLandscape::$0 = benchmarkLandscape::i#1 != rangelast(0,$d) + if(benchmarkLandscape::$0) goto benchmarkLandscape::@2 + to:benchmarkLandscape::@3 +benchmarkLandscape::@3: scope:[benchmarkLandscape] from benchmarkLandscape::@2 + benchmarkLandscape::z#4 = phi( benchmarkLandscape::@2/benchmarkLandscape::z#6 ) + benchmarkLandscape::x#0 = $27 + to:benchmarkLandscape::@4 +benchmarkLandscape::@4: scope:[benchmarkLandscape] from benchmarkLandscape::@3 benchmarkLandscape::@9 + benchmarkLandscape::z#3 = phi( benchmarkLandscape::@3/benchmarkLandscape::z#4, benchmarkLandscape::@9/benchmarkLandscape::z#5 ) + benchmarkLandscape::x#2 = phi( benchmarkLandscape::@3/benchmarkLandscape::x#0, benchmarkLandscape::@9/benchmarkLandscape::x#1 ) + benchmarkLandscape::$1 = benchmarkLandscape::x#2 >= 0 + if(benchmarkLandscape::$1) goto benchmarkLandscape::@5 + to:benchmarkLandscape::@6 +benchmarkLandscape::@5: scope:[benchmarkLandscape] from benchmarkLandscape::@4 + benchmarkLandscape::z#10 = phi( benchmarkLandscape::@4/benchmarkLandscape::z#3 ) + benchmarkLandscape::x#3 = phi( benchmarkLandscape::@4/benchmarkLandscape::x#2 ) + benchmarkLandscape::$2 = lms + benchmarkLandscape::x#3 + benchmarkLandscape::screenAddress#0 = benchmarkLandscape::$2 + benchmarkLandscape::start#0 = 0 + benchmarkLandscape::c#0 = $d + to:benchmarkLandscape::@7 +benchmarkLandscape::@6: scope:[benchmarkLandscape] from benchmarkLandscape::@4 + benchmarkLandscape::z#2 = phi( benchmarkLandscape::@4/benchmarkLandscape::z#3 ) + benchmarkLandscape::z#1 = benchmarkLandscape::z#2 + rangenext(0,9) + benchmarkLandscape::$8 = benchmarkLandscape::z#1 != rangelast(0,9) + if(benchmarkLandscape::$8) goto benchmarkLandscape::@1 + to:benchmarkLandscape::@return +benchmarkLandscape::@7: scope:[benchmarkLandscape] from benchmarkLandscape::@12 benchmarkLandscape::@5 + benchmarkLandscape::z#7 = phi( benchmarkLandscape::@12/benchmarkLandscape::z#9, benchmarkLandscape::@5/benchmarkLandscape::z#10 ) + benchmarkLandscape::screenAddress#5 = phi( benchmarkLandscape::@12/benchmarkLandscape::screenAddress#6, benchmarkLandscape::@5/benchmarkLandscape::screenAddress#0 ) + benchmarkLandscape::start#6 = phi( benchmarkLandscape::@12/benchmarkLandscape::start#2, benchmarkLandscape::@5/benchmarkLandscape::start#0 ) + benchmarkLandscape::x#5 = phi( benchmarkLandscape::@12/benchmarkLandscape::x#6, benchmarkLandscape::@5/benchmarkLandscape::x#3 ) + benchmarkLandscape::c#2 = phi( benchmarkLandscape::@12/benchmarkLandscape::c#1, benchmarkLandscape::@5/benchmarkLandscape::c#0 ) + benchmarkLandscape::$3 = benchmarkLandscape::c#2 >= 0 + if(benchmarkLandscape::$3) goto benchmarkLandscape::@8 + to:benchmarkLandscape::@9 +benchmarkLandscape::@8: scope:[benchmarkLandscape] from benchmarkLandscape::@7 + benchmarkLandscape::z#13 = phi( benchmarkLandscape::@7/benchmarkLandscape::z#7 ) + benchmarkLandscape::x#9 = phi( benchmarkLandscape::@7/benchmarkLandscape::x#5 ) + benchmarkLandscape::screenAddress#4 = phi( benchmarkLandscape::@7/benchmarkLandscape::screenAddress#5 ) + benchmarkLandscape::start#5 = phi( benchmarkLandscape::@7/benchmarkLandscape::start#6 ) + benchmarkLandscape::c#3 = phi( benchmarkLandscape::@7/benchmarkLandscape::c#2 ) + benchmarkLandscape::uc#0 = (byte)benchmarkLandscape::c#3 + benchmarkLandscape::stop#0 = benchmarkLandscape::colHeight[benchmarkLandscape::uc#0] + to:benchmarkLandscape::@10 +benchmarkLandscape::@9: scope:[benchmarkLandscape] from benchmarkLandscape::@7 + benchmarkLandscape::z#5 = phi( benchmarkLandscape::@7/benchmarkLandscape::z#7 ) + benchmarkLandscape::x#4 = phi( benchmarkLandscape::@7/benchmarkLandscape::x#5 ) + benchmarkLandscape::x#1 = -- benchmarkLandscape::x#4 + to:benchmarkLandscape::@4 +benchmarkLandscape::@10: scope:[benchmarkLandscape] from benchmarkLandscape::@11 benchmarkLandscape::@8 + benchmarkLandscape::z#11 = phi( benchmarkLandscape::@11/benchmarkLandscape::z#12, benchmarkLandscape::@8/benchmarkLandscape::z#13 ) + benchmarkLandscape::x#7 = phi( benchmarkLandscape::@11/benchmarkLandscape::x#8, benchmarkLandscape::@8/benchmarkLandscape::x#9 ) + benchmarkLandscape::c#5 = phi( benchmarkLandscape::@11/benchmarkLandscape::c#6, benchmarkLandscape::@8/benchmarkLandscape::c#3 ) + benchmarkLandscape::uc#2 = phi( benchmarkLandscape::@11/benchmarkLandscape::uc#1, benchmarkLandscape::@8/benchmarkLandscape::uc#0 ) + benchmarkLandscape::screenAddress#3 = phi( benchmarkLandscape::@11/benchmarkLandscape::screenAddress#1, benchmarkLandscape::@8/benchmarkLandscape::screenAddress#4 ) + benchmarkLandscape::stop#1 = phi( benchmarkLandscape::@11/benchmarkLandscape::stop#3, benchmarkLandscape::@8/benchmarkLandscape::stop#0 ) + benchmarkLandscape::start#3 = phi( benchmarkLandscape::@11/benchmarkLandscape::start#1, benchmarkLandscape::@8/benchmarkLandscape::start#5 ) + benchmarkLandscape::$4 = benchmarkLandscape::start#3 < benchmarkLandscape::stop#1 + if(benchmarkLandscape::$4) goto benchmarkLandscape::@11 + to:benchmarkLandscape::@12 +benchmarkLandscape::@11: scope:[benchmarkLandscape] from benchmarkLandscape::@10 + benchmarkLandscape::z#12 = phi( benchmarkLandscape::@10/benchmarkLandscape::z#11 ) + benchmarkLandscape::x#8 = phi( benchmarkLandscape::@10/benchmarkLandscape::x#7 ) + benchmarkLandscape::c#6 = phi( benchmarkLandscape::@10/benchmarkLandscape::c#5 ) + benchmarkLandscape::stop#3 = phi( benchmarkLandscape::@10/benchmarkLandscape::stop#1 ) + benchmarkLandscape::start#4 = phi( benchmarkLandscape::@10/benchmarkLandscape::start#3 ) + benchmarkLandscape::uc#1 = phi( benchmarkLandscape::@10/benchmarkLandscape::uc#2 ) + benchmarkLandscape::screenAddress#2 = phi( benchmarkLandscape::@10/benchmarkLandscape::screenAddress#3 ) + benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f + benchmarkLandscape::$6 = benchmarkLandscape::uc#1 << 4 + benchmarkLandscape::$7 = benchmarkLandscape::$5 | benchmarkLandscape::$6 + *benchmarkLandscape::screenAddress#2 = benchmarkLandscape::$7 + benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 + benchmarkLandscape::start#1 = ++ benchmarkLandscape::start#4 + to:benchmarkLandscape::@10 +benchmarkLandscape::@12: scope:[benchmarkLandscape] from benchmarkLandscape::@10 + benchmarkLandscape::z#9 = phi( benchmarkLandscape::@10/benchmarkLandscape::z#11 ) + benchmarkLandscape::screenAddress#6 = phi( benchmarkLandscape::@10/benchmarkLandscape::screenAddress#3 ) + benchmarkLandscape::x#6 = phi( benchmarkLandscape::@10/benchmarkLandscape::x#7 ) + benchmarkLandscape::c#4 = phi( benchmarkLandscape::@10/benchmarkLandscape::c#5 ) + benchmarkLandscape::stop#2 = phi( benchmarkLandscape::@10/benchmarkLandscape::stop#1 ) + benchmarkLandscape::start#2 = benchmarkLandscape::stop#2 + benchmarkLandscape::c#1 = -- benchmarkLandscape::c#4 + to:benchmarkLandscape::@7 +benchmarkLandscape::@return: scope:[benchmarkLandscape] from benchmarkLandscape::@6 + 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 +void __start() +void benchmarkCountdownFor() +bool~ benchmarkCountdownFor::$0 +bool~ benchmarkCountdownFor::$1 +signed byte benchmarkCountdownFor::a loadstore !zp[-1]:65 +signed byte benchmarkCountdownFor::b loadstore !zp[-1]:75 +void benchmarkLandscape() +bool~ benchmarkLandscape::$0 +bool~ benchmarkLandscape::$1 +byte*~ benchmarkLandscape::$2 +bool~ benchmarkLandscape::$3 +bool~ benchmarkLandscape::$4 +number~ benchmarkLandscape::$5 +byte~ benchmarkLandscape::$6 +number~ benchmarkLandscape::$7 +bool~ benchmarkLandscape::$8 +signed byte benchmarkLandscape::c +signed byte benchmarkLandscape::c#0 +signed byte benchmarkLandscape::c#1 +signed byte benchmarkLandscape::c#2 +signed byte benchmarkLandscape::c#3 +signed byte benchmarkLandscape::c#4 +signed byte benchmarkLandscape::c#5 +signed byte benchmarkLandscape::c#6 +const byte* benchmarkLandscape::colHeight[$e] = { fill( $e, 0) } +byte benchmarkLandscape::i +byte benchmarkLandscape::i#0 +byte benchmarkLandscape::i#1 +byte benchmarkLandscape::i#2 +byte* benchmarkLandscape::screenAddress +byte* benchmarkLandscape::screenAddress#0 +byte* benchmarkLandscape::screenAddress#1 +byte* benchmarkLandscape::screenAddress#2 +byte* benchmarkLandscape::screenAddress#3 +byte* benchmarkLandscape::screenAddress#4 +byte* benchmarkLandscape::screenAddress#5 +byte* benchmarkLandscape::screenAddress#6 +byte benchmarkLandscape::start +byte benchmarkLandscape::start#0 +byte benchmarkLandscape::start#1 +byte benchmarkLandscape::start#2 +byte benchmarkLandscape::start#3 +byte benchmarkLandscape::start#4 +byte benchmarkLandscape::start#5 +byte benchmarkLandscape::start#6 +byte benchmarkLandscape::stop +byte benchmarkLandscape::stop#0 +byte benchmarkLandscape::stop#1 +byte benchmarkLandscape::stop#2 +byte benchmarkLandscape::stop#3 +byte benchmarkLandscape::uc +byte benchmarkLandscape::uc#0 +byte benchmarkLandscape::uc#1 +byte benchmarkLandscape::uc#2 +signed byte benchmarkLandscape::x +signed byte benchmarkLandscape::x#0 +signed byte benchmarkLandscape::x#1 +signed byte benchmarkLandscape::x#2 +signed byte benchmarkLandscape::x#3 +signed byte benchmarkLandscape::x#4 +signed byte benchmarkLandscape::x#5 +signed byte benchmarkLandscape::x#6 +signed byte benchmarkLandscape::x#7 +signed byte benchmarkLandscape::x#8 +signed byte benchmarkLandscape::x#9 +byte benchmarkLandscape::z +byte benchmarkLandscape::z#0 +byte benchmarkLandscape::z#1 +byte benchmarkLandscape::z#10 +byte benchmarkLandscape::z#11 +byte benchmarkLandscape::z#12 +byte benchmarkLandscape::z#13 +byte benchmarkLandscape::z#2 +byte benchmarkLandscape::z#3 +byte benchmarkLandscape::z#4 +byte benchmarkLandscape::z#5 +byte benchmarkLandscape::z#6 +byte benchmarkLandscape::z#7 +byte benchmarkLandscape::z#8 +byte benchmarkLandscape::z#9 +const byte* landscapeBase[] = kickasm {{ .fill 14, 0 + }} +const nomodify byte* lms = (byte*)$a000 +void main() + +Adding number conversion cast (snumber) 1 in benchmarkCountdownFor::a = 1 +Adding number conversion cast (snumber) 0 in benchmarkCountdownFor::$0 = benchmarkCountdownFor::a >= 0 +Adding number conversion cast (snumber) 9 in benchmarkCountdownFor::b = 9 +Adding number conversion cast (snumber) 0 in benchmarkCountdownFor::$1 = benchmarkCountdownFor::b >= 0 +Adding number conversion cast (snumber) 0 in benchmarkLandscape::$1 = benchmarkLandscape::x#2 >= 0 +Adding number conversion cast (snumber) 0 in benchmarkLandscape::$3 = benchmarkLandscape::c#2 >= 0 +Adding number conversion cast (unumber) $f in benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f +Adding number conversion cast (unumber) benchmarkLandscape::$5 in benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & (unumber)$f +Adding number conversion cast (unumber) 4 in benchmarkLandscape::$6 = benchmarkLandscape::uc#1 << 4 +Adding number conversion cast (unumber) benchmarkLandscape::$7 in benchmarkLandscape::$7 = benchmarkLandscape::$5 | benchmarkLandscape::$6 +Adding number conversion cast (unumber) $28 in benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast benchmarkCountdownFor::a = (snumber)1 +Inlining cast benchmarkCountdownFor::b = (snumber)9 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 40960 +Simplifying constant integer cast 1 +Simplifying constant integer cast 0 +Simplifying constant integer cast 9 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast $f +Simplifying constant integer cast 4 +Simplifying constant integer cast $28 +Successful SSA optimization PassNCastSimplification +Finalized signed number type 1 +Finalized signed number type 0 +Finalized signed number type 9 +Finalized signed number type 0 +Finalized signed number type 0 +Finalized signed number type 0 +Finalized unsigned number type $f +Finalized unsigned number type 4 +Finalized unsigned number type $28 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f +Inferred type updated to byte in benchmarkLandscape::$7 = benchmarkLandscape::$5 | benchmarkLandscape::$6 +Alias benchmarkLandscape::z#4 = benchmarkLandscape::z#6 +Alias benchmarkLandscape::x#2 = benchmarkLandscape::x#3 +Alias benchmarkLandscape::z#10 = benchmarkLandscape::z#3 benchmarkLandscape::z#2 +Alias benchmarkLandscape::screenAddress#0 = benchmarkLandscape::$2 +Alias benchmarkLandscape::c#2 = benchmarkLandscape::c#3 +Alias benchmarkLandscape::start#5 = benchmarkLandscape::start#6 +Alias benchmarkLandscape::screenAddress#4 = benchmarkLandscape::screenAddress#5 +Alias benchmarkLandscape::x#4 = benchmarkLandscape::x#9 benchmarkLandscape::x#5 +Alias benchmarkLandscape::z#13 = benchmarkLandscape::z#7 benchmarkLandscape::z#5 +Alias benchmarkLandscape::screenAddress#2 = benchmarkLandscape::screenAddress#3 benchmarkLandscape::screenAddress#6 +Alias benchmarkLandscape::uc#1 = benchmarkLandscape::uc#2 +Alias benchmarkLandscape::start#3 = benchmarkLandscape::start#4 +Alias benchmarkLandscape::stop#1 = benchmarkLandscape::stop#3 benchmarkLandscape::stop#2 benchmarkLandscape::start#2 +Alias benchmarkLandscape::c#4 = benchmarkLandscape::c#6 benchmarkLandscape::c#5 +Alias benchmarkLandscape::x#6 = benchmarkLandscape::x#8 benchmarkLandscape::x#7 +Alias benchmarkLandscape::z#11 = benchmarkLandscape::z#12 benchmarkLandscape::z#9 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values benchmarkLandscape::z#4 benchmarkLandscape::z#8 +Identical Phi Values benchmarkLandscape::stop#1 benchmarkLandscape::stop#0 +Identical Phi Values benchmarkLandscape::uc#1 benchmarkLandscape::uc#0 +Identical Phi Values benchmarkLandscape::c#4 benchmarkLandscape::c#2 +Identical Phi Values benchmarkLandscape::x#6 benchmarkLandscape::x#4 +Identical Phi Values benchmarkLandscape::z#11 benchmarkLandscape::z#13 +Successful SSA optimization Pass2IdenticalPhiElimination +Identical Phi Values benchmarkLandscape::x#4 benchmarkLandscape::x#2 +Identical Phi Values benchmarkLandscape::z#13 benchmarkLandscape::z#10 +Successful SSA optimization Pass2IdenticalPhiElimination +Identical Phi Values benchmarkLandscape::z#10 benchmarkLandscape::z#8 +Successful SSA optimization Pass2IdenticalPhiElimination +Simple Condition benchmarkCountdownFor::$0 [7] if(benchmarkCountdownFor::a>=0) goto benchmarkCountdownFor::@2 +Simple Condition benchmarkCountdownFor::$1 [10] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 +Simple Condition benchmarkLandscape::$0 [21] if(benchmarkLandscape::i#1!=rangelast(0,$d)) goto benchmarkLandscape::@2 +Simple Condition benchmarkLandscape::$1 [25] if(benchmarkLandscape::x#2>=0) goto benchmarkLandscape::@5 +Simple Condition benchmarkLandscape::$8 [31] if(benchmarkLandscape::z#1!=rangelast(0,9)) goto benchmarkLandscape::@1 +Simple Condition benchmarkLandscape::$3 [34] if(benchmarkLandscape::c#2>=0) goto benchmarkLandscape::@8 +Simple Condition benchmarkLandscape::$4 [40] if(benchmarkLandscape::start#3=0) goto benchmarkCountdownFor::@2 + to:benchmarkCountdownFor::@return +benchmarkCountdownFor::@return: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + [9] return + to:@return +benchmarkCountdownFor::@2: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@1 + [10] benchmarkCountdownFor::b = 9 + to:benchmarkCountdownFor::@3 +benchmarkCountdownFor::@3: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@2 benchmarkCountdownFor::@4 + [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 + to:benchmarkCountdownFor::@5 +benchmarkCountdownFor::@5: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + [12] benchmarkCountdownFor::a = -- benchmarkCountdownFor::a + to:benchmarkCountdownFor::@1 +benchmarkCountdownFor::@4: scope:[benchmarkCountdownFor] from benchmarkCountdownFor::@3 + [13] benchmarkCountdownFor::b = -- benchmarkCountdownFor::b + to:benchmarkCountdownFor::@3 + +void benchmarkLandscape() +benchmarkLandscape: scope:[benchmarkLandscape] from main::@1 + [14] phi() + to:benchmarkLandscape::@1 +benchmarkLandscape::@1: scope:[benchmarkLandscape] from benchmarkLandscape benchmarkLandscape::@5 + [15] benchmarkLandscape::z#8 = phi( benchmarkLandscape/0, benchmarkLandscape::@5/benchmarkLandscape::z#1 ) + to:benchmarkLandscape::@2 +benchmarkLandscape::@2: scope:[benchmarkLandscape] from benchmarkLandscape::@1 benchmarkLandscape::@2 + [16] benchmarkLandscape::i#2 = phi( benchmarkLandscape::@1/0, benchmarkLandscape::@2/benchmarkLandscape::i#1 ) + [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] + [18] benchmarkLandscape::i#1 = ++ benchmarkLandscape::i#2 + [19] if(benchmarkLandscape::i#1!=$e) goto benchmarkLandscape::@2 + to:benchmarkLandscape::@3 +benchmarkLandscape::@3: scope:[benchmarkLandscape] from benchmarkLandscape::@2 benchmarkLandscape::@8 + [20] benchmarkLandscape::x#2 = phi( benchmarkLandscape::@2/$27, benchmarkLandscape::@8/benchmarkLandscape::x#1 ) + [21] if(benchmarkLandscape::x#2>=0) goto benchmarkLandscape::@4 + to:benchmarkLandscape::@5 +benchmarkLandscape::@5: scope:[benchmarkLandscape] from benchmarkLandscape::@3 + [22] benchmarkLandscape::z#1 = ++ benchmarkLandscape::z#8 + [23] if(benchmarkLandscape::z#1!=$a) goto benchmarkLandscape::@1 + to:benchmarkLandscape::@return +benchmarkLandscape::@return: scope:[benchmarkLandscape] from benchmarkLandscape::@5 + [24] return + to:@return +benchmarkLandscape::@4: scope:[benchmarkLandscape] from benchmarkLandscape::@3 + [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 + to:benchmarkLandscape::@6 +benchmarkLandscape::@6: scope:[benchmarkLandscape] from benchmarkLandscape::@11 benchmarkLandscape::@4 + [26] benchmarkLandscape::screenAddress#4 = phi( benchmarkLandscape::@11/benchmarkLandscape::screenAddress#2, benchmarkLandscape::@4/benchmarkLandscape::screenAddress#0 ) + [26] benchmarkLandscape::start#5 = phi( benchmarkLandscape::@11/benchmarkLandscape::start#7, benchmarkLandscape::@4/0 ) + [26] benchmarkLandscape::c#2 = phi( benchmarkLandscape::@11/benchmarkLandscape::c#1, benchmarkLandscape::@4/$d ) + [27] if(benchmarkLandscape::c#2>=0) goto benchmarkLandscape::@7 + to:benchmarkLandscape::@8 +benchmarkLandscape::@8: scope:[benchmarkLandscape] from benchmarkLandscape::@6 + [28] benchmarkLandscape::x#1 = -- benchmarkLandscape::x#2 + to:benchmarkLandscape::@3 +benchmarkLandscape::@7: scope:[benchmarkLandscape] from benchmarkLandscape::@6 + [29] benchmarkLandscape::stop#0 = benchmarkLandscape::colHeight[(byte)benchmarkLandscape::c#2] + to:benchmarkLandscape::@9 +benchmarkLandscape::@9: scope:[benchmarkLandscape] from benchmarkLandscape::@10 benchmarkLandscape::@7 + [30] benchmarkLandscape::screenAddress#2 = phi( benchmarkLandscape::@10/benchmarkLandscape::screenAddress#1, benchmarkLandscape::@7/benchmarkLandscape::screenAddress#4 ) + [30] benchmarkLandscape::start#3 = phi( benchmarkLandscape::@10/benchmarkLandscape::start#1, benchmarkLandscape::@7/benchmarkLandscape::start#5 ) + [31] if(benchmarkLandscape::start#3=0) goto benchmarkCountdownFor::@2 [ benchmarkCountdownFor::a ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a ] { } ) always clobbers reg byte a +Statement [10] benchmarkCountdownFor::b = 9 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] { } ) always clobbers reg byte a +Statement [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] { } ) always clobbers reg byte a +Statement [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] [ benchmarkLandscape::z#8 benchmarkLandscape::i#2 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::i#2 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:129 [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] +Statement [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::screenAddress#0 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::screenAddress#0 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +Statement [34] benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 ] { } ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Removing always clobbered register reg byte y as potential for zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +Removing always clobbered register reg byte y as potential for zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:135 [ benchmarkLandscape::stop#0 ] +Removing always clobbered register reg byte y as potential for zp[1]:135 [ benchmarkLandscape::stop#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:134 [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] +Removing always clobbered register reg byte y as potential for zp[1]:134 [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] +Statement [35] benchmarkLandscape::$6 = (byte)benchmarkLandscape::c#2 << 4 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 benchmarkLandscape::$6 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 benchmarkLandscape::$6 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:136 [ benchmarkLandscape::$5 ] +Statement [37] *benchmarkLandscape::screenAddress#2 = benchmarkLandscape::$7 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 ] { } ) always clobbers reg byte y +Statement [38] benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::screenAddress#1 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::screenAddress#1 ] { } ) always clobbers reg byte a +Statement [5] benchmarkCountdownFor::a = 0 [ ] ( benchmarkCountdownFor:1 [ ] { } ) always clobbers reg byte a +Statement [6] benchmarkCountdownFor::b = 0 [ ] ( benchmarkCountdownFor:1 [ ] { } ) always clobbers reg byte a +Statement [7] benchmarkCountdownFor::a = 1 [ benchmarkCountdownFor::a ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a ] { } ) always clobbers reg byte a +Statement [8] if(benchmarkCountdownFor::a>=0) goto benchmarkCountdownFor::@2 [ benchmarkCountdownFor::a ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a ] { } ) always clobbers reg byte a +Statement [10] benchmarkCountdownFor::b = 9 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] { } ) always clobbers reg byte a +Statement [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] ( benchmarkCountdownFor:1 [ benchmarkCountdownFor::a benchmarkCountdownFor::b ] { } ) always clobbers reg byte a +Statement [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] [ benchmarkLandscape::z#8 benchmarkLandscape::i#2 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::i#2 ] { } ) always clobbers reg byte a +Statement [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::screenAddress#0 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::screenAddress#0 ] { } ) always clobbers reg byte a +Statement [34] benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 ] { } ) always clobbers reg byte a reg byte y +Statement [35] benchmarkLandscape::$6 = (byte)benchmarkLandscape::c#2 << 4 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 benchmarkLandscape::$6 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::$5 benchmarkLandscape::$6 ] { } ) always clobbers reg byte a +Statement [37] *benchmarkLandscape::screenAddress#2 = benchmarkLandscape::$7 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::screenAddress#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 ] { } ) always clobbers reg byte y +Statement [38] benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::screenAddress#1 ] ( benchmarkLandscape:3 [ benchmarkLandscape::z#8 benchmarkLandscape::x#2 benchmarkLandscape::c#2 benchmarkLandscape::stop#0 benchmarkLandscape::start#3 benchmarkLandscape::screenAddress#1 ] { } ) always clobbers reg byte a +Potential registers zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] : zp[1]:128 , reg byte x , +Potential registers zp[1]:129 [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] : zp[1]:129 , reg byte x , reg byte y , +Potential registers zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] : zp[1]:130 , reg byte x , +Potential registers zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] : zp[1]:131 , reg byte x , +Potential registers zp[2]:132 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] : zp[2]:132 , +Potential registers zp[1]:134 [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] : zp[1]:134 , reg byte x , +Potential registers zp[1]:65 [ benchmarkCountdownFor::a ] : zp[1]:65 , +Potential registers zp[1]:75 [ benchmarkCountdownFor::b ] : zp[1]:75 , +Potential registers zp[1]:135 [ benchmarkLandscape::stop#0 ] : zp[1]:135 , reg byte x , +Potential registers zp[1]:136 [ benchmarkLandscape::$5 ] : zp[1]:136 , reg byte x , reg byte y , +Potential registers zp[1]:137 [ benchmarkLandscape::$6 ] : zp[1]:137 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:138 [ benchmarkLandscape::$7 ] : zp[1]:138 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [benchmarkLandscape] 270,957.62: zp[1]:134 [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] 200,002: zp[1]:137 [ benchmarkLandscape::$6 ] 200,002: zp[1]:138 [ benchmarkLandscape::$7 ] 161,504.75: zp[2]:132 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] 100,001: zp[1]:136 [ benchmarkLandscape::$5 ] 12,728.55: zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] 12,000.3: zp[1]:135 [ benchmarkLandscape::stop#0 ] 3,503.5: zp[1]:129 [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] 2,252.25: zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] 160.68: zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Uplift Scope [benchmarkCountdownFor] 1,038.33: zp[1]:75 [ benchmarkCountdownFor::b ] 54.17: zp[1]:65 [ benchmarkCountdownFor::a ] +Uplift Scope [main] +Uplift Scope [] + +Uplifting [benchmarkLandscape] best 738134 combination reg byte x [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] reg byte a [ benchmarkLandscape::$6 ] reg byte a [ benchmarkLandscape::$7 ] zp[2]:132 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] zp[1]:136 [ benchmarkLandscape::$5 ] zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] zp[1]:135 [ benchmarkLandscape::stop#0 ] zp[1]:129 [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Limited combination testing to 100 combinations of 4608 possible. +Uplifting [benchmarkCountdownFor] best 738134 combination zp[1]:75 [ benchmarkCountdownFor::b ] zp[1]:65 [ benchmarkCountdownFor::a ] +Uplifting [main] best 738134 combination +Uplifting [] best 738134 combination +Attempting to uplift remaining variables inzp[1]:136 [ benchmarkLandscape::$5 ] +Uplifting [benchmarkLandscape] best 738134 combination zp[1]:136 [ benchmarkLandscape::$5 ] +Attempting to uplift remaining variables inzp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +Uplifting [benchmarkLandscape] best 738134 combination zp[1]:131 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +Attempting to uplift remaining variables inzp[1]:135 [ benchmarkLandscape::stop#0 ] +Uplifting [benchmarkLandscape] best 738134 combination zp[1]:135 [ benchmarkLandscape::stop#0 ] +Attempting to uplift remaining variables inzp[1]:129 [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] +Uplifting [benchmarkLandscape] best 736934 combination reg byte x [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] +Attempting to uplift remaining variables inzp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +Uplifting [benchmarkLandscape] best 736934 combination zp[1]:130 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +Attempting to uplift remaining variables inzp[1]:75 [ benchmarkCountdownFor::b ] +Uplifting [benchmarkCountdownFor] best 736934 combination zp[1]:75 [ benchmarkCountdownFor::b ] +Attempting to uplift remaining variables inzp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Uplifting [benchmarkLandscape] best 736934 combination zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +Attempting to uplift remaining variables inzp[1]:65 [ benchmarkCountdownFor::a ] +Uplifting [benchmarkCountdownFor] best 736934 combination zp[1]:65 [ benchmarkCountdownFor::a ] +Allocated (was zp[1]:130) zp[1]:129 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +Allocated (was zp[1]:131) zp[1]:130 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +Allocated (was zp[2]:132) zp[2]:131 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] +Allocated (was zp[1]:135) zp[1]:133 [ benchmarkLandscape::stop#0 ] +Allocated (was zp[1]:136) zp[1]:134 [ benchmarkLandscape::$5 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Demonstrates problem where reserved ZP addresses can still be coalesced if they are explicitly __address() assigned to variables +// https://gitlab.com/camelot/kickc/-/issues/550 + // Upstart + // Atari XL/XE executable XEX file with a single segment +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="zp-reserve-coalesce-problem.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // Global Constants & labels + .label lms = $a000 +.segment Code + // main +main: { + // [1] call benchmarkCountdownFor + jsr benchmarkCountdownFor + // [2] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + jmp __b1 + // main::@1 + __b1: + // [3] call benchmarkLandscape + // [14] phi from main::@1 to benchmarkLandscape [phi:main::@1->benchmarkLandscape] + benchmarkLandscape_from___b1: + jsr benchmarkLandscape + jmp __breturn + // main::@return + __breturn: + // [4] return + rts +} + // benchmarkCountdownFor +benchmarkCountdownFor: { + .label a = $41 + .label b = $4b + // [5] benchmarkCountdownFor::a = 0 -- vbsz1=vbsc1 + lda #0 + sta.z a + // [6] benchmarkCountdownFor::b = 0 -- vbsz1=vbsc1 + lda #0 + sta.z b + // [7] benchmarkCountdownFor::a = 1 -- vbsz1=vbsc1 + lda #1 + sta.z a + jmp __b1 + // benchmarkCountdownFor::@1 + __b1: + // [8] if(benchmarkCountdownFor::a>=0) goto benchmarkCountdownFor::@2 -- vbsz1_ge_0_then_la1 + lda.z a + cmp #0 + bpl __b2 + jmp __breturn + // benchmarkCountdownFor::@return + __breturn: + // [9] return + rts + // benchmarkCountdownFor::@2 + __b2: + // [10] benchmarkCountdownFor::b = 9 -- vbsz1=vbsc1 + lda #9 + sta.z b + jmp __b3 + // benchmarkCountdownFor::@3 + __b3: + // [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 -- vbsz1_ge_0_then_la1 + lda.z b + cmp #0 + bpl __b4 + jmp __b5 + // benchmarkCountdownFor::@5 + __b5: + // [12] benchmarkCountdownFor::a = -- benchmarkCountdownFor::a -- vbsz1=_dec_vbsz1 + dec.z a + jmp __b1 + // benchmarkCountdownFor::@4 + __b4: + // [13] benchmarkCountdownFor::b = -- benchmarkCountdownFor::b -- vbsz1=_dec_vbsz1 + dec.z b + jmp __b3 +} + // benchmarkLandscape +benchmarkLandscape: { + .label __5 = $86 + .label screenAddress = $83 + .label z = $80 + .label stop = $85 + .label x = $81 + .label c = $82 + // [15] phi from benchmarkLandscape to benchmarkLandscape::@1 [phi:benchmarkLandscape->benchmarkLandscape::@1] + __b1_from_benchmarkLandscape: + // [15] phi benchmarkLandscape::z#8 = 0 [phi:benchmarkLandscape->benchmarkLandscape::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z z + jmp __b1 + // [15] phi from benchmarkLandscape::@5 to benchmarkLandscape::@1 [phi:benchmarkLandscape::@5->benchmarkLandscape::@1] + __b1_from___b5: + // [15] phi benchmarkLandscape::z#8 = benchmarkLandscape::z#1 [phi:benchmarkLandscape::@5->benchmarkLandscape::@1#0] -- register_copy + jmp __b1 + // benchmarkLandscape::@1 + __b1: + // [16] phi from benchmarkLandscape::@1 to benchmarkLandscape::@2 [phi:benchmarkLandscape::@1->benchmarkLandscape::@2] + __b2_from___b1: + // [16] phi benchmarkLandscape::i#2 = 0 [phi:benchmarkLandscape::@1->benchmarkLandscape::@2#0] -- vbuxx=vbuc1 + ldx #0 + jmp __b2 + // [16] phi from benchmarkLandscape::@2 to benchmarkLandscape::@2 [phi:benchmarkLandscape::@2->benchmarkLandscape::@2] + __b2_from___b2: + // [16] phi benchmarkLandscape::i#2 = benchmarkLandscape::i#1 [phi:benchmarkLandscape::@2->benchmarkLandscape::@2#0] -- register_copy + jmp __b2 + // benchmarkLandscape::@2 + __b2: + // [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx + lda landscapeBase,x + sta colHeight,x + // [18] benchmarkLandscape::i#1 = ++ benchmarkLandscape::i#2 -- vbuxx=_inc_vbuxx + inx + // [19] if(benchmarkLandscape::i#1!=$e) goto benchmarkLandscape::@2 -- vbuxx_neq_vbuc1_then_la1 + cpx #$e + bne __b2_from___b2 + // [20] phi from benchmarkLandscape::@2 to benchmarkLandscape::@3 [phi:benchmarkLandscape::@2->benchmarkLandscape::@3] + __b3_from___b2: + // [20] phi benchmarkLandscape::x#2 = $27 [phi:benchmarkLandscape::@2->benchmarkLandscape::@3#0] -- vbsz1=vbsc1 + lda #$27 + sta.z x + jmp __b3 + // benchmarkLandscape::@3 + __b3: + // [21] if(benchmarkLandscape::x#2>=0) goto benchmarkLandscape::@4 -- vbsz1_ge_0_then_la1 + lda.z x + cmp #0 + bpl __b4 + jmp __b5 + // benchmarkLandscape::@5 + __b5: + // [22] benchmarkLandscape::z#1 = ++ benchmarkLandscape::z#8 -- vbuz1=_inc_vbuz1 + inc.z z + // [23] if(benchmarkLandscape::z#1!=$a) goto benchmarkLandscape::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #$a + cmp.z z + bne __b1_from___b5 + jmp __breturn + // benchmarkLandscape::@return + __breturn: + // [24] return + rts + // benchmarkLandscape::@4 + __b4: + // [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 -- pbuz1=pbuc1_plus_vbsz2 + lda.z x + clc + adc #lms + sta.z screenAddress+1 + // [26] phi from benchmarkLandscape::@4 to benchmarkLandscape::@6 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6] + __b6_from___b4: + // [26] phi benchmarkLandscape::screenAddress#4 = benchmarkLandscape::screenAddress#0 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#0] -- register_copy + // [26] phi benchmarkLandscape::start#5 = 0 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#1] -- vbuxx=vbuc1 + ldx #0 + // [26] phi benchmarkLandscape::c#2 = $d [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#2] -- vbsz1=vbsc1 + lda #$d + sta.z c + jmp __b6 + // benchmarkLandscape::@6 + __b6: + // [27] if(benchmarkLandscape::c#2>=0) goto benchmarkLandscape::@7 -- vbsz1_ge_0_then_la1 + lda.z c + cmp #0 + bpl __b7 + jmp __b8 + // benchmarkLandscape::@8 + __b8: + // [28] benchmarkLandscape::x#1 = -- benchmarkLandscape::x#2 -- vbsz1=_dec_vbsz1 + dec.z x + // [20] phi from benchmarkLandscape::@8 to benchmarkLandscape::@3 [phi:benchmarkLandscape::@8->benchmarkLandscape::@3] + __b3_from___b8: + // [20] phi benchmarkLandscape::x#2 = benchmarkLandscape::x#1 [phi:benchmarkLandscape::@8->benchmarkLandscape::@3#0] -- register_copy + jmp __b3 + // benchmarkLandscape::@7 + __b7: + // [29] benchmarkLandscape::stop#0 = benchmarkLandscape::colHeight[(byte)benchmarkLandscape::c#2] -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z c + lda colHeight,y + sta.z stop + // [30] phi from benchmarkLandscape::@10 benchmarkLandscape::@7 to benchmarkLandscape::@9 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9] + __b9_from___b10: + __b9_from___b7: + // [30] phi benchmarkLandscape::screenAddress#2 = benchmarkLandscape::screenAddress#1 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9#0] -- register_copy + // [30] phi benchmarkLandscape::start#3 = benchmarkLandscape::start#1 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9#1] -- register_copy + jmp __b9 + // benchmarkLandscape::@9 + __b9: + // [31] if(benchmarkLandscape::start#3benchmarkLandscape::@6] + __b6_from___b11: + // [26] phi benchmarkLandscape::screenAddress#4 = benchmarkLandscape::screenAddress#2 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#0] -- register_copy + // [26] phi benchmarkLandscape::start#5 = benchmarkLandscape::start#7 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#1] -- register_copy + // [26] phi benchmarkLandscape::c#2 = benchmarkLandscape::c#1 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#2] -- register_copy + jmp __b6 + // benchmarkLandscape::@10 + __b10: + // [34] benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f -- vbuz1=_deref_pbuz2_band_vbuc1 + lda #$f + ldy #0 + and (screenAddress),y + sta.z __5 + // [35] benchmarkLandscape::$6 = (byte)benchmarkLandscape::c#2 << 4 -- vbuaa=vbuz1_rol_4 + lda.z c + asl + asl + asl + asl + // [36] benchmarkLandscape::$7 = benchmarkLandscape::$5 | benchmarkLandscape::$6 -- vbuaa=vbuz1_bor_vbuaa + ora.z __5 + // [37] *benchmarkLandscape::screenAddress#2 = benchmarkLandscape::$7 -- _deref_pbuz1=vbuaa + ldy #0 + sta (screenAddress),y + // [38] benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 -- pbuz1=pbuz1_plus_vbuc1 + lda #$28 + clc + adc.z screenAddress + sta.z screenAddress + bcc !+ + inc.z screenAddress+1 + !: + // [39] benchmarkLandscape::start#1 = ++ benchmarkLandscape::start#3 -- vbuxx=_inc_vbuxx + inx + jmp __b9_from___b10 + .segment Data + colHeight: .fill $e, 0 +} + // File Data +landscapeBase: +.fill 14, 0 + + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b3 +Removing instruction jmp __b5 +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __b5 +Removing instruction jmp __breturn +Removing instruction jmp __b6 +Removing instruction jmp __b8 +Removing instruction jmp __b9 +Removing instruction jmp __b11 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Removing instruction ldy #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label __b2_from___b2 with __b2 +Replacing label __b1_from___b5 with __b1 +Replacing label __b9_from___b10 with __b9 +Removing instruction __b1_from_main: +Removing instruction benchmarkLandscape_from___b1: +Removing instruction __b1_from___b5: +Removing instruction __b2_from___b1: +Removing instruction __b2_from___b2: +Removing instruction __b9_from___b10: +Removing instruction __b9_from___b7: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __b5: +Removing instruction __b1_from_benchmarkLandscape: +Removing instruction __b3_from___b2: +Removing instruction __b5: +Removing instruction __breturn: +Removing instruction __b6_from___b4: +Removing instruction __b8: +Removing instruction __b3_from___b8: +Removing instruction __b11: +Removing instruction __b6_from___b11: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +void benchmarkCountdownFor() +signed byte benchmarkCountdownFor::a loadstore !zp[-1]:65 zp[1]:65 54.16666666666666 +signed byte benchmarkCountdownFor::b loadstore !zp[-1]:75 zp[1]:75 1038.3333333333335 +void benchmarkLandscape() +byte~ benchmarkLandscape::$5 zp[1]:134 100001.0 +byte~ benchmarkLandscape::$6 reg byte a 200002.0 +byte~ benchmarkLandscape::$7 reg byte a 200002.0 +signed byte benchmarkLandscape::c +signed byte benchmarkLandscape::c#1 c zp[1]:130 10001.0 +signed byte benchmarkLandscape::c#2 c zp[1]:130 2727.5454545454545 +const byte* benchmarkLandscape::colHeight[$e] = { fill( $e, 0) } +byte benchmarkLandscape::i +byte benchmarkLandscape::i#1 reg byte x 1501.5 +byte benchmarkLandscape::i#2 reg byte x 2002.0 +byte* benchmarkLandscape::screenAddress +byte* benchmarkLandscape::screenAddress#0 screenAddress zp[2]:131 2002.0 +byte* benchmarkLandscape::screenAddress#1 screenAddress zp[2]:131 100001.0 +byte* benchmarkLandscape::screenAddress#2 screenAddress zp[2]:131 52500.75 +byte* benchmarkLandscape::screenAddress#4 screenAddress zp[2]:131 7001.0 +byte benchmarkLandscape::start +byte benchmarkLandscape::start#1 reg byte x 200002.0 +byte benchmarkLandscape::start#3 reg byte x 44286.28571428572 +byte benchmarkLandscape::start#5 reg byte x 6667.333333333333 +byte benchmarkLandscape::start#7 reg byte x 20002.0 +byte benchmarkLandscape::stop +byte benchmarkLandscape::stop#0 stop zp[1]:133 12000.300000000001 +byte benchmarkLandscape::uc +signed byte benchmarkLandscape::x +signed byte benchmarkLandscape::x#1 x zp[1]:129 2002.0 +signed byte benchmarkLandscape::x#2 x zp[1]:129 250.25 +byte benchmarkLandscape::z +byte benchmarkLandscape::z#1 z zp[1]:128 151.5 +byte benchmarkLandscape::z#8 z zp[1]:128 9.181818181818182 +const byte* landscapeBase[] = kickasm {{ .fill 14, 0 + }} +const nomodify byte* lms = (byte*) 40960 +void main() + +zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +reg byte x [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] +zp[1]:129 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +zp[1]:130 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +zp[2]:131 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] +reg byte x [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] +zp[1]:65 [ benchmarkCountdownFor::a ] +zp[1]:75 [ benchmarkCountdownFor::b ] +zp[1]:133 [ benchmarkLandscape::stop#0 ] +zp[1]:134 [ benchmarkLandscape::$5 ] +reg byte a [ benchmarkLandscape::$6 ] +reg byte a [ benchmarkLandscape::$7 ] + + +FINAL ASSEMBLER +Score: 649273 + + // File Comments +// Demonstrates problem where reserved ZP addresses can still be coalesced if they are explicitly __address() assigned to variables +// https://gitlab.com/camelot/kickc/-/issues/550 + // Upstart + // Atari XL/XE executable XEX file with a single segment +// https://www.atarimax.com/jindroush.atari.org/afmtexe.html +.file [name="zp-reserve-coalesce-problem.xex", type="bin", segments="XexFile"] +.segmentdef XexFile +.segment XexFile +// Binary File Header +.byte $ff, $ff +// Program segment [start address, end address, data] +.word ProgramStart, ProgramEnd-1 +.segmentout [ segments="Program" ] +// RunAd - Run Address Segment [start address, end address, data] +.word $02e0, $02e1 +.word main +.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"] +.segmentdef ProgramStart [start=$2000] +.segment ProgramStart +ProgramStart: +.segmentdef Code [startAfter="ProgramStart"] +.segmentdef Data [startAfter="Code"] +.segmentdef ProgramEnd [startAfter="Data"] +.segment ProgramEnd +ProgramEnd: + + // Global Constants & labels + .label lms = $a000 +.segment Code + // main +main: { + // benchmarkCountdownFor() + // [1] call benchmarkCountdownFor + jsr benchmarkCountdownFor + // [2] phi from main to main::@1 [phi:main->main::@1] + // main::@1 + // benchmarkLandscape() + // [3] call benchmarkLandscape + // [14] phi from main::@1 to benchmarkLandscape [phi:main::@1->benchmarkLandscape] + jsr benchmarkLandscape + // main::@return + // } + // [4] return + rts +} + // benchmarkCountdownFor +benchmarkCountdownFor: { + .label a = $41 + .label b = $4b + // a + // [5] benchmarkCountdownFor::a = 0 -- vbsz1=vbsc1 + lda #0 + sta.z a + // b + // [6] benchmarkCountdownFor::b = 0 -- vbsz1=vbsc1 + sta.z b + // a = 1 + // [7] benchmarkCountdownFor::a = 1 -- vbsz1=vbsc1 + lda #1 + sta.z a + // benchmarkCountdownFor::@1 + __b1: + // for(a = 1; a >= 0; a--) + // [8] if(benchmarkCountdownFor::a>=0) goto benchmarkCountdownFor::@2 -- vbsz1_ge_0_then_la1 + lda.z a + cmp #0 + bpl __b2 + // benchmarkCountdownFor::@return + // } + // [9] return + rts + // benchmarkCountdownFor::@2 + __b2: + // b = 9 + // [10] benchmarkCountdownFor::b = 9 -- vbsz1=vbsc1 + lda #9 + sta.z b + // benchmarkCountdownFor::@3 + __b3: + // for(b = 9; b >= 0; b--) + // [11] if(benchmarkCountdownFor::b>=0) goto benchmarkCountdownFor::@4 -- vbsz1_ge_0_then_la1 + lda.z b + cmp #0 + bpl __b4 + // benchmarkCountdownFor::@5 + // for(a = 1; a >= 0; a--) + // [12] benchmarkCountdownFor::a = -- benchmarkCountdownFor::a -- vbsz1=_dec_vbsz1 + dec.z a + jmp __b1 + // benchmarkCountdownFor::@4 + __b4: + // for(b = 9; b >= 0; b--) + // [13] benchmarkCountdownFor::b = -- benchmarkCountdownFor::b -- vbsz1=_dec_vbsz1 + dec.z b + jmp __b3 +} + // benchmarkLandscape +benchmarkLandscape: { + .label __5 = $86 + .label screenAddress = $83 + .label z = $80 + .label stop = $85 + .label x = $81 + .label c = $82 + // [15] phi from benchmarkLandscape to benchmarkLandscape::@1 [phi:benchmarkLandscape->benchmarkLandscape::@1] + // [15] phi benchmarkLandscape::z#8 = 0 [phi:benchmarkLandscape->benchmarkLandscape::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z z + // [15] phi from benchmarkLandscape::@5 to benchmarkLandscape::@1 [phi:benchmarkLandscape::@5->benchmarkLandscape::@1] + // [15] phi benchmarkLandscape::z#8 = benchmarkLandscape::z#1 [phi:benchmarkLandscape::@5->benchmarkLandscape::@1#0] -- register_copy + // benchmarkLandscape::@1 + __b1: + // [16] phi from benchmarkLandscape::@1 to benchmarkLandscape::@2 [phi:benchmarkLandscape::@1->benchmarkLandscape::@2] + // [16] phi benchmarkLandscape::i#2 = 0 [phi:benchmarkLandscape::@1->benchmarkLandscape::@2#0] -- vbuxx=vbuc1 + ldx #0 + // [16] phi from benchmarkLandscape::@2 to benchmarkLandscape::@2 [phi:benchmarkLandscape::@2->benchmarkLandscape::@2] + // [16] phi benchmarkLandscape::i#2 = benchmarkLandscape::i#1 [phi:benchmarkLandscape::@2->benchmarkLandscape::@2#0] -- register_copy + // benchmarkLandscape::@2 + __b2: + // colHeight[i] = landscapeBase[i] + // [17] benchmarkLandscape::colHeight[benchmarkLandscape::i#2] = landscapeBase[benchmarkLandscape::i#2] -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx + lda landscapeBase,x + sta colHeight,x + // for (char i: 0..13) + // [18] benchmarkLandscape::i#1 = ++ benchmarkLandscape::i#2 -- vbuxx=_inc_vbuxx + inx + // [19] if(benchmarkLandscape::i#1!=$e) goto benchmarkLandscape::@2 -- vbuxx_neq_vbuc1_then_la1 + cpx #$e + bne __b2 + // [20] phi from benchmarkLandscape::@2 to benchmarkLandscape::@3 [phi:benchmarkLandscape::@2->benchmarkLandscape::@3] + // [20] phi benchmarkLandscape::x#2 = $27 [phi:benchmarkLandscape::@2->benchmarkLandscape::@3#0] -- vbsz1=vbsc1 + lda #$27 + sta.z x + // benchmarkLandscape::@3 + __b3: + // for (signed char x = 39; x >= 0; x--) + // [21] if(benchmarkLandscape::x#2>=0) goto benchmarkLandscape::@4 -- vbsz1_ge_0_then_la1 + lda.z x + cmp #0 + bpl __b4 + // benchmarkLandscape::@5 + // for(char z: 0..9) + // [22] benchmarkLandscape::z#1 = ++ benchmarkLandscape::z#8 -- vbuz1=_inc_vbuz1 + inc.z z + // [23] if(benchmarkLandscape::z#1!=$a) goto benchmarkLandscape::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #$a + cmp.z z + bne __b1 + // benchmarkLandscape::@return + // } + // [24] return + rts + // benchmarkLandscape::@4 + __b4: + // screenAddress = lms + x + // [25] benchmarkLandscape::screenAddress#0 = lms + benchmarkLandscape::x#2 -- pbuz1=pbuc1_plus_vbsz2 + lda.z x + clc + adc #lms + sta.z screenAddress+1 + // [26] phi from benchmarkLandscape::@4 to benchmarkLandscape::@6 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6] + // [26] phi benchmarkLandscape::screenAddress#4 = benchmarkLandscape::screenAddress#0 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#0] -- register_copy + // [26] phi benchmarkLandscape::start#5 = 0 [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#1] -- vbuxx=vbuc1 + ldx #0 + // [26] phi benchmarkLandscape::c#2 = $d [phi:benchmarkLandscape::@4->benchmarkLandscape::@6#2] -- vbsz1=vbsc1 + lda #$d + sta.z c + // benchmarkLandscape::@6 + __b6: + // for (signed char c = 13; c >= 0; c--) + // [27] if(benchmarkLandscape::c#2>=0) goto benchmarkLandscape::@7 -- vbsz1_ge_0_then_la1 + lda.z c + cmp #0 + bpl __b7 + // benchmarkLandscape::@8 + // for (signed char x = 39; x >= 0; x--) + // [28] benchmarkLandscape::x#1 = -- benchmarkLandscape::x#2 -- vbsz1=_dec_vbsz1 + dec.z x + // [20] phi from benchmarkLandscape::@8 to benchmarkLandscape::@3 [phi:benchmarkLandscape::@8->benchmarkLandscape::@3] + // [20] phi benchmarkLandscape::x#2 = benchmarkLandscape::x#1 [phi:benchmarkLandscape::@8->benchmarkLandscape::@3#0] -- register_copy + jmp __b3 + // benchmarkLandscape::@7 + __b7: + // stop = colHeight[uc] + // [29] benchmarkLandscape::stop#0 = benchmarkLandscape::colHeight[(byte)benchmarkLandscape::c#2] -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z c + lda colHeight,y + sta.z stop + // [30] phi from benchmarkLandscape::@10 benchmarkLandscape::@7 to benchmarkLandscape::@9 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9] + // [30] phi benchmarkLandscape::screenAddress#2 = benchmarkLandscape::screenAddress#1 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9#0] -- register_copy + // [30] phi benchmarkLandscape::start#3 = benchmarkLandscape::start#1 [phi:benchmarkLandscape::@10/benchmarkLandscape::@7->benchmarkLandscape::@9#1] -- register_copy + // benchmarkLandscape::@9 + __b9: + // while (start < stop) + // [31] if(benchmarkLandscape::start#3= 0; c--) + // [32] benchmarkLandscape::c#1 = -- benchmarkLandscape::c#2 -- vbsz1=_dec_vbsz1 + dec.z c + // [33] benchmarkLandscape::start#7 = benchmarkLandscape::stop#0 -- vbuxx=vbuz1 + ldx.z stop + // [26] phi from benchmarkLandscape::@11 to benchmarkLandscape::@6 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6] + // [26] phi benchmarkLandscape::screenAddress#4 = benchmarkLandscape::screenAddress#2 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#0] -- register_copy + // [26] phi benchmarkLandscape::start#5 = benchmarkLandscape::start#7 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#1] -- register_copy + // [26] phi benchmarkLandscape::c#2 = benchmarkLandscape::c#1 [phi:benchmarkLandscape::@11->benchmarkLandscape::@6#2] -- register_copy + jmp __b6 + // benchmarkLandscape::@10 + __b10: + // (*screenAddress) & 0xf + // [34] benchmarkLandscape::$5 = *benchmarkLandscape::screenAddress#2 & $f -- vbuz1=_deref_pbuz2_band_vbuc1 + lda #$f + ldy #0 + and (screenAddress),y + sta.z __5 + // uc << 4 + // [35] benchmarkLandscape::$6 = (byte)benchmarkLandscape::c#2 << 4 -- vbuaa=vbuz1_rol_4 + lda.z c + asl + asl + asl + asl + // ((*screenAddress) & 0xf) | (uc << 4) + // [36] benchmarkLandscape::$7 = benchmarkLandscape::$5 | benchmarkLandscape::$6 -- vbuaa=vbuz1_bor_vbuaa + ora.z __5 + // *screenAddress = ((*screenAddress) & 0xf) | (uc << 4) + // [37] *benchmarkLandscape::screenAddress#2 = benchmarkLandscape::$7 -- _deref_pbuz1=vbuaa + sta (screenAddress),y + // screenAddress += 40 + // [38] benchmarkLandscape::screenAddress#1 = benchmarkLandscape::screenAddress#2 + $28 -- pbuz1=pbuz1_plus_vbuc1 + lda #$28 + clc + adc.z screenAddress + sta.z screenAddress + bcc !+ + inc.z screenAddress+1 + !: + // start++; + // [39] benchmarkLandscape::start#1 = ++ benchmarkLandscape::start#3 -- vbuxx=_inc_vbuxx + inx + jmp __b9 + .segment Data + colHeight: .fill $e, 0 +} + // File Data +landscapeBase: +.fill 14, 0 + + diff --git a/src/test/ref/zp-reserve-coalesce-problem.sym b/src/test/ref/zp-reserve-coalesce-problem.sym new file mode 100644 index 000000000..cc7c938d8 --- /dev/null +++ b/src/test/ref/zp-reserve-coalesce-problem.sym @@ -0,0 +1,50 @@ +void benchmarkCountdownFor() +signed byte benchmarkCountdownFor::a loadstore !zp[-1]:65 zp[1]:65 54.16666666666666 +signed byte benchmarkCountdownFor::b loadstore !zp[-1]:75 zp[1]:75 1038.3333333333335 +void benchmarkLandscape() +byte~ benchmarkLandscape::$5 zp[1]:134 100001.0 +byte~ benchmarkLandscape::$6 reg byte a 200002.0 +byte~ benchmarkLandscape::$7 reg byte a 200002.0 +signed byte benchmarkLandscape::c +signed byte benchmarkLandscape::c#1 c zp[1]:130 10001.0 +signed byte benchmarkLandscape::c#2 c zp[1]:130 2727.5454545454545 +const byte* benchmarkLandscape::colHeight[$e] = { fill( $e, 0) } +byte benchmarkLandscape::i +byte benchmarkLandscape::i#1 reg byte x 1501.5 +byte benchmarkLandscape::i#2 reg byte x 2002.0 +byte* benchmarkLandscape::screenAddress +byte* benchmarkLandscape::screenAddress#0 screenAddress zp[2]:131 2002.0 +byte* benchmarkLandscape::screenAddress#1 screenAddress zp[2]:131 100001.0 +byte* benchmarkLandscape::screenAddress#2 screenAddress zp[2]:131 52500.75 +byte* benchmarkLandscape::screenAddress#4 screenAddress zp[2]:131 7001.0 +byte benchmarkLandscape::start +byte benchmarkLandscape::start#1 reg byte x 200002.0 +byte benchmarkLandscape::start#3 reg byte x 44286.28571428572 +byte benchmarkLandscape::start#5 reg byte x 6667.333333333333 +byte benchmarkLandscape::start#7 reg byte x 20002.0 +byte benchmarkLandscape::stop +byte benchmarkLandscape::stop#0 stop zp[1]:133 12000.300000000001 +byte benchmarkLandscape::uc +signed byte benchmarkLandscape::x +signed byte benchmarkLandscape::x#1 x zp[1]:129 2002.0 +signed byte benchmarkLandscape::x#2 x zp[1]:129 250.25 +byte benchmarkLandscape::z +byte benchmarkLandscape::z#1 z zp[1]:128 151.5 +byte benchmarkLandscape::z#8 z zp[1]:128 9.181818181818182 +const byte* landscapeBase[] = kickasm {{ .fill 14, 0 + }} +const nomodify byte* lms = (byte*) 40960 +void main() + +zp[1]:128 [ benchmarkLandscape::z#8 benchmarkLandscape::z#1 ] +reg byte x [ benchmarkLandscape::i#2 benchmarkLandscape::i#1 ] +zp[1]:129 [ benchmarkLandscape::x#2 benchmarkLandscape::x#1 ] +zp[1]:130 [ benchmarkLandscape::c#2 benchmarkLandscape::c#1 ] +zp[2]:131 [ benchmarkLandscape::screenAddress#4 benchmarkLandscape::screenAddress#2 benchmarkLandscape::screenAddress#0 benchmarkLandscape::screenAddress#1 ] +reg byte x [ benchmarkLandscape::start#3 benchmarkLandscape::start#1 benchmarkLandscape::start#5 benchmarkLandscape::start#7 ] +zp[1]:65 [ benchmarkCountdownFor::a ] +zp[1]:75 [ benchmarkCountdownFor::b ] +zp[1]:133 [ benchmarkLandscape::stop#0 ] +zp[1]:134 [ benchmarkLandscape::$5 ] +reg byte a [ benchmarkLandscape::$6 ] +reg byte a [ benchmarkLandscape::$7 ]