X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fpeeph-z80.def;h=cf5a83d4f7d1ec66a522cb456f06b6a85c0f6447;hb=d0d1319aba1a3ae007786c03c49f0ca82b480365;hp=f717847ad2a11dd08f784864a7cbd5d78ba05909;hpb=3d5f7dfa8edf8ea9a0e1b0d74ab0daadbf7e819c;p=fw%2Fsdcc diff --git a/src/z80/peeph-z80.def b/src/z80/peeph-z80.def index f717847a..cf5a83d4 100644 --- a/src/z80/peeph-z80.def +++ b/src/z80/peeph-z80.def @@ -1,3 +1,1337 @@ +// peeph.def - Common Z80 and gbz80 peephole rules +// +// 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 - 2008 +// +// 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 -1 removed redundant load. +} if notVolatile(%1) + +// This one doesn't work currently since the peephole optimizer can't match lines generated by multiline macros: Bug #1570701 +//replace restart { +// pop af +// ld sp,%1 +//} by { +// ; peephole -1a eleminated dead pop. +// ld sp,%1 +//} if notUsed('a') + +replace restart { + ld %1,%2 +} by { + ; peephole 0a removed dead load from %2 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,%2 + ld a,%1 +} by { + ; peephole 0b loaded %2 into a directly instead of going through %1. + ld a,%2 +} if notVolatile(%1), notUsed(%1) + +replace restart { + ld %1,%2 (%3) + ld a,%1 +} by { + ; peephole 0c loaded %2 (%3) into a directly instead of going through %1. + ld a,%2 (%3) +} if notVolatile(%1), notUsed(%1) + +replace restart { + ld %1,#%2 + ld a,%3 (%1) +} by { + ; peephole 0d loaded %2 into a directly instead of going through %1. + ld a,(#%2+%3) +} if notUsed(%1) + +replace restart { + srl %1 + ld a,%1 +} by { + ld a,%1 + ; peephole 0e shifted in a instead of %1. + srl a +} if notVolatile(%1), notUsed(%1) + +replace restart { + ld %1,(hl) + ld a,%2 (%3) + sub a,%1 +} by { + ld a,%2 (%3) + ; peephole 0f 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 0g incremented in hl instead of bc. + inc hl +} if notUsed('bc') + +// Catch double and triple incs before later peepholes introduce an ex de,hl in here. +replace restart { + inc de + inc de + ld l,e + ld h,d +} by { + ld l,e + ld h,d + ; peephole 0h' incremented in hl instead of de. + inc hl + inc hl +} if notUsed('de') + +replace restart { + inc de + ld l,e + ld h,d +} by { + ld l,e + ld h,d + ; peephole 0h incremented in hl instead of de. + inc hl +} if notUsed('de') + +replace restart { + ld e,%1 + ld d,%2 + ld l,e + ld h,d +} by { + ; peephole 0i loaded %2%1 into hl directly instead of going through de. + ld l,%1 + ld h,%2 +} if notUsed('de') + +replace restart { + ld bc,#%2 + %3 + ld a,(bc) + ld c,a +} by { + ; peephole 0j used hl for #%2 + %3 instead of bc, not going through a. + ld hl,#%2 + %3 + ld c,(hl) +} if notUsed('a'), notUsed('hl') + +replace restart { + ld de,#%2 + %3 + ld a,(de) + ld e,a +} by { + ; peephole 0j' used hl for #%2 + %3 instead of de, not going through a. + ld hl,#%2 + %3 + ld e,(hl) +} if notUsed('a'), notUsed('hl') + +replace restart { + ex de,hl + push hl +} by { + ; peephole 0k pushed de directly instead of going through hl. + push de +} if notUsed('de'), notUsed('hl') + +replace restart { + ex de,hl + push de +} by { + ; peephole 0k' pushed hl directly instead of going through de. + push hl +} if notUsed('de'), notUsed('hl') + +replace restart { + ld l,%1 + ld h,d + push hl +} by { + ; peephole 0k'' pushed de instead of hl removing a load. + ld e,%1 + push de +} if notUsed('hl'), notUsed('e') + +replace restart { + ex de,hl + push bc + push de +} by { + ; peephole 0l pushed hl directly instead of going through de. + push bc + push hl +} if notUsed('de'), notUsed('hl') + +replace restart { + ld l,c + ld h,b + push hl +} by { + ; peephole 0m pushed bc directly instead of going through hl. + push bc +} if notUsed('hl') + +replace restart { + ld l,%1 + ld h,b + push hl +} by { + ; peephole 0m' pushed bc instead of hl removing a load. + ld c,%1 + push bc +} if notUsed('hl'), notUsed('c') + +replace restart { + ld c,a + push de + ld a,c +} by { + ; peephole 0n removed redundant load of a through c. + push de +} if notUsed('c') + +replace restart { + ld c,e + ld b,d + ld a,(bc) +} by { + ; peephole 0o used de directly instead of going through bc. + ld a,(de) +} if notUsed('bc') + +replace restart { + pop de + ld l,e + ld h,d +} by { + ; peephole 0p popped hl directly instead of going through de. + pop hl +} if notUsed('de') + +replace restart { + ld %1,a + ld %2 (%3),%1 +} by { + ; peephole 0q loaded a into %2 (%3) directly instead of going through %1. + ld %2 (%3),a +} if notVolatile(%1), notUsed(%1) + +replace restart { + ld %1 (ix),%2 + ld %3, %1 (ix) +} by { + ; peephole 0r loaded %3 from %2 instead of going through %1 (ix). + ld %1 (ix),%2 + ld %3, %2 +} +// Don't need to check for volatile, since ix is used for the stack. + +replace restart { + ld %1, %2 (%3) + ld b, %1 +} by { + ; peephole 0s loaded b from %2 (%3) instead of going through %1. + ld b, %2 (%3) +} if notVolatile(%1), notUsed(%1) + +// Bug #2728445 +//replace restart { +// ld %1,a +// ld %2,%3 +// ld %4,%1 +//} by { +// ; peephole 0t loaded %4 from a instead of going through %1. +// ld %1,a +// ld %2,%3 +// ld %4,a +//} if notVolatile(%1), operandsNotRelated(%1 %3), operandsNotRelated(%1 %2) + +replace restart { + ld %1,a + ld a,%2 + adc a,#%3 + ld %4,%1 +} by { + ld %1,a + ; peephole 0t' loaded %4 from a instead of going through %1. + ld %4,a + ld a,%2 + adc a,#%3 +} if notVolatile(%1), operandsNotRelated(%1 %2), operandsNotRelated(%4 %2) + +replace restart { + ld %1,a + ld a,#%2 + adc a,#%3 + ld %4,%1 +} by { + ld %1,a + ; peephole 0t'' loaded %4 from a instead of going through %1. + ld %4,a + ld a,#%2 + adc a,#%3 +} if notVolatile(%1) + +replace restart { + ld %1,(hl) + ld e,%1 +} by { + ; peephole 0u loaded e from (hl) instead of going through %1. + ld e,(hl) +} if notUsed(%1) + +replace restart { + ld %1,l + ld %2 (%3),%1 +} by { + ; peephole 0v loaded %2 (%3) from l instead of going through %1. + ld %2 (%3),l +} if notUsed(%1) + +replace restart { + ld l,%1 (ix) + ld h,%2 (ix) + ld %3,(hl) + srl %3 + ld l,%1 (ix) + ld h,%2 (ix) + ld (hl),%3 +} by { + ld l,%1 (ix) + ld h,%2 (ix) + ; peephole 0w shifted (hl) in place. + srl (hl) + ld %3,(hl) +} if notVolatile(%3) +// Don't check for volatile since ix points to the stack. + +replace restart { + push af + inc sp + ld a,e + push af + inc sp +} by { + ; peephole 0x 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,c + push af + inc sp +} by { + ; peephole 0y pushed bc instead of pushing a twice. + ld b,a + push bc +} if notUsed('b'), notUsed('a') + +replace restart { + ld a,#%1 + ld d,a +} by { + ; peephole 0z loaded #%1 into d directly instead of going through a. + ld d,#%1 +} if notUsed('a') + +replace restart { + ld a,%1 (ix) + push af + inc sp + ld a,%2 (ix) + push af + inc sp +} by { + ; peephole 0za pushed %1 (ix), %2(ix) through hl instead of af. + ld h,%1 (ix) + ld l,%2 (ix) + push hl +} if notUsed('a'), notUsed('hl') + +replace restart { + ld c,l + ld b,h + push bc +} by { + ; peephole 0zb pushed hl instead of bc. + push hl +} if notUsed('bc') + +// Doesn'T work due to bug #1947081 +//replace restart { +// pop %1 +// push %1 +//} by { +// ; peephole 0zc eleminated dead pop/push pair. +//} if notUsed(%1) + +replace restart { + ld iy,#%1 + or a,%2 (iy) +} by { + ; peephole 0zd 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 (%4) +} by { + ; peephole 0ze used hl instead of iy. + ld hl,#%1 + %3 + ld %2,(hl) +} if notUsed('iy'), notUsed('hl') + +replace restart { + ld iy,#%1 + ld %2 (%3), %4 +} by { + ; peephole 0zf used hl instead of iy. + ld hl,#%1 + %2 + ld (hl), %4 +} if notUsed('iy'), notUsed('hl'), operandsNotRelated(%4 'h'), operandsNotRelated(%4 'l') + +replace restart { + ld e,l + ld d,h + ld %1,(de) +} by { + ; peephole 0zg loaded %1 from (hl) directly instead of going through (de). + ld %1,(hl) +} if notUsed('de') + +replace restart { + ld c,l + ld b,h + ld %1,(bc) +} by { + ; peephole 0zh loaded %1 from (hl) directly instead of going through (bc). + ld %1,(hl) +} if notUsed('bc') + +replace restart { + ld c,l + ld b,h + inc bc +} by { + ; peephole 0zi incremented in hl instead of bc. + inc hl + ld c,l + ld b,h +} if notUsed('hl') + +replace restart { + ld a,%1 (%2) + bit %3,a +} by { + ; peephole 0zj tested bit of %1 (%2) directly instead of going through a. + bit %3,%1 (%2) +} if notUsed('a') + +replace restart { + ld bc, #%1 + %2 + ld l,c + ld h,b +} by { + ; peephole 0zk stored constant #%1 + %2 into hl directly instead of going through bc. + ld hl, #%1 + %2 +} if notUsed('bc') + +replace restart { + ld c, %1 (%2) + ld b, %3 (%4) + ld l,c + ld h,b +} by { + ; peephole 0zk' stored %1 (%2) %3 (%4) into hl directly instead of going through bc. + ld l, %1 (%2) + ld h, %3 (%4) +} if notUsed('bc') + +replace restart { + jp NC,%1 + jp %2 +%1: +} by { + jp C,%2 + ; peephole 3 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 4 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 5 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 6 removed jp by using inverse jump logic +%1: +} if labelRefCountChange(%1 -1) + +replace restart { + jp %5 +} by { + jp %6 + ; peephole 7 redirected jump-to-jump at %5 by jump to %6 +} if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1) + +replace restart { + jp %1,%5 +} by { + jp %1,%6 + ; peephole 8 redirected jump-to-jump at %5 by jump to %6 +} if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1) + +replace restart { + xor a,a + ld a,#0x00 +} by { + xor a,a + ; peephole 10 removed redundant load of 0 into a. +} + +replace { + ld e,#0x%1 + ld d,#0x%2 +} by { + ld de,#0x%2%1 + ; peephole 11 combined constant loads into register pair. +} + +replace { + ld l,#0x%1 + ld h,#0x%2 +} by { + ld hl,#0x%2%1 + ; peephole 12 combined constant loads into register pair. +} + +replace { + ld c,#0x%1 + ld b,#0x%2 +} by { + ld bc,#0x%2%1 + ; peephole 13 combined constant loads into register pair. +} + +replace restart { + ld %1,a + ld a,%1 +} by { + ld %1,a + ; peephole 14 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 a,%1 + ld %1,a +} by { + ld a,%1 + ; peephole 15 removed redundant load from a into %1. +} 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 %1,a + ld a,%2 + or a,%1 +} by { + ld %1,a + or a,%2 + ; peephole 17a removed load by reordering or arguments. +} if notVolatile(%1) + +replace restart { + ld %1,a + ld a,%2 (ix) + or a,%1 +} by { + ld %1,a + or a,%2 (ix) + ; peephole 17b removed load by reordering or arguments. +} if notVolatile(%1) + +replace restart { + ld %1,a + xor a,a + or a,%1 +} by { + ld %1,a + or a,a + ; peephole 18 used value still in a instead of loading it from %1. +} + +replace restart { + or a,%1 + or a,a +} by { + or a,%1 + ; peephole 19 removed redundant or after or. +} + +replace restart { + or a,%1 (%2) + or a,a +} by { + or a,%1 (%2) + ; peephole 19a removed redundant or after or. +} + +replace restart { + and a,%1 + or a,a +} by { + and a,%1 + ; peephole 20 removed redundant or after and. +} + +replace restart { + and a,%1 (%2) + or a,a +} by { + and a,%1 (%2) + ; peephole 20a removed redundant or after and. +} + +replace restart { + xor a,%1 + or a,a +} by { + xor a,%1 + ; peephole 21 removed redundant or after xor. +} + +replace restart { + xor a,%1 (%2) + or a,a +} by { + xor a,%1 (%2) + ; peephole 21a removed redundant or after xor. +} + +replace { + ld %1,%2 + ld a,%2 +} by { + ld a,%2 + ld %1,a + ; peephole 23 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 24 removed redundant load from %3%1 into %4%2 +} if notVolatile(%1 %2 %3 %4) + +replace restart { + ld a,c + push af + inc sp + ld a,#%2 + push af + inc sp + call %3 +} by { + ld b,c + ld c,#%2 + push bc + ; peephole 31 moved and pushed arguments c and #%2 through bc instead of pushing them individually. + call %3 +} + +replace restart { + ld a,e + push af + inc sp + ld a,#%2 + push af + inc sp + call %3 +} by { + ld d,e + ld e,#%2 + push de + ; peephole 32 moved and pushed arguments e and #%2 through de instead of pushing them individually. + call %3 +} + +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 33 removed load by replacing sub with cp + assert a=%1 +} if notVolatile(%1) + +replace restart { + assert a=%1 + sub a,%2 + jp %3,%4 + ld a,%1 +} by { + cp a,#%2 + jp %3,%4 + ; peephole 34 removed load by replacing sub with cp + assert a=%1 +} + +replace restart { + assert a=%1 +} by { +} + +replace restart { + sub a,#0xFF + jp Z,%1 +} by { + inc a + ; peephole 35 replaced sub a,#0xFF by inc a. + jp Z,%1 +} + +replace restart { + sub a,#0xFF + jp NZ,%1 +} by { + inc a + ; peephole 36 replaced sub a,#0xFF by inc a. + jp NZ,%1 +} + +replace restart { + ld bc,#%1 + %2 + ld a,c + add a,%3 + ld c,a + ld a,b + adc a,%4 + ld b,a +} by { + ld a,#<(%1 + %2) + add a,%3 + ld c,a + ld a,#>(%1 + %2) + ; peephole 37 directly used (%1 + %2) in calculation instead of placing it in bc first. + adc a,%4 + ld b,a +} + +replace restart { + ld de,#%1 + %2 + ld a,e + add a,%3 + ld e,a + ld a,d + adc a,%4 + ld d,a +} by { + ld a,#<(%1 + %2) + add a,%3 + ld e,a + ld a,#>(%1 + %2) + ; peephole 38 directly used (%1 + %2) in calculation instead of placing it in de first. + adc a,%4 + ld d,a +} + +replace restart { + rlca + ld a,#0x00 + rla +} by { + rlca + and a,#0x01 + ; peephole 39 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 40 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 41 removed lower part of multibyte addition. + ld %2,a + ld a,%3 + add a,%4 +} + +replace restart { + ld %1,a + ld a,%2 + add a,%1 +} by { + ; peephole 42 removed loads by exploiting commutativity of addition. + add a,%2 +} if notVolatile(%1), notUsed(%1), operandsNotRelated(%2 '(bc)' '(de)') + +replace restart { + ld %1 (ix),a + ld a,#%2 + add a,%1 (ix) +} by { + ld %1 (ix),a + ; peephole 42a removed loads by exploiting commutativity of addition. + add a,#%2 +} +// Don't need to check for volatile, since ix is used to access the stack. + +// sdcc does not use the H flag. sla resets it, while add sets it. +// To ensure that the state of the H flag is not changed by this +// peephole uncomment the add %3, %4 at the end (since it overwrite the H flag). +replace restart { + ld %1, a + sla %1 + ld a, %2 + //add %3, %4 +} by { + add a, a + ; peephole 42b shifted in accumulator insted of %1 + ld %1, a + ld a, %2 + //add %3, %4 +} + +// sdcc does not use the H flag. sla resets it, while add sets it. +// To ensure that the state of the H flag is not changed by this +// peephole uncomment the add %3, %4 at the end (since it overwrite the H flag). +replace restart { + ld %1, a + sla %1 + sla %1 + ld a, %2 + //add %3, %4 +} by { + add a, a + add a, a + ; peephole 42b' shifted in accumulator insted of %1 + ld %1, a + ld a, %2 + //add %3, %4 +} + +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) + ; peephole 42c incremented in (hl) instead of going through a. +} if notUsed('a') + +replace restart { + ld l,%1 (ix) + ld h,%2 (ix) + ld a,(hl) + dec a + ld l,%1 (ix) + ld h,%2 (ix) + ld (hl),a +} by { + ld l,%1 (ix) + ld h,%2 (ix) + dec (hl) + ; peephole 42d decremented in (hl) instead of going through a. +} if notUsed('a') + +replace restart { + ld %1,a + ld a,%2 + add a,%1 +} by { + ld %1, a + ; peephole 43 removed load by exploiting commutativity of addition. + add a,%2 +} if operandsNotRelated(%2 '(bc)' '(de)') + +replace restart { + ld c,l + ld b,h + ld hl,#%1 + add hl,bc +} by { + ; peephole 43a 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 43b removed loads by exploiting commutativity of addition. + ld hl,#%1 + %4 + add hl,%2 +} if notUsed('bc') + +replace restart { + ld c,e + ld b,d + ld hl,#%1 + add hl,bc +} by { + ; peephole 43c removed loads by exploiting commutativity of addition. + ld hl,#%1 + add hl,de +} if notUsed('bc') + +replace restart { + or a,%1 + jp NZ,%2 + xor a,a + or a,%3 +} by { + or a,%1 + jp NZ,%2 + ; peephole 44 removed redundant zeroing of a (which has just been tested to be #0x00). + or a,%3 +} + +replace restart { + or a,%1 + jp NZ,%2 + ld %3,#0x00 +} by { + or a,%1 + jp NZ,%2 + ld %3,a + ; peephole 45 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 46 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 + ; peephole 47 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 + ; peephole 48 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 49 shortened or using a (which has just been tested to be #0x00). +//} if operandsNotSame3(%3 '(bc)' '(de)') + +//replace restart { +// and a,%1 +// jp NZ,%2 +// ld a,%3 +// or a,a +//} by { +// and a,%1 +// jp NZ,%2 +// or a,%3 +// ; peephole 50 shortened or using a (which has just been tested to be #0x00). +//} if operandsNotSame3(%3 '(bc)' '(de)') + +// Commented out sine it triggers for %3 od the form (#...) +//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 51 shortened or using a (which has just been tested to be #0x00). +//} +//if operandsNotSame3(%3 '(bc)' '(de)') + +replace restart { + dec a + jp NZ,%1 + ld a,%2 + or a,a +} by { + dec a + jp NZ,%1 + or a,%2 + ; peephole 52 shortened or using a (which has just been tested to be #0x00). +} +//if operandsNotSame3(%2 '(bc)' '(de)') + +replace restart { + or a,%1 + jp NZ,%2 + push %3 + ld %4,#0x00 +} by { + or a,%1 + jp NZ,%2 + push %3 + ld %4,a + ; peephole 53 replaced constant #0x00 by a (which has just been tested to be #0x00). +} + +replace restart { + and a,%1 + jp NZ,%2 + push %3 + ld %4,#0x00 +} by { + sub a,%1 + jp NZ,%2 + push %3 + ld %4,a + ; peephole 54 replaced constant #0x00 by a (which has just been tested to be #0x00). +} + +replace restart { + sub a,%1 + jp NZ,%2 + push %3 + ld %4,#0x00 +} by { + sub a,%1 + jp NZ,%2 + push %3 + ld %4,a + ; peephole 55 replaced constant #0x00 by a (which has just been tested to be #0x00). +} + +replace restart { + dec a + jp NZ,%1 + push %2 + ld %3,#0x00 +} by { + dec a + jp NZ,%1 + push %2 + ld %3,a + ; peephole 56 replaced constant #0x00 by a (which has just been tested to be #0x00). +} + +replace restart { + ld de,#%1 + %2 + inc de +} by { + ld de,#%1 + %2+1 + ; peephole 59 moved increment of de to constant. +} + +replace restart { + ld bc,#%1 + %2 + inc bc +} by { + ld bc,#%1 + %2+1 + ; peephole 62 moved increment of bc to constant. +} + +replace restart { + ld bc,#%1 + ld a,c + add a,#0x%2 + ld c,a + ld a,b + adc a,#0x%3 + ld b,a +} by { + ld bc,#%1 + 0x%3%2 + ; peephole 63 moved addition of constant 0x%3%2 to bc to constant. +} + +replace restart { + call %1 + ret +} by { + jp %1 + ; peephole 65 replaced call at end of function by jump. +} + +// Callee saves ix. +replace restart { + call %1 + pop ix + ret +} by { + pop ix + jp %1 + ; peephole 66 replaced call at end of function by jump moving call beyond pop ix. +} + +replace restart { + ld %1,a + ld %2,%1 + ld %3,%1 +} by { + ; peephole 67 loaded %2, %3 from a instead of %1. + ld %1,a + ld %2,a + ld %3,a +} if notVolatile(%1) + +replace restart { + ld %1,a + ld %2,a + ld %3,%1 +} by { + ld %1,a + ld %2,a + ; peephole 68 loaded %3 from a instead of %1. + ld %3,a +} if notVolatile(%1) + +replace restart { + ld %1,l + xor a,a + or a,%1 +} by { + ld %1,l + xor a,a + ; peephole 69 used l in or instead of %1. + or a,l +} if notVolatile(%1) + +replace restart { + ld %1,#%2 + ld %3,%4 + ld %1,#%2 +} by { + ld %1,#%2 + ld %3,%4 + ; peephole 70 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 70a used #%1 from hl for load into de. + ld hl,#%1 + ld e,l + ld d,h +} + +replace restart { + ld hl,#%1 + push hl + ld l,e + ld h,d + jp (hl) +%1: +} by { + ; peephole 71 used ex to get de into hl. + ex de,hl + ld de,#%1 + push de + jp (hl) +%1: +} +// Lets' hope this is never applied to a jump table. It's fine for calls. + +// Should be after 0z. +replace restart { + ld %1 (ix),l + ld %2 (ix),h + ld %3,%1 (ix) + ld %4,%2 (ix) +} by { + ld %1 (ix),l + ld %2 (ix),h + ; peephole 72 used hl instead of %2 (ix), %1 (ix) to load %4%3. + ld %3,l + ld %4,h +} if operandsNotRelated('h' %3) +// Don't check for volatile since ix points to the stack. + +replace restart { + ld %1, a + ld a, %2 (%3) + adc a, #%4 + ld l, %1 +} by { + ld l, a + ld a, %2 (%3) + adc a, #%4 + ; peephole 76 loaded l from a directly instead of going through %1. +} if notUsed(%1) + +replace restart { + ld %1, a + ld a, #%2 + adc a, #%3 + ld l, %1 +} by { + ld l, a + ld a, #%2 + adc a, #%3 + ; peephole 77 loaded l from a directly instead of going through %1. +} if notUsed(%1) + +replace restart { + ld hl, #%1 + add hl, %2 + ex de, hl + ld hl, #%3 + add hl, de +} by { + ld hl, #%1+%3 + add hl, %2 + ; peephole 78 removed addition and loads exploiting commutativity of addition. +} if notUsed('de') + +replace restart { + ex de, hl + ld hl, #%1 + add hl, de +} by { + ; peephole 78a 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 79 moved increment to constant. + add hl, %2 + ex de, hl +} if notUsed('hl') + +// These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed(). +replace restart { + ld d,h + ld e,l +} by { + ; peephole 80 used ex to load hl into de. + ex de,hl +} if notUsed('hl') + +replace restart { + ld e,l + ld d,h +} by { + ; peephole 81 used ex to load hl into de. + ex de,hl +} if notUsed('hl') + +replace restart { + ld l,e + ld h,d +} by { + ; peephole 82 used ex to load de into hl. + ex de,hl +} if notUsed('de') + // peeph-z80.def - Z80 peephole rules // // @@ -19,23 +1353,23 @@ replace restart { ld %1,#%2 - ld a,0(%1) - ld %3,a + ld a,%3 (%1) + ld %4,a ld %1,#%5 } by { - ld a,(#%2) + ld a,(#%2 + %3) ; peephole z1 used #%2 directly instead of going through %1 using indirect addressing. - ld %3,a + ld %4,a ld %1,#%5 } replace restart { ld %1,#%2 - ld 0(%1),a + ld %3 (%1),a %4: ld %1,%5 } by { - ld (#%2),a + ld (#%2 + %3),a ; peephole z2 directly used #%2 instead of going through %1 using indirect addressing. %4: ld %1,%5 @@ -44,67 +1378,35 @@ replace restart { replace restart { pop af ld %1,#%2 - ld 0(%1),%3 - ld %1,#%4 + ld %3 (%1),%4 + ld %1,#%5 } by { - ld a,%3 - ld (#%2),a + ld a,%4 + ld (#%2 + %3),a ; peephole z3 used #%2 directly instead of going through %1 using indirect addressing. pop af - ld %1,#%4 + ld %1,#%5 } if operandsNotRelated(%3 'a') replace restart { ld bc,#%1 + %2 ld a,%3 ld (bc),a - ld bc,#%4 + %5 } by { ld a,%3 ld (#%1 + %2),a ; peephole z4 directly used address #%1 + %2 instead of placing it in bc first. - ld bc,#%4 + %5 -} +} if notUsed('bc') replace restart { ld bc,#%1 + %2 + %6 ld a,%3 ld (bc),a - ld bc,#%4 + %5 } by { ld a,%3 ld (#%1 + %2 + %6),a ; peephole z5 directly used address #%1 + %2 + %6 instead of placing it in bc first. - ld bc,#%4 + %5 -} - -replace restart { - ld bc,#%1 + %2 - ld a,%3 - ld (bc),a -%7: - ld bc,#%4 + %5 -} by { - ld a,%3 - ld (#%1 + %2),a - ; peephole z6 directly used address #%1 + %2 instead of placing it in bc first. -%7: - ld bc,#%4 + %5 -} - -replace restart { - ld bc,#%1 + %2 + %6 - ld a,%3 - ld (bc),a -%7: - ld bc,#%4 + %5 -} by { - ld a,%3 - ld (#%1 + %2 + %6),a - ; peephole z7 directly used address #%1 + %2 + %6 instead of placing it in bc first. -%7: - ld bc,#%4 + %5 -} +} if notUsed('bc') replace restart { ld c,%1 @@ -151,22 +1453,72 @@ replace restart { jp %1,%5 } by { ret %1 - ; peephole z12 replaced jump by return. + ; peephole z11a replaced jump by return. } if labelIsReturnOnly(), labelRefCountChange(%5 -1) // Should be one of the last ones. Opens the code to further peephole optimization. replace restart { %1: } by { - ; peephole z13 removed unused label %1. + ; peephole z12 removed unused label %1. } if labelRefCount(%1 0) +// Applying z11 or z11a followed by z12 will often leave a dead ret at the end of the function. Remove it. +replace { + jp %5 + ret +} by { + jp %5 + ; peephole z13 removed unused ret. +} + +// These four need two be here since the peephole optimizer continues to apply rules further down the file even for replace restart rules. +replace restart { + jp NC,%1 + jp %2 +%1: +} by { + jp C,%2 + ; peephole 5' 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 5' 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 5' 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 6' removed jp by using inverse jump logic +%1: +} if labelRefCountChange(%1 -1) + // These should be the last rules, so that the peepholes above need to look at jp only. replace { jp %5 } by { jr %5 - ; peephole z14 changed absolute to relative conditional jump. + ; peephole z14 changed absolute to relative unconditional jump. } if labelInRange() replace {