// peeph-z80.def - Z80 peephole rules // // Some of these peepholes could be potentially moved to peeph.def, but a // GBZ80 expert should have a look at them before. // // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2015 // // 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 { ; peephole 0 removed redundant load from %1 into %1. } if notVolatile(%1) replace restart { add ix,sp } by { ; peephole 1 removed dead frame pointer setup. } if notUsed('ix') replace restart { ld %1, %2 + %3 } by { ; peephole 2 removed dead load from %2 + %3 into %1. } if notVolatile(%1), notUsed(%1) // Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail. replace restart { ld %1, (iy) } by { ld %1, 0 (iy) ; peephole 3 made 0 offset explicit. } replace restart { ld (iy), %1 } by { ld 0 (iy), %1 ; peephole 4 made 0 offset explicit. } replace restart { dec hl } by { ; peephole 5 removed dead decrement of hl. } if notUsed('hl') replace restart { ld %1, %2 (iy) } by { ; peephole 6 removed dead load from %2 (iy) into %1. } if notUsed(%1) // Should probably check for notVolatile(), but gives many false positives and no regression tests fail. replace restart { ld %1, %2 (ix) } by { ; peephole 7 removed dead load from %2 (ix) into %1. } if notUsed(%1) replace restart { ld %1, %2 ld %3, %1 } by { ; peephole 8 loaded %3 from %2 directly instead of going through %1. ld %3, %2 } if canAssign(%3 %2), notVolatile(%1), notUsed(%1) replace restart { ld %1, %2 ld %3, %4 ld %5, %1 } by { ld %5, %2 ; peephole 9 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)'), notVolatile(%5) // Rule OK unless both %5 and %4 are volatile, but we can't express that directly. replace restart { ld %1, %2 (%3) ld %4, %1 } by { ; peephole 10 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 { ; peephole 11 loaded %2 into %3 (%4) directly instead of going through %1. ld %3 (%4), %2 } if canAssign(%3 %4 %2), notVolatile(%1), notUsed(%1), notSame(%1 'hl') replace restart { ld %1, %2 (%3) ld %4, %5 (%6) ld %7, %1 } by { ld %7, %2 (%3) ; peephole 12 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, %7 ld %5 (%6), %4 ld %2 (%3), %1 } by { ld %5 (%6), %4 ; peephole 13 loaded %7 into %2 (%3) directly instead of going through %1. ld %2 (%3), %7 } if canAssign(%2 %3 %7), notVolatile(%1), notUsed(%1), notSame(%1 %4 %1 'hl') replace restart { ld %1, %2 (%3) ld %4, %5 ld %7, %1 } by { ld %7, %2 (%3) ; peephole 14 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)'), notSame(%5 '(hl)' '(de)' '(bc)' '(iy)') replace restart { ld %1,#%2 ld a,%3 (%1) } by { ; peephole 15 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) ; peephole 16 loaded a from (#%1) directly instead of using hl. } if notUsed('hl') replace restart { ld hl,#%1 + %2 ld a,(hl) } by { ; peephole 17 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 ; peephole 18 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 ; peephole 19 loaded (#%1) from a directly instead of using hl. } if notUsed('hl') replace restart { ld a, %1 (%2) srl a ld %1 (%2), a } by { srl %1 (%2) ld a, %1 (%2) ; peephole 20 shifted in (%2) instead of a. } replace restart { ld %1,(hl) ld a,%2 (%3) sub a,%1 } by { ld a,%2 (%3) ; peephole 21 used (hl) in sub directly instead of going through %1. sub a,(hl) } if notVolatile(%1), notUsed(%1) replace restart { inc bc ld l,c ld h,b } by { ld l,c ld h,b ; peephole 22 incremented in hl instead of bc. inc hl } if notUsed('bc') replace restart { inc de ld l,e ld h,d } by { ld l,e ld h,d ; peephole 23 incremented in hl instead of de. inc hl } if notUsed('de') replace restart { ld c,l ld b,h ld a,#%1 ld (bc),a } by { ld c,l ld b,h ld (hl),#%1 ; peephole 24 loaded #%1 into (hl) instead of (bc). } if notUsed('a') replace restart { ex de, hl push de } by { ; peephole 25 pushed hl directly instead of going through de. push hl } if notUsed('de'), notUsed('hl') replace restart { ex de, hl push bc push de } by { ; peephole 26 pushed hl directly instead of going through de. push bc push hl } if notUsed('de'), notUsed('hl') replace restart { ld c,l ld b,h push %1 push bc } by { ; peephole 27 pushed hl directly instead of going through bc. push %1 push hl } if notUsed('bc'), notSame(%1 'bc') replace restart { pop de ld l, e ld h, d } by { ; peephole 28 popped hl directly instead of going through de. pop hl } if notUsed('de') replace restart { pop bc ld l, c ld h, b } by { ; peephole 29 popped hl directly instead of going through bc. pop hl } if notUsed('bc') replace restart { ld %1 (ix), %2 ld %3, %1 (ix) } by { ; peephole 30 loaded %3 from %2 instead of going through %1 (ix). ld %1 (ix), %2 ld %3, %2 } if canAssign(%3 %2) // Don't need to check for volatile, since ix is used for the stack. replace restart { ld %1 (ix), a push de ld %2, %1 (ix) } by { ld %1 (ix), a push de ; peephole 31 loaded %2 from a instead of %1 (ix) ld %2, a } if canAssign(%2 'a') replace restart { push af inc sp ld a,e push af inc sp } by { ; peephole 32 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 { ; peephole 33 pushed de instead of pushing a twice. ld d,a ld e,#%1 push de } if notUsed('de') replace restart { push bc inc sp push de inc sp } by { ld c, d ; peephole 34 combined pushing of b and d. push bc } if notUsed('c') replace restart { ld a,#%1 ld d,a } by { ; peephole 35 loaded #%1 into d directly instead of going through a. ld d,#%1 } if notUsed('a') replace restart { ld %1,a ld %2,%1 } by { ; peephole 36 loaded %2 from a directly instead of going through %1. ld %2,a } if notUsed(%1) replace restart { ld a,%1 (%3) push af inc sp ld a,%2 (%3) push af inc sp } by { ; peephole 37 pushed %1 (%3), %2(%3) through hl instead of af. ld h,%1 (%3) ld l,%2 (%3) push hl } if notUsed('a'), notUsed('hl') replace restart { ld c, l ld b, h push bc } by { ; peephole 38 pushed hl instead of bc. push hl } if notUsed('bc') replace restart { ld a, (hl) inc hl ld h, (hl) ld l, a push hl } by { ; peephole 39 pushed bc instead of hl. ld c, (hl) inc hl ld b, (hl) push bc } if notUsed('bc'), notUsed('hl') replace restart { pop %1 push %1 } by { ; peephole 40 eleminated dead pop/push pair. } if notUsed(%1) replace restart { push hl pop bc } by { ld c, l ld b, h ; peephole 41 replaced push/pop pair by loads. } if notUsed('hl') replace restart { push hl pop de } by { ld e, l ld d, h ; peephole 42 replaced push/pop pair by loads. } if notUsed('hl') replace restart { ld iy,#%1 or a,%2 (iy) } by { ; peephole 43 used hl instead of iy. ld hl,#%1 + %2 or a,(hl) } if notUsed('iy'), notUsed('hl') replace restart { ld iy,#%1 ld %2,%3 (iy) } by { ; peephole 44 used hl instead of iy. ld hl,#%1 + %3 ld %2, (hl) } if notUsed('iy'), notUsed('hl') replace restart { ld iy,#%1 ld h,%3 (iy) } by { ; peephole 45 used hl instead of iy. ld hl,#%1 + %3 ld h, (hl) } if notUsed('iy'), notUsed('l') replace restart { ld iy,#%1 ld %2 (iy), %3 } by { ; peephole 46 used hl instead of iy. ld hl,#%1 + %2 ld (hl), %3 } if notUsed('iy'), notUsed('hl'), notSame(%3 'h' 'l') replace restart { ld iy,#%1 ld %2,0 (iy) ld %3,1 (iy) } by { ; peephole 47 used hl instead of iy. ld hl,#%1 ld %2, (hl) inc hl ld %3, (hl) } if notUsed('iy'), notUsed('hl'), operandsNotRelated(%2 'hl') replace restart { ld iy,#%1 bit %2,%3 (iy) } by { ; peephole 48 used hl instead of iy. ld hl,#%1+%3 bit %2, (hl) } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp ld %2, %3 (iy) } by { ; peephole 49 used hl instead of iy. ld hl, #%1+%3 add hl, sp ld %2, (hl) } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp ld %2, 0 (iy) ld %3, 1 (iy) } by { ; peephole 50 used hl instead of iy. ld hl, #%1 add hl, sp ld %2, (hl) inc hl ld %3, (hl) } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp ld l, 0 (iy) ld h, 1 (iy) } by { ; peephole 51 used hl instead of iy. ld hl, #%1 add hl, sp ld a, (hl) inc hl ld h, (hl) ld l, a } if notUsed('iy'), notUsed('a') replace restart { ld iy, #%1+1 ld a, 1 (iy) or a, 0 (iy) } by { ld hl, #%1 ld a, (hl) dec hl or a, (hl) ; peephole 52 used hl instead of iy. } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp ld a, 1 (iy) or a, 0 (iy) } by { ld hl, #%1+1 add hl, sp ld a, (hl) dec hl or a, (hl) ; peephole 53 used hl instead of iy. } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp bit %2, %3 (iy) } by { ld hl, #%1+%3 add hl, sp bit %2, (hl) ; peephole 54 used hl instead of iy. } if notUsed('iy'), notUsed('hl') replace restart { ld iy, #%1 add iy, sp or a, %2 (iy) } by { ld hl, #%1+%2 add hl, sp or a, (hl) ; peephole 55 used hl instead of iy. } if notUsed('iy'), notUsed('hl') replace restart { ld c,l ld b,h inc bc } by { ; peephole 56 incremented in hl instead of bc. inc hl ld c,l ld b,h } if notUsed('hl') replace restart { ld iy, #%1 inc %2 (iy) } by { ; peephole 57 incremented in (hl) instead of %2 (iy). ld hl, #%1+%2 inc (hl) } if notUsed('hl'), notUsed('iy') replace restart { ld iy, #%1 dec %2 (iy) } by { ; peephole 58 decremented in (hl) instead of %2 (iy). ld hl, #%1+%2 dec (hl) } if notUsed('hl'), notUsed('iy') replace restart { add hl, hl ld e, l ld d, h inc de inc de } by { inc hl ; peephole 59 incremented once in hl instead of incrementing in de twice. add hl, hl ld e, l ld d, h } if notUsed('hl') replace restart { add hl, hl inc hl inc hl } by { inc hl ; peephole 60 incremented once in hl instead of incrementing in hl twice. add hl, hl } replace restart { add a, a add a, a add a, #0x04 } by { inc a ; peephole 61 incremented a once instead of adding #0x04 to a. add a, a add a, a } replace restart { add hl, hl pop de inc hl inc hl } by { inc hl ; peephole 62 incremented once in hl instead of incrementing in hl twice. add hl, hl pop de } replace restart { ld a,%1 (%2) bit %3,a } by { ; peephole 63 tested bit of %1 (%2) directly instead of going through a. bit %3,%1 (%2) } if notUsed('a') replace restart { ld a,%1 bit %2,a } by { ; peephole 64 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 set %2, a ld %1, a } by { ; peephole 65 set bit %2 of %1 directly instead of going through a. set %2, %1 ld a, %1 } if canAssign(%1 'b') // canAssign(%1 'b') is true, iff set b, %1 is possible. replace restart { ld a, %1 (%2) set %3, a ld %1 (%2), a } by { ; peephole 66 set bit %3 of %1 (%2) directly instead of going through a. set %3, %1 (%2) ld a, %1 (%2) } replace restart { ld a, %1 (%2) res %3, a ld %1 (%2), a } by { ; peephole 67 reset bit %3 of %1 (%2) directly instead of going through a. res %3, %1 (%2) ld a, %1 (%2) } replace restart { jp NC,%1 jp %2 %1: } by { jp C,%2 ; peephole 68 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp C,%1 jp %2 %1: } by { jp NC,%2 ; peephole 69 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp NZ,%1 jp %2 %1: } by { jp Z,%2 ; peephole 70 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp Z,%1 jp %2 %1: } by { jp NZ,%2 ; peephole 71 removed jp by using inverse jump logic %1: } if labelRefCountChange(%1 -1) replace restart { jp %5 } by { jp %6 ; peephole 72 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 ; peephole 73 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 { ; peephole 74 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 ; peephole 77 jumped directly to %3 instead of testing a first. %1: bit %2,a jp Z,%3 } if labelRefCountChange(%3 +1) replace { ld e,#0x%1 ld d,#0x%2 } by { ld de,#0x%2%1 ; peephole 78 combined constant loads into register pair. } replace { ld d,#0x%1 ld e,#0x%2 } by { ld de,#0x%1%2 ; peephole 79 combined constant loads into register pair. } replace { ld l,#0x%1 ld h,#0x%2 } by { ld hl,#0x%2%1 ; peephole 80 combined constant loads into register pair. } replace { ld h,#0x%1 ld l,#0x%2 } by { ld hl,#0x%1%2 ; peephole 81 combined constant loads into register pair. } replace { ld c,#0x%1 ld b,#0x%2 } by { ld bc,#0x%2%1 ; peephole 82 combined constant loads into register pair. } replace { ld b,#0x%1 ld c,#0x%2 } by { ld bc,#0x%1%2 ; peephole 83 combined constant loads into register pair. } replace restart { ld %1,a ld a,%1 } by { ld %1,a ; peephole 84 removed redundant load from %1 into a. } if notVolatile(%1) // 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 ; peephole 84a 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 ; peephole 85 removed load by reordering or arguments. } if notVolatile(%1), canAssign('b' %2) // canAssign('b' %2) is true, iff or a,%2 is possible. replace restart { and a,%1 or a,a } by { and a,%1 ; peephole 86 removed redundant or after and. } replace restart { xor a,%1 (%2) or a,a } by { xor a,%1 (%2) ; peephole 87 removed redundant or after xor. } replace { ld %1,%2 ld a,%2 } by { ld a,%2 ld %1,a ; peephole 88 load value in a first and use it next } if notVolatile(%1 %2) replace restart { ld %1,%2 ld %3,%4 ld %2,%1 ld %4,%3 } by { ld %1,%2 ld %3,%4 ; peephole 89 removed redundant load from %3%1 into %4%2 } if notVolatile(%1 %2 %3 %4) replace restart { push de inc sp ld a,e push af inc sp } by { push de ; peephole 90 pushed de } if notUsed('a') replace restart { ld a,%1 sub a,%2 jp %3,%4 ld a,%1 } by { ld a,%1 cp a,%2 jp %3,%4 ; peephole 91 removed load from %1 into a by replacing sub with cp assert a=%1 } if notVolatile(%1), notUsedFrom(%4 'a') replace restart { assert a=%1 } by { } replace restart { rlca ld a,#0x00 rla } by { rlca and a,#0x01 ; peephole 92 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 ; peephole 93 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 { ; peephole 94 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 ; peephole 95 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 ; peephole 96 used 16-bit addition. ld c, l ld b, h ld a, h } if notUsed('hl') replace restart { ld a,(hl) inc a ld (hl),a } by { inc (hl) ; peephole 97 incremented in (hl) instead of going through a. } if notUsed('a') replace restart { ld c,l ld b,h ld hl,#%1 add hl,bc } by { ; peephole 98 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 { ; peephole 99 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 ; peephole 100 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 ; peephole 101 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 ; peephole 102 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 ; peephole 103 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 ; peephole 104 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 ; peephole 106 moved increment of hl to constant. } replace restart { call %1 ret } by { jp %1 ; peephole 107 replaced call at end of function by jump (tail call optimization). } if symmParmStack(%1) replace restart { ld %1,#%2 ld %3,%4 ld %1,#%2 } by { ld %1,#%2 ld %3,%4 ; peephole 108 removed load of #%2 into %1 since it's still there. } if notVolatile(%1), operandsNotRelated(%3 %1) replace restart { ld hl,#%1 ld de,#%1 } by { ; peephole 109 used #%1 from hl for load into de. ld hl,#%1 ld e,l ld d,h } replace restart { ld %1, a ld a, %2 (%3) adc a, #%4 ld %5, a ld %6, %1 } by { ld %6, a ld a, %2 (%3) adc a, #%4 ld %5, a ; peephole 110 loaded %6 from a directly instead of going through %1. } if notUsed(%1), notSame(%5 %1), notSame(%5 '(hl)' '(de)' '(bc)'), notSame(%5 %6), notSame(%6 '(hl)' '(de)' '(bc)'), notSame(%5 'a'), notSame(%6 'a') replace restart { ex de, hl ld hl, #%1 add hl, de } by { ; peephole 111 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 ; peephole 112 moved increment to constant. add hl, %2 ex de, hl } if notUsed('hl') replace restart { ld %1,a bit %2,%1 } by { bit %2,a ; peephole 113 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 ; peephole 114 used sign flag instead of testing bit 7. } replace restart { ld %1,a or a,a jp %3,%4 ld a,%1 } by { ld %1,a or a,a jp %3,%4 ; peephole 115 used value still in a instead of reloading from %1. } replace { jp %5 ret } by { jp %5 ; peephole 116 removed unused ret. } replace { jp %5 ld sp,ix pop ix ret } by { jp %5 ; peephole 117 removed unused ret. } replace restart { or a,%1 jp NZ,%2 xor a,a jp %3 } by { or a,%1 jp NZ,%2 ; peephole 118 removed redundant zeroing of a (which has just been tested to be #0x00). jp %3 } // 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 { ; peephole 119 used ex to load hl into de. ex de,hl } if notUsed('hl') replace restart { ld l,e ld h,d } by { ; peephole 120 used ex to load de into hl. ex de,hl } if notUsed('de') barrier // Should be one of the last ones. Opens the code to further peephole optimization. replace restart { %1: } by { ; peephole 121 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 { ; peephole 123 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 { ; peephole 124 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 { ; peephole 125 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 { ; peephole 126 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 { ; peephole 127 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 { ; peephole 128 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 { ; peephole 129 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 { ; peephole 130 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 { ; peephole 131 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 { ; peephole 132 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 ; peephole 122 replaced jump by return. } if labelIsReturnOnly(%5), labelRefCountChange(%5 -1) replace restart { jp %1,%5 } by { ret %1 ; peephole 134 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 { jp %5 } by { jr %5 ; peephole 135 changed absolute to relative unconditional jump. } if labelInRange(%5) replace { jp Z,%5 } by { jr Z,%5 ; peephole 136 changed absolute to relative conditional jump. } if labelInRange(%5) replace { jp NZ,%5 } by { jr NZ,%5 ; peephole 137 changed absolute to relative conditional jump. } if labelInRange(%5) replace { jp C,%5 } by { jr C,%5 ; peephole 138 changed absolute to relative conditional jump. } if labelInRange(%5) replace { jp NC,%5 } by { jr NC,%5 ; peephole 139 changed absolute to relative conditional jump. } if labelInRange(%5) replace { dec b jr NZ, %5 } by { djnz %5 ; peephole 140 used djnz }