// peeph.def - Common Z80 and gbz80 peephole rules // // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2020 // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, or (at your option) any // later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. replace restart { ld %1, %1 } by { ; common peephole 0 removed redundant load from %1 into %1. } if notVolatile(%1) replace restart { ld %1, %2 } by { ; common peephole 1 removed dead load from %2 into %1. } if notVolatile(%1), notUsed(%1), notVolatile(%2), notSame(%1 '(hl+)' '(hl-)'), notSame(%2 '(hl+)' '(hl-)') replace restart { %1 hl, %2 } by { ; common peephole 2a removed %1 hl,%2 due to unused result. } if same(%1 'adc' 'add' 'sbc'), notUsed('hl' 'f') replace restart { %1 %2 } by { ; common peephole 2b removed %1 %2 due to unused result. } if same(%1 'dec' 'inc'), same(%2 'bc' 'de' 'hl' 'sp' 'ix' 'iy'), notUsed(%2) replace restart { ld %1, %2 + %3 } by { ; common peephole 3 removed dead load from %2 + %3 into %1. } if notVolatile(%1), notUsed(%1), notSame(%1 '(hl+)' '(hl-)') // Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail. replace restart { ld %1, (%2) } by { ld %1, 0 (%2) ; common peephole 4a made 0 offset explicit. } if same(%2 'ix' 'iy') replace restart { ld (%1), %2 } by { ld 0 (%1), %2 ; common peephole 4b made 0 offset explicit. } if same(%1 'ix' 'iy') //remove dead INC/DEC instructions on 16-bit registers replace restart { %1 %2 } by { ; common peephole 5 removed dead %1 %2. } if same(%1 'inc' 'dec'), same(%2 'bc' 'de' 'hl' 'sp' 'ix' 'iy'), notUsed(%2) //remove dead INC/DEC instructions on 8-bit registers replace restart { %1 %2 } by { ; common peephole 6a removed dead %1 %2 } if same(%1 'inc' 'dec'), same(%2 'a' 'b' 'c' 'd' 'e' 'h' 'l' 'ixh' 'ixl' 'iyh' 'iyl'), notUsed(%2 'f') //remove dead ALU instructions on 8-bit register replace restart { %1 a, %2 } by { ; common peephole 6b removed dead %1 a, %2 } if same(%1 'sub' 'sbc' 'add' 'adc' 'and' 'or' 'xor'), notUsed('af') //remove dead CP instructions replace restart { cp a, %1 } by { ; common peephole 6c removed dead cp a, %1 } if notUsed('f') replace restart { %1 %2 } by { ; common peephole 6d removed dead %1 %2 } if same(%1 'rlc' 'rl' 'rrc' 'rr' 'sla' 'sra' 'srl' 'sll' 'sli'), notVolatile(%2), notUsed(%2 'f') replace restart { ld %1, %2 (%3) } by { ; common peephole 7 removed dead load from %2 (%3) into %1. } if notUsed(%1), same(%3 'ix' 'iy') // Should probably check for notVolatile(), but gives many false positives and no regression tests fail. replace { ex de, hl ex de, hl } by { ; common peephole 8 removed double de/hl swap. } replace restart { ld %1, %2 ld %3, %1 } by { ; common peephole 9 loaded %3 from %2 directly instead of going through %1. ld %3, %2 } if canAssign(%3 %2), notVolatile(%1), notUsed(%1), notSame(%3 '(hl)' '(de)' '(bc)' '(hl+)' '(hl-)'), notSame(%1 '(hl+)' '(hl-)') replace restart { ld %1, %2 ld %3, %1 } by { ; common peephole 9a loaded %3 from %2 directly instead of going through %1. ld %3, %2 } if canAssign(%3 %2), notVolatile(%1), notUsed(%1), canAssign('a' %1), notSame(%1 '(hl+)' '(hl-)') replace restart { ld %1, hl ld hl, %1 } by { ; common peephole 9b reused value still in hl. ld %1, hl } if notVolatile(%1), notSame(%1 '(hl+)' '(hl-)') replace restart { ld %1, %2 ld %3, %4 ld %5, %1 } by { ld %5, %2 ; common peephole 10 loaded %5 from %2 directly instead of going through %1. ld %3, %4 } if canAssign(%5 %2), notVolatile(%1), operandsNotRelated(%1 %4), operandsNotRelated(%1 %3), operandsNotRelated(%3 %5), operandsNotRelated(%4 %5), notUsed(%1), notSame(%3 %4 '(hl)' '(de)' '(bc)' '(hl+)' '(hl-)'), notVolatile(%5), notSame(%1 '(hl+)' '(hl-)'), notSame(%5 '(hl+)' '(hl-)') // Rule OK unless both %5 and %4 are volatile, but we can't express that directly. replace restart { ld %3 (ix), %1 ld %4 (ix), %2 ld %5, %3 (ix) ld %6, %4 (ix) } by { ld %3 (ix), %1 ld %4 (ix), %2 ; common peephole 11 loaded %5%6 from %1%2 directly instead of going through %3 (ix) %4 (ix). ld %5, %1 ld %6, %2 } if canAssign(%5 %1), canAssign(%6 %2), notSame(%5 %2) replace restart { ld %1, %2 (%3) ld %4, %1 } by { ; common peephole 12 loaded %2 (%3) into %4 directly instead of going through %1. ld %4, %2 (%3) } if canAssign(%4 %2 %3), notVolatile(%1), notUsed(%1) replace restart { ld %1, %2 ld %3 (%4), %1 } by { ; common peephole 13 loaded %2 into %3 (%4) directly instead of going through %1. ld %3 (%4), %2 } if canAssign(%3 %4 %2), notVolatile(%1), notUsed(%1), canAssign('a' %1) // canAssign ('a' %1) checks that %1 is an 8-bit value replace restart { ld %1, %2 (%3) ld %4, %5 (%6) ld %7, %1 } by { ld %7, %2 (%3) ; common peephole 14 loaded %2 (%3) into %7 directly instead of going through %1. ld %4, %5 (%6) } if canAssign(%7 %2 %3), notVolatile(%1), notUsed(%1), notSame(%1 %4), notSame(%7 %4) replace restart { ld %1, %2 (%3) ld %4, %5 ld %7, %1 } by { ld %7, %2 (%3) ; common peephole 15 loaded %2 (%3) into %7 directly instead of going through %1. ld %4, %5 } if canAssign(%7 %2 %3), notVolatile(%1), notUsed(%1), operandsNotRelated(%1 %5), operandsNotRelated(%7 %4), operandsNotRelated(%7 %5), notSame(%4 '(hl)' '(de)' '(bc)' '(hl+)' '(hl-)'), notSame(%5 '(hl)' '(de)' '(bc)' '(hl+)' '(hl-)' '(iy)') replace restart { ld %1,#%2 ld a,%3 (%1) } by { ; common peephole 16 loaded %2 into a directly instead of going through %1. ld a,(#%2 + %3) } if notUsed(%1) replace restart { ld hl, #%1 ld a, (hl) } by { ld a, (#%1) ; common peephole 17 loaded a from (#%1) directly instead of using hl. } if notUsed('hl') replace restart { ld hl,#%1 + %2 ld a,(hl) } by { ; common peephole 18 loaded %2 into a directly instead of using hl. ld a, (#%1 + %2) } if notUsed('hl') replace restart { ld hl,#%1 ld (hl),a } by { ld (#%1),a ; common peephole 19 loaded (#%1) from a directly instead of using hl. } if notUsed('hl') replace restart { ld hl,#%1 + %2 ld (hl),a } by { ld (#%1 + %2),a ; common peephole 20 loaded (#%1) from a directly instead of using hl. } if notUsed('hl') replace restart { ld a, %1 (%2) %3 a ld %1 (%2), a } by { %3 %1 (%2) ld a, %1 (%2) ; common peephole 21 shifted in (%2) instead of a. } if same(%3 'srl' 'sla' 'rl' 'rr' 'rlc' 'rrc' 'sll') replace restart { ld %1,(hl) ld a,%2 (%3) %4 a,%1 } by { ld a,%2 (%3) ; common peephole 22 used (hl) in %4 directly instead of going through %1. %4 a,(hl) } if notVolatile(%1), notUsed(%1), same(%4 'add' 'adc' 'sub' 'sbc' 'and' 'or' 'xor') replace restart { ld l, %1 ld h, %2 ld a, (hl) inc hl ld h, (hl) ld l, a } by { ld a, (%3) ld l, a inc %3 ld a, (%3) ld h, a ; common peephole 23 optimize 16-bit load from %3. } if canJoinRegs(%2 %1 %3), notUsed(%3 'a') replace restart { inc %1 ld l, %2 ld h, %3 } by { ld l, %2 ld h, %3 ; common peephole 24 incremented in hl instead of %1. inc hl } if canJoinRegs(%3 %2 %4), same(%1 %4), notUsed(%1) replace restart { ld %1, l ld %2, h ld a, #%3 ld (%4), a } by { ld %1, l ld %2, h ld (hl), #%3 ; common peephole 25 loaded #%1 into (hl) instead of (%4). } if canJoinRegs(%2 %1 %5), same(%4 %5), notUsed('a') replace restart { push de ex de, hl } by { ; common peephole 26a moved push after de/hl swap. ex de, hl push hl } replace restart { push hl ex de, hl } by { ; common peephole 26b moved push after de/hl swap. ex de, hl push de } replace restart { ex de, hl push %1 } by { ; common peephole 26c moved push %1 before de/hl swap. push %1 ex de, hl } if notSame(%1 'hl' 'de') replace restart { ex de, hl push de } by { ; common peephole 26d pushed hl directly instead of going through de. push hl } if notUsed('de' 'hl') replace restart { ld l,%1 ld h,d push hl } by { ; common peephole 27 pushed de instead of hl removing a load. ld e,%1 push de } if notUsed('hl' 'e') //TODO: remove if unused replace restart { ex de, hl push %1 push de } by { ; common peephole 28 pushed hl directly instead of going through de. push %1 push hl } if notSame(%1 'hl' 'de'), notUsed('de' 'hl') replace restart { ld %4,%1 ld %5,%2 push %6 } by { ; common peephole 29 pushed %3 directly instead of going through %6. push %3 } if canJoinRegs(%2 %1 %3), canJoinRegs(%5 %4 %7), same(%7 %6), notUsed(%6) replace restart { ld %2,%5 ld %3,%6 push %1 push %4 } by { ; common peephole 30 pushed %7 directly instead of going through %4. push %1 push %7 } if canJoinRegs(%3 %2 %5), same(%5 %4), canJoinRegs(%6 %5 %7), notSame(%1 %4), notUsed(%4) replace restart { pop %1 ld %2, %3 ld %4, %5 } by { ; common peephole 31 popped %6 directly instead of going through %1. pop %6 } if canJoinRegs(%4 %2 %6), canJoinRegs(%5 %3 %7), same(%7 %1), notUsed(%1) replace restart { ex de, hl ld e, l ld d, h } by { ; common peephole 32a removed de/hl swap. ld l, e ld h, d } replace restart { ex de, hl ld l, e ld h, d } by { ; common peephole 32b removed de/hl swap. ld e, l ld d, h } replace restart { ld %1 (%4), %2 ld %3, %1 (%4) } by { ; common peephole 33 loaded %3 from %2 instead of going through %1 (%4). ld %1 (%4), %2 ld %3, %2 } if same(%4 'ix' 'iy'), canAssign(%3 %2) // Don't need to check for volatile, since ix is used for the stack. replace restart { ld %1 (%3), a push %4 ld %2, %1 (%3) } by { ld %1 (%3), a push %4 ; common peephole 34 loaded %2 from a instead of %1 (%3) ld %2, a } if same(%3 'ix' 'iy'), canAssign(%2 'a') replace restart { push af inc sp ld a,e push af inc sp } by { ; common peephole 35 pushed de instead of pushing a twice. ld d,a push de } if notUsed('d'), notUsed('a') replace restart { push af inc sp ld a,#%1 push af inc sp } by { ; common peephole 36 pushed de instead of pushing a twice. ld d,a ld e,#%1 push de } if notUsed('de') replace restart { push af inc sp ld a, #%1 push af inc sp } by { ; common peephole 37 pushed bc instead of pushing a twice. ld %2, a ld %3, #%1 push %4 } if unusedReg(%4 'bc' 'de' 'hl'), canSplitReg(%4 %2 %3) replace restart { push %1 inc sp push %2 inc sp } by { ld %4, %5 ; common peephole 38 combined pushing of %3 and %5. push %1 } if canSplitReg(%1 %3 %4), canSplitReg(%2 %5), notUsed(%4) replace restart { ld hl, #%1 add hl, %2 } by { ; common peephole 39 replaced 16-bit addition by 8-bit loads and 16-bit increment. ld l, %4 ld h, %3 inc hl } if canSplitReg(%2 %3 %4), immdInRange(1 1 '+' %1 0 %9) replace restart { push af inc sp ld a, c push af inc sp } by { ld b, a ; common peephole 42 combined pushing of a and c. push bc } if notUsed('b'), notUsed('a') replace restart { push %1 inc sp ld a, %2 push af inc sp } by { ld %4, %2 ; common peephole 43 combined pushing of %3 and %2. push %1 } if notSame(%1 'iy'), canSplitReg(%1 %3 %4), canAssign(%4 %2), notUsed(%4 'a') replace restart { ld a, %1 push af inc sp ld a, %2 (%3) push af inc sp } by { ld %4, %1 ld %5, %2 (%3) ; common peephole 44 combined pushing of %1 and %2 (%3). push %6 } if unusedReg(%6 'bc' 'de' 'hl'), canSplitReg(%6 %4 %5), canAssign(%4 %1), notUsed('a') replace restart { ld %1, #%2 } by { ; common peephole 45 replace 16-bit immediate load by 8-bit one. ld %3, #%4 } if canSplitReg(%1 %5 %3), immdInRange(0x00 0xff '&' %2 0xff %4), canAssign(%3 %4), notUsed(%5) replace restart { ld %1, #%2 } by { ; common peephole 46 replace 16-bit immediate load by 8-bit one. ld %3, #%4 } if canSplitReg(%1 %3 %5), immdInRange(0x00 0xff '/' %2 256 %4), canAssign(%3 %4), notUsed(%5) replace restart { ld a, %1 (%3) push af inc sp ld a, %2 (%3) push af inc sp } by { ; common peephole 47 pushed %1 (%3), %2 (%3) through %6 instead of af. ld %4, %1 (%3) ld %5, %2 (%3) push %6 } if unusedReg(%6 'bc' 'de' 'hl'), canSplitReg(%6 %4 %5), notUsed('a') replace restart { ld %1, %4 ld %2, %5 push %3 } by { ; common peephole 48 pushed %6 instead of %3. push %6 } if canJoinRegs(%2 %1 %7), same(%3 %7), canJoinRegs(%5 %4 %6), notUsed(%3) replace restart { ld a, (hl) inc hl ld h, (hl) ld l, a push hl } by { ; common peephole 49 pushed %3 instead of hl. ld %1, (hl) inc hl ld %2, (hl) push %3 } if unusedReg(%3 'de' 'bc'), canSplitReg(%3 %2 %1), notUsed('hl') replace restart { ld %3, %1 push %3 } by { ; common peephole 49a pushed %2 instead of %3. ld %2, %1 push %2 } if same(%3 'ix' 'iy'), notUsed(%3), unusedReg(%2 'bc' 'de' 'hl') replace restart { pop %1 push %1 } by { ; common peephole 50 eleminated dead pop/push pair. } if notUsed(%1) replace restart { pop %1 ld %2 (ix), %3 push %1 } by { ; common peephole 51 eleminated dead pop/push pair. ld %2 (ix), %3 } if notUsed(%1), operandsNotRelated(%1 %3) replace restart { push %1 pop %2 } by { ld %6, %4 ld %5, %3 ; common peephole 52 replaced push/pop pair by loads. } if canSplitReg(%1 %3 %4), canSplitReg(%2 %5 %6), notSame(%1 %2 'ix' 'iy'), notUsed(%1) replace restart { ld %3, #%1 ld %4, %2 (%3) } by { ; common peephole 53 used direct memory loading instead of indirect. ld a, (#%1 + %2) ld %4, a } if notUsed(%3 'a') replace restart { ld %4, #%1 %3 %5, %2 (%4) } by { ; common peephole 54 used hl instead of %4. ld hl, #%1 + %2 %3 %5, (hl) } if notUsed(%4 'hl'), same(%5 'a' 'b' 'c' 'd' 'e' 'h' 'l'), same(%3 'add' 'adc' 'and' 'ld' 'or' 'sbc' 'sub' 'xor') replace restart { ld %4, #%1 ld h, %3 (%4) } by { ; common peephole 55 used hl instead of %4. ld hl, #%1 + %3 ld h, (hl) } if notUsed(%4 'l') replace restart { ld %4, #%1 ld %2 (%4), %3 } by { ; common peephole 56 used hl instead of %4. ld hl, #%1 + %2 ld (hl), %3 } if notUsed(%4 'hl'), notSame(%3 'h' 'l') replace restart { ld %4, #%1 ld %2 (%4), %3 } by { ; common peephole 57 used direct memory storing instead of indirect. ld a, %3 ld (#%1 + %2), a } if notUsed('a' %4) replace restart { ld %4, #%1 ld %2, %5 (%4) ld %3, %6 (%4) } by { ; common peephole 58 used hl instead of %4. ld hl, #%1 + %5 ld %2, (hl) inc hl ld %3, (hl) } if operandsNotRelated(%2 'hl'), operandsNotRelated(%3 'hl'), immdInRange(-128 127 '+' %5 1 %7), same(%6 %7), notUsed(%4 'hl') replace restart { ld %4, #%1 ld %2 (%4), %3 ld l, %2 (%4) } by { ; common peephole 59 used hl instead of %4. ld hl, #%1 + %2 ld (hl), %3 ld l, (hl) } if notUsed(%4 'h') replace restart { ld %3, #%1 ld %2 (%3), %4 } by { ; common peephole 60 used hl instead of %3. ld hl, #%1 + %2 ld (hl), %4 } if notUsed(%3 'hl'), operandsNotRelated(%4 'hl') replace restart { ld %4, #%1 %5 %2, %3 (%4) } by { ; common peephole 61 used hl instead of %4. ld hl, #%1 + %3 %5 %2, (hl) } if same(%5 'bit' 'res' 'set'), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp ld %2, %5 (%4) ld %3, %6 (%4) } by { ; common peephole 62 used hl instead of %4. ld hl, #%1 + %5 add hl, sp ld %2, (hl) inc hl ld %3, (hl) } if operandsNotRelated(%2 'hl'), immdInRange(-128 127 '+' %5 1 %7), same(%7 %6), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp ld %2, %3 (%4) } by { ; common peephole 63 used hl instead of %4. ld hl, #%1 + %3 add hl, sp ld %2, (hl) } if notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp ld l, %2 (%4) ld h, %3 (%4) } by { ; common peephole 64 used hl instead of %4. ld hl, #%1 + %2 add hl, sp ld a, (hl) inc hl ld h, (hl) ld l, a } if immdInRange(-128 127 '+' %2 1 %5), same(%5 %3), notUsed(%4 'a') replace restart { ld %4, #%1 add %4, sp ld %5 (iy), #%2 ld %6 (iy), #%3 } by { ; common peephole 65 used hl instead of %4. ld hl, #%1 + %5 add hl, sp ld (hl), #%2 inc hl ld (hl), #%3 } if immdInRange(-128 127 '+' %5 1 %7), same(%7 %6), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp ld a, %2 (%4) or a, %3 (%4) } by { ld hl, #%1 + %2 add hl, sp ld a, (hl) inc hl or a, (hl) ; common peephole 66a used hl instead of %4. } if immdInRange(-128 127 '+' %2 1 %5), same(%5 %3), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp ld a, %2 (%4) or a, %3 (%4) } by { ld hl, #%1 + %3 add hl, sp ld a, (hl) inc hl or a, (hl) ; common peephole 66b used hl instead of %4. } if immdInRange(-128 127 '-' %2 1 %5), same(%5 %3), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp %5 %2, %3 (%4) } by { ld hl, #%1 + %3 add hl, sp %5 %2, (hl) ; common peephole 67 used hl instead of %4. } if same(%5 'bit' 'res' 'set'), notUsed(%4 'hl') replace restart { ld %4, #%1 add %4, sp %5 %3, %2 (%4) } by { ld hl, #%1 + %2 add hl, sp %5 %3, (hl) ; common peephole 68 used hl instead of %4. } if same(%5 'adc' 'add' 'and' 'ld' 'or' 'sbc' 'sub' 'xor'), notUsed(%4 'hl') replace restart { ld %1, l ld %2, h inc %3 } by { ; common peephole 69 incremented in hl instead of %3. inc hl ld %1, l ld %2, h } if canJoinRegs(%2 %1 %4), same(%4 %3), notUsed('hl') replace restart { ld %4, #%1 %3 %2 (%4) } by { ; common peephole 70 %3 (hl) instead of %2 (%4). ld hl, #%1 + %2 %3 (hl) } if same(%3 'inc' 'dec'), notUsed(%4 'hl') replace restart { ld %1, %2 push %3 inc sp } by { ; common peephole 71 eliminate unnecessary initialization of %1 register. push %3 inc sp } if same(%1 'c' 'e' 'l' 'ixl' 'iyl'), canJoinRegs('' %1 %4), same(%3 %4), notUsed(%1) replace restart { ld a, %1 (%2) bit %3, a } by { ; common peephole 72 tested bit %3 of %1 (%2) directly instead of going through a. bit %3, %1 (%2) } if notUsed('a') replace restart { ld %1, (hl) bit %2, %1 } by { ; common peephole 73 tested bit %2 of (hl) directly instead of going through %1. bit %2, (hl) } if notUsed(%1) replace restart { ld a, %1 bit %2, a } by { ; common peephole 74 tested bit %2 of %1 directly instead of going through a. bit %2, %1 } if notUsed('a'), canAssign(%1 'b') replace restart { ld a, %1 %3 %2, a ld %1, a } by { ; common peephole 75 %3 bit %2 of %1 directly instead of going through a. %3 %2, %1 ld a, %1 } if same(%3 'set' 'res'), canAssign(%1 'b'), notSame(%1 '(hl+)' '(hl-)') // canAssign(%1 'b') is true, iff set b, %1 is possible. replace restart { ld a, %1 (%2) %4 %3, a ld %1 (%2), a } by { ; common peephole 76 %4 bit %3 of %1 (%2) directly instead of going through a. %4 %3, %1 (%2) ld a, %1 (%2) } if same(%4 'set' 'res') replace { ld %1, #%2 + 0 } by { ; common peephole 77a removed unnecessary +0 to immediate ld %1, #%2 } // Bug #3102 //replace { // ld %1, (#%2 + 0) //} by { // ; common peephole 77b removed unnecessary +0 to immediate // ld %1, (#%2) //} replace { ld (#%2 + 0), %1 } by { ; common peephole 77c removed unnecessary +0 to immediate ld (#%2), %1 } replace restart { jp NC,%1 jp %2 %1: } by { jp C,%2 ; common peephole 79 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp C,%1 jp %2 %1: } by { jp NC,%2 ; common peephole 80 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp NZ,%1 jp %2 %1: } by { jp Z,%2 ; common peephole 81 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp Z,%1 jp %2 %1: } by { jp NZ,%2 ; common peephole 82 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp %5 } by { jp %6 ; common peephole 83 jumped to %6 directly instead of via %5. } if labelIsUncondJump(), notSame(%5 %6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1) replace restart { jp %1,%5 } by { jp %1,%6 ; common peephole 84 jumped to %6 directly instead of via %5. } if labelIsUncondJump(), notSame(%5 %6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1) replace restart { jp %1 %2: %1: } by { ; common peephole 85 eliminated jump. %2: %1: } if labelRefCountChange(%1 -1) // A peephole that makes the code longer. Let's hope it's worth it in speed gain and further optimization potential. replace restart { ld a,#0x00 %1: bit %2,a jp Z,%3 } by { ld a,#0x00 jp %3 ; common peephole 86 jumped directly to %3 instead of testing a first. %1: bit %2,a jp Z,%3 } if labelRefCountChange(%3 +1) replace restart { ld %1, %2 jp %3 jp %4 } by { ld %1, %2 jp %3 ; common peephole 87a removed unreachable jump to %4 } if labelRefCountChange(%4 -1) replace restart { jp %1 %2: jp %3 } by { ; common peephole 88b removed unreachable jump to %3 jp %1 } if labelRefCount(%2 0), labelRefCountChange(%3 -1) replace restart { ld %1, %2 jp %3 %3: } by { ld %1, %2 %3: ; common peephole 88 removed redundant jump to %3. } if labelRefCountChange(%3 -1) replace restart { ld %1, #0x01 bit 0, %1 jp Z, %2 } by { ld %1, #0x01 ; common peephole 89 removed impossible jump to %2. } if labelRefCountChange(%2 -1) replace restart { rlca and a, #0x01 jp Z, %1 } by { rlca ; common peephole 90 removed and by changing jump condition. jp NC, %1 } if notUsed('a'), notUsedFrom(%1 'a') replace restart { rlca and a, #0x01 jp NZ, %1 } by { rlca ; common peephole 91 removed and by changing jump condition. jp C, %1 } if notUsed('a'), notUsedFrom(%1 'a') replace { ld e, #0x%1 ld d, #0x%2 } by { ld de, #0x%2%1 ; common peephole 92 combined constant loads into register pair. } replace { ld d, #0x%1 ld e, #0x%2 } by { ld de, #0x%1%2 ; common peephole 93 combined constant loads into register pair. } replace { ld l, #0x%1 ld h, #0x%2 } by { ld hl, #0x%2%1 ; common peephole 94 combined constant loads into register pair. } replace { ld h, #0x%1 ld l, #0x%2 } by { ld hl, #0x%1%2 ; common peephole 95 combined constant loads into register pair. } replace { ld c, #0x%1 ld b, #0x%2 } by { ld bc, #0x%2%1 ; common peephole 96 combined constant loads into register pair. } replace { ld b, #0x%1 ld c, #0x%2 } by { ld bc, #0x%1%2 ; common peephole 97 combined constant loads into register pair. } replace restart { ld %1, a ld a, %1 } by { ld %1, a ; common peephole 98 removed redundant load from %1 into a. } if notVolatile(%1), notSame(%1 '(hl+)' '(hl-)') // This gives many false negatives and without the test no problems are encountered in the regression tests // Maybe we can try this after 2.7.0 release replace restart { ld %2 (ix), %1 ld %1, %2 (ix) } by { ld %2 (ix), %1 ; common peephole 98a removed redundant load of %1 from %2 (ix) } replace restart { ld %1,a ld a,%2 or a,%1 } by { ld %1,a or a,%2 ; common peephole 99 removed load by reordering or arguments. } if notVolatile(%1), canAssign('b' %2), notSame(%1 '(hl+)' '(hl-)') // canAssign('b' %2) is true, iff or a,%2 is possible. replace restart { ld %1, (hl) inc hl ld a, (hl) or a, %1 } by { ld a, (hl) inc hl ; common peephole 99a removed load by reordering or arguments. or a, (hl) } if notUsed(%1) replace restart { and a,%1 or a,a } by { and a,%1 ; common peephole 100 removed redundant or after and. } replace restart { xor a,%1 or a,a } by { xor a,%1 ; common peephole 101 removed redundant or after xor. } replace restart { xor a,%1 (%2) or a,a } by { xor a,%1 (%2) ; common peephole 102 removed redundant or after xor. } replace restart { dec a or a, a } by { dec a ; common peephole 102a removed redundant or after dec. } replace restart { dec %1 ld a, %1 or a, a } by { dec %1 ld a, %1 ; common peephole 102b removed redundant or after dec. } replace restart { sbc hl, %1 ld a, h or a, l jp NZ, %2 } by { sbc hl, %1 jp NZ, %2 ; common peephole 102c removed redundant or after sbc. } replace restart { sbc hl, %1 ld a, h or a, l jp Z, %2 } by { sbc hl, %1 jp Z, %2 ; common peephole 102d removed redundant or after sbc. } replace { ld %1,%2 ld a,%2 } by { ld a,%2 ld %1,a ; common peephole 103 loaded value in a first and used it next } if notVolatile(%1 %2), canAssign(%1 'a'), operandsNotRelated(%1 %2), notSame(%1 '(hl+)' '(hl-)'), notSame(%2 '(hl+)' '(hl-)') replace restart { ld %1,%2 ld %3,%4 ld %2,%1 ld %4,%3 } by { ld %1,%2 ld %3,%4 ; common peephole 104 removed redundant load from %3%1 into %4%2 } if notVolatile(%1 %2 %3 %4), notSame(%1 '(hl+)' '(hl-)'), notSame(%2 '(hl+)' '(hl-)'), notSame(%3 '(hl+)' '(hl-)'), notSame(%4 '(hl+)' '(hl-)') replace restart { push de inc sp ld a,e push af inc sp } by { push de ; common peephole 105 pushed de } if notUsed('a') replace restart { ld iy,%1 add iy,sp ld sp,iy } by { ld hl,%1 add hl,sp ld sp,hl ; common peephole 106 fixed stack using hl instead of iy. } if notUsed('hl'), notUsed('iy') replace restart { ld a,%1 sub a,%2 jp %3,%4 ld a,%1 } by { ld a,%1 cp a,%2 jp %3,%4 ; common peephole 107 removed load from %1 into a by replacing sub with cp assert a=%1 } if notVolatile(%1), notUsedFrom(%4 'a'), notSame(%1 '(hl+)' '(hl-)') replace restart { assert a=%1 sub a,%2 jp %3,%4 ld a,%1 } by { cp a,%2 jp %3,%4 ; common peephole 108 removed load from %1 into a by replacing sub with cp assert a=%1 } if notUsedFrom(%4 'a') replace restart { assert a=%1 } by { } replace restart { rlca ld a,#0x00 rla } by { rlca and a,#0x01 ; common peephole 109 replaced zero load, rla by and since rlca writes the same value to carry bit and least significant bit. } replace restart { ld %1,%2 push %1 pop %4 ld %1,%3 } by { ld %4,%2 ; common peephole 110 moved %2 directly into de instead of going through %1. ld %1,%3 } replace restart { add a,#0x00 ld %2,a ld a,%3 adc a,%4 } by { ; common peephole 111 removed lower part of multibyte addition. ld %2,a ld a,%3 add a,%4 } replace restart { ld a, l add a, #0x%1 ld e, a ld a, h adc a, #0x%2 ld d, a } by { ld de, #0x%2%1 add hl, de ; common peephole 112 used 16-bit addition. ld e, l ld d, h ld a, h } if notUsed('hl') replace restart { ld a, l add a, #0x%1 ld c, a ld a, h adc a, #0x%2 ld b, a } by { ld bc, #0x%2%1 add hl,bc ; common peephole 113 used 16-bit addition. ld c, l ld b, h ld a, h } if notUsed('hl') replace restart { ld l,%1 (ix) ld h,%2 (ix) ld a,(hl) inc a ld l,%1 (ix) ld h,%2 (ix) ld (hl),a } by { ld l,%1 (ix) ld h,%2 (ix) inc (hl) ; common peephole 114 incremented in (hl) instead of going through a. } if notUsed('a') replace restart { ld a,(hl) inc a ld (hl),a } by { inc (hl) ; common peephole 115 incremented in (hl) instead of going through a. } if notUsed('a') // TODO: Check for volatile? replace restart { ld %1, %2 (%3) inc %1 ld %2 (%3), %1 } by { inc %2 (%3) ld %1, %2 (%3) ; common peephole 116 incremented in %2 (%3) instead of going through %1. } if canAssign('a' %1) // TODO: Check for volatile? replace restart { ld %1, %2 (%3) dec %1 ld %2 (%3), %1 } by { dec %2 (%3) ld %1, %2 (%3) ; common peephole 117 decremented in %2 (%3) instead of going through %1. } if canAssign('a' %1) replace restart { ld %1,a ld a,%2 add a,%1 } by { ld %1, a ; common peephole 118 removed load by exploiting commutativity of addition. add a,%2 } if notSame(%2 '(bc)' '(de)'), canAssign('b' %2) // canAssign('b' %2) is true, iff add a,%2 is possible. replace restart { ld c,l ld b,h ld hl,#%1 add hl,bc } by { ; common peephole 119 removed loads by exploiting commutativity of addition. ld bc,#%1 add hl,bc } if notUsed('bc') replace restart { ld hl,#%1 add hl,%2 ld bc,#%4 add hl,bc } by { ; common peephole 120 removed loads by exploiting commutativity of addition. ld hl,#%1 + %4 add hl,%2 } if notUsed('bc') replace restart { or a,%1 jp NZ,%2 ld %3,#0x00 } by { or a,%1 jp NZ,%2 ld %3,a ; common peephole 121 replaced constant #0x00 by a (which has just been tested to be #0x00). } replace restart { and a,%1 jp NZ,%2 ld %3,#0x00 } by { and a,%1 jp NZ,%2 ld %3,a ; common peephole 122 replaced constant #0x00 by a (which has just been tested to be #0x00). } replace restart { sub a,%1 jp NZ,%2 ld %3,#0x00 } by { sub a,%1 jp NZ,%2 ld %3,a ; common peephole 123 replaced constant #0x00 by a (which has just been tested to be #0x00). } replace restart { inc a jp NZ,%1 ld %2,#0x00 } by { inc a jp NZ,%1 ld %2,a ; common peephole 124 replaced constant #0x00 by a (which has just been tested to be #0x00). } replace restart { dec a jp NZ,%1 ld %2,#0x00 } by { dec a jp NZ,%1 ld %2,a ; common peephole 125 replaced constant #0x00 by a (which has just been tested to be #0x00). } replace restart { or a,%1 jp NZ,%2 ld a,%3 or a,a } by { or a,%1 jp NZ,%2 or a,%3 ; common peephole 126 shortened or using a (which has just been tested to be #0x00). } if canAssign('b' %3) // canAssign('b' %2) is true, iff or a,%2 is possible. replace restart { sub a,%1 jp NZ,%2 ld a,%3 or a,a } by { sub a,%1 jp NZ,%2 or a,%3 ; common peephole 127 shortened or using a (which has just been tested to be #0x00). } if canAssign('b' %3) // canAssign('b' %2) is true, iff or a,%2 is possible. replace restart { ld hl,#%1 add hl,%2 inc hl } by { ld hl,#%1+1 add hl,%2 ; common peephole 129 moved increment of hl to constant. } replace restart { push hl pop iy pop hl inc iy } by { inc hl push hl pop iy pop hl ; common peephole 130 incremented in hl instead of iy. } replace restart { push bc pop iy inc iy } by { inc bc push bc pop iy ; common peephole 131 incremented in bc instead of iy. } if notUsed('bc') replace restart { ld hl,%1 add hl,%2 push hl pop iy } by { ld iy,%1 add iy,%2 ; common peephole 132 added in iy instead of hl. } if notUsed('hl'), notSame(%2 'hl') replace restart { pop af ld sp,%1 } by { ; common peephole 133 removed redundant pop af. ld sp,%1 } if notUsed('a') replace restart { inc sp ld sp,%1 } by { ; common peephole 134 removed redundant inc sp. ld sp,%1 } replace restart { call %1 ret } by { jp %1 ; common peephole 135 replaced call at end of function by jump (tail call optimization). } if symmParmStack(%1) // Callee saves ix. replace restart { call %1 pop ix ret } by { pop ix jp %1 ; common peephole 136 replaced call at end of function by jump moving call beyond pop ix (tail call optimization). } if symmParmStack(%1) replace restart { ld %1,#%2 ld %3,%4 ld %1,#%2 } by { ld %1,#%2 ld %3,%4 ; common peephole 137 removed load of #%2 into %1 since it's still there. } if notVolatile(%1), operandsNotRelated(%3 %1), notSame(%1 '(hl+)' '(hl-)') replace restart { ld hl,#%1 ld de,#%1 } by { ; common peephole 138 used #%1 from hl for load into de. ld hl,#%1 ld e,l ld d,h } replace restart { ld sp,hl ld hl,#0x0002 add hl,sp } by { ld sp, hl inc hl inc hl ; common peephole 139 replaced addition by increment. } replace restart { ex de, hl ld hl, #%1 add hl, de } by { ; common peephole 140 removed ex exploiting commutativity of addition. ld de, #%1 add hl, de } if notUsed('de') replace restart { ld hl, #%1 add hl, %2 ex de, hl inc de } by { ld hl, #%1+1 ; common peephole 141 moved increment to constant. add hl, %2 ex de, hl } if notUsed('hl') // those might work for tlcs90 too replace restart { pop af push hl } by { ; common peephole 142 used ex to move hl onto the stack. ex (sp),hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n'), notUsed('a'), notUsed('hl') replace restart { pop af ld hl, #%1 push hl } by { ld hl, #%1 ; common peephole 143 used ex to move hl onto the stack. ex (sp),hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n'), notUsed('a'), notUsed('hl') replace restart { pop af inc sp ld hl,#%1 push hl } by { inc sp ld hl,#%1 ; common peephole 144 used ex to move #%1 onto the stack. ex (sp),hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n'), notUsed('a'), notUsed('hl') replace restart { pop af inc sp ld h, %1 (ix) ld l, %2 (ix) push hl } by { inc sp ld h, %1 (ix) ld l, %2 (ix) ; common peephole 145 used ex to move %1 (ix) %2 (ix) onto the stack. ex (sp),hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n'), notUsed('a'), notUsed('hl') replace restart { pop af ld a,#%1 push af inc sp } by { ld h,#%1 ex (sp),hl ; common peephole 146 used ex to move #%1 onto the stack. inc sp } if isPort('z80' 'ez80_z80' 'z180' 'z80n'), notUsed('a'), notUsed('hl') replace restart { ld %1,#%2 ld %3 (%1),a %4: ld %1,%5 } by { ld (#%2 + %3),a ; common peephole 147 directly used #%2 instead of going through %1 using indirect addressing. %4: ld %1,%5 } replace restart { pop af ld %1,#%2 ld %3 (%1),%4 ld %1,#%5 } by { ld a,%4 ld (#%2 + %3),a ; common peephole 148 used #%2 directly instead of going through %1 using indirect addressing. pop af ld %1,#%5 } if notSame(%3 'a') replace restart { ld %1,a bit %2,%1 } by { bit %2,a ; common peephole 149 tested bit %2 of a directly instead of going through %1. } if notUsed(%1) replace restart { sbc a,%1 bit 7,a jp NZ,%2 } by { sbc a,%1 jp M,%2 ; common peephole 150 used sign flag instead of testing bit 7. } if isPort('z80' 'ez80_z80' 'z180' 'z80n' 'tlcs90') replace restart { ld %1,a or a,a jp %3,%4 ld a,%1 } by { ld %1,a or a,a jp %3,%4 ; common peephole 151 used value still in a instead of reloading from %1. } replace { jp %5 ret } by { jp %5 ; common peephole 152 removed unused ret. } replace { jp %5 ld sp,ix pop ix ret } by { jp %5 ; common peephole 153 removed unused ret. } replace restart { or a,%1 jp NZ,%2 xor a,a jp %3 } by { or a,%1 jp NZ,%2 ; common peephole 154 removed redundant zeroing of a (which has just been tested to be #0x00). jp %3 } replace restart { dec %1 inc %1 } by { ; common peephole 155a swap dec %1 / inc %1 pair. inc %1 dec %1 } replace restart { inc %1 dec %1 } by { ; common peephole 155b removed inc %1 / dec %1 pair. } if same(%1 'bc' 'de' 'hl' 'ix' 'iy' 'sp') replace restart { inc %1 dec %1 } by { ; common peephole 155c removed inc %1 / dec %1 pair. } if same(%1 'a' 'b' 'c' 'd' 'e' 'h' 'l' 'ixh' 'ixl' 'iyh' 'iyl'), notUsed('zf' 'vf' 'sf' 'nf' 'hf') replace restart { inc %2 inc %1 dec %1 } by { ; common peephole 155e removed inc %1 / dec %1 pair. inc %1 inc %2 dec %1 } if same(%1 'bc' 'de' 'hl' 'ix' 'iy' 'sp'), same(%2 'bc' 'de' 'hl' 'ix' 'iy' 'sp'), operandsNotRelated(%1 %2) replace restart { jp Z, %2 ld a, #%3 jp %1 %2: ld a, #%4 %1: } by { ld a, #%3 jp NZ, %1 %2: ld a, #%4 ; common peephole 168z used double assignment in case of Z condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp NZ, %2 ld a, #%3 jp %1 %2: ld a, #%4 %1: } by { ld a, #%3 jp Z, %1 %2: ld a, #%4 ; common peephole 168nz used double assignment in case of NZ condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp Z, %2 ld a, #%3 jp %1 %2: xor a, a %1: } by { ld a, #%3 jp NZ, %1 ; common peephole 169xz used double assignment in case of Z condition. %2: xor a, a %1: } if labelRefCountChange(%2 -1) replace restart { jp NZ, %2 ld a, #%3 jp %1 %2: xor a, a %1: } by { ld a, #%3 jp Z, %1 ; common peephole 169xnz used double assignment in case of NZ condition. %2: xor a, a %1: } if labelRefCountChange(%2 -1) replace restart { jp Z, %2 ld c, #%3 jp %1 %2: ld c, #%4 %1: } by { ld c, #%3 jp NZ, %1 %2: ld c, #%4 ; common peephole 170z used double assignment in case of Z condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp NZ, %2 ld c, #%3 jp %1 %2: ld c, #%4 %1: } by { ld c, #%3 jp Z, %1 %2: ld c, #%4 ; common peephole 170nz used double assignment in case of NZ condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp Z, %2 ld e, #%3 jp %1 %2: ld e, #%4 %1: } by { ld e, #%3 jp NZ, %1 %2: ld e, #%4 ; common peephole 171z used double assignment in case of Z condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp NZ, %2 ld e, #%3 jp %1 %2: ld e, #%4 %1: } by { ld e, #%3 jp Z, %1 %2: ld e, #%4 ; common peephole 171nz used double assignment in case of NZ condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp Z, %2 ld l, #%3 jp %1 %2: ld l, #%4 %1: } by { ld l, #%3 jp NZ, %1 %2: ld l, #%4 ; common peephole 172z used double assignment in case of Z condition. %1: } if labelRefCountChange(%2 -1) replace restart { jp NZ, %2 ld l, #%3 jp %1 %2: ld l, #%4 %1: } by { ld l, #%3 jp Z, %1 %2: ld l, #%4 ; common peephole 172nz used double assignment in case of NZ condition. %1: } if labelRefCountChange(%2 -1) replace restart { ld %1, %3 ld %2, %4 push %5 } by { ; common peephole 173 eliminated assignment by pushing %6 push %6 } if canJoinRegs(%2 %1 %7), same(%7 %5), canJoinRegs(%4 %3 %6), notUsed(%5) replace restart { ld %1,%2 ld %2,%1 } by { ld %1,%2 ; common peephole 176 remove unnecessary load back } if notVolatile(%1), notVolatile(%2), notSame(%1 '(hl+)' '(hl-)'), notSame(%2 '(hl+)' '(hl-)') replace restart { ld a, %1 push af } by { push %2 ; common peephole 177 replace pushed register pair } if notUsed('a'), canJoinRegs(%1 '' %2), canSplitReg(%2 %3), same(%3 %1) replace restart { inc %3 ld %1, %2 (%3) } by { ; common peephole 178 moved increment of %3 after ld instruction ld %1, %4 (%3) inc %3 } if operandsNotRelated(%1 %3), immdInRange(-128 127 '+' %2 1 %4) replace restart { dec %3 ld %1, %2 (%3) } by { ; common peephole 179 moved decrement of %3 after ld instruction ld %1, %4 (%3) dec %3 } if operandsNotRelated(%1 %3), immdInRange(-128 127 '-' %2 1 %4) //next rules optimize code after the call //replaces lot of `inc sp` by `ld hl,#n; add hl,sp; ld sp,hl` replace restart { inc sp pop %1 ld %2 (%3), %4 } by { inc sp ; common peephole 190: move pop instruction after register store ld %2 (%3), %4 pop %1 } if notSame(%1 %3 %4), operandsNotRelated(%1 %4) replace restart { inc sp ld %1 (%2), %3 } by { ; common peephole 191a: move register store before stack restore ld %1 (%2), %3 inc sp } if notSame(%2 'sp') replace restart { inc sp pop %1 ld %2, %3 } by { ; common peephole 191b: move register to register copy before SP increment ld %2, %3 inc sp pop %1 } if same(%3 'l' 'h'), notSame(%2 'l' 'h'), notUsed('hl'), operandsNotRelated(%1 %2 %3), notSame('sp' %2 %3) replace restart { inc sp ld %1, %2 } by { ; common peephole 191c: move register store before stack restore ld %1, %2 inc sp } if notUsed('hl'), same(%2 'h' 'l' 'sp'), notSame(%1 'h' 'l' 'sp') replace restart { inc sp ld %3, #%1 add %3, sp ld sp, %3 } by { ; common peephole 192: increase SP by addition ld %3, #%2 add %3, sp ld sp, %3 } if notUsed(%3), same(%3 'hl' 'ix' 'iy'), immdInRange(0 0x7fff '+' %1 1 %2) replace restart { inc sp inc sp inc sp inc sp inc sp } by { ; common peephole 193: increase SP by addition ld hl, #5 add hl, sp ld sp, hl } if notUsed('hl') //next rules optimized some checks replace restart { ld a, %1 sub a, #%7 ld a, %2 sbc a, #0x00 ld a, %3 sbc a, #0x00 ld a, %4 sbc a, #0x00 %5 C, %6 } by { ; common peephole 194-1: symplify 32-bit compare for 8 bit values ld a, %2 or a, %3 or a, %4 jp NZ, %9 ld a, %1 cp a, #%7 %5 C, %6 %9: } if same(%5 'jr' 'jp' 'call'), notUsed('a'), newLabel(%9) replace restart { ld a, %1 sub a, #%7 ld a, %2 sbc a, #%8 ld a, %3 sbc a, #0x00 ld a, %4 sbc a, #0x00 %5 C, %6 } by { ; common peephole 194-2: symplify 32-bit compare for 16 bit values ld a, %3 or a, %4 jp NZ, %9 ld a, %1 sub a, #%7 ld a, %2 sbc a, #%8 %5 C, %6 %9: } if same(%5 'jr' 'jp' 'call'), notUsed('a'), newLabel(%9) replace restart { ld a, #0xff cp a, %1 %2 NC, %3 } by { ; common peephole 195-1: remove always true check } if same(%2 'jr' 'jp' 'call'), notUsed('a'), labelRefCountChange(%3 -1) replace restart { ld a, #0xff sub a, %1 ld a, #0xff sbc a, %2 %3 NC, %4 } by { ; common peephole 195-2: remove always true check } if same(%3 'jr' 'jp' 'call'), notUsed('a'), labelRefCountChange(%4 -1) // These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed(). barrier replace restart { ld e,l ld d,h } by { ; common peephole 156 used ex to load hl into de. ex de,hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n' 'r2k' 'r3ka' 'tlcs90'), notUsed('hl') replace restart { ld l,e ld h,d } by { ; common peephole 157 used ex to load de into hl. ex de,hl } if isPort('z80' 'ez80_z80' 'z180' 'z80n' 'r2k' 'r3ka' 'tlcs90'), notUsed('de') barrier // Should be one of the last ones. Opens the code to further peephole optimization. replace restart { %1: } by { ; common peephole 158 removed unused label %1. } if labelRefCount(%1 0) // Ensure that all rules above see only jp, not jr. barrier replace { add hl,de pop de jp (hl) %1: jp %5 jp %6 jp %7 %2: } by { ; common peephole 159-3 removed addition using short jumps in jump-table. pop de jp (hl) %1: jr %5 jr %6 jr %7 %2: } if labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 %2: } by { ; common peephole 159-3' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 %2: } if labelJTInRange replace { add hl,de pop de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 %2: } by { ; common peephole 159-4 removed addition using short jumps in jump-table. pop de jp (hl) %1: jr %5 jr %6 jr %7 jr %8 %2: } if labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 %2: } by { ; common peephole 159-4' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 jr %8 %2: } if labelJTInRange replace { add hl,de pop de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 %2: } by { ; common peephole 159-5 removed addition using short jumps in jump-table. pop de jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 %2: } if labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 %2: } by { ; common peephole 159-5' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 %2: } if labelJTInRange replace { add hl,de pop de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 jp %10 %2: } by { ; common peephole 159-6 removed addition using short jumps in jump-table. pop de jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 jr %10 %2: } if labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 jp %10 %2: } by { ; common peephole 150-6' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 jr %10 %2: } if isPort('r2k' 'r3ka'), labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 jp %10 %2: } by { ; common peephole 159-6' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 jr %10 %2: } if labelJTInRange replace { add hl,de pop de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 jp %10 jp %11 %2: } by { ; common peephole 159-7 removed addition using short jumps in jump-table. pop de jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 jr %10 jr %11 %2: } if labelJTInRange replace { add hl,de jp (hl) %1: jp %5 jp %6 jp %7 jp %8 jp %9 jp %10 jp %11 %2: } by { ; common peephole 159-7' removed addition using short jumps in jump-table. jp (hl) %1: jr %5 jr %6 jr %7 jr %8 jr %9 jr %10 jr %11 %2: } if labelJTInRange barrier // Do all jump optimizations before replacing by ret. replace restart { jp %5 } by { ret ; common peephole 160 replaced jump by return. } if labelIsReturnOnly(%5), labelRefCountChange(%5 -1) replace restart { jp %1,%5 } by { ret %1 ; common peephole 161 replaced jump by return. } if labelIsReturnOnly(%5), labelRefCountChange(%5 -1) // Replace jp by ret before replacing jp by jr outside of jump tables, since using ret can reduce the number of references to jump labels. barrier replace restart { jp %5 } by { ; common peephole 162 changed absolute to relative unconditional jump. jr %5 } if labelInRange(%5) replace restart { jp %1, %5 } by { ; common peephole 163 changed absolute to relative conditional jump. jr %1, %5 } if same(%1 'C' 'NC' 'NZ' 'Z'), labelInRange(%5) replace { dec b jr NZ, %5 } by { ; common peephole 167 used djnz djnz %5 } if isPort('z80' 'ez80_z80' 'z180' 'z80n' 'r2k' 'r3ka' 'tlcs90') replace restart{ ld c,l ld b,h ld (%1), bc } by { ld (%1), hl } if notUsed('bc') barrier