Minor peephole improvement
[fw/sdcc] / src / z80 / peeph-z80.def
1 // peeph.def - Common Z80 and gbz80 peephole rules
2 //
3 // These peepholes could be potentially moved to peeph.def, but a GBZ80 expert
4 // Should have a look at them before.
5 //
6 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2008
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 2, or (at your option) any
11 // later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 replace restart {
23         ld      %1,%1
24 } by {
25         ; peephole -1 removed redundant load.
26 } if notVolatile(%1)
27
28 // This one doesn't work currently since the peephole optimizer can't match lines generated by multiline macros: Bug #1570701
29 //replace restart {
30 //      pop     af
31 //      ld      sp,%1
32 //} by {
33 //      ; peephole -1a eleminated dead pop.
34 //      ld      sp,%1
35 //} if notUsed('a')
36
37 replace restart {
38         ld      %1,%2
39 } by {
40         ; peephole 0a removed dead load from %2 into %1.
41 } if notVolatile(%1), notUsed(%1)
42 // Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail.
43
44 replace restart {
45         ld      %1,%2
46         ld      a,%1
47 } by {
48         ; peephole 0b loaded %2 into a directly instead of going through %1.
49         ld      a,%2
50 } if notVolatile(%1), notUsed(%1)
51
52 replace restart {
53         ld      %1,%2 (%3)
54         ld      a,%1
55 } by {
56         ; peephole 0c loaded %2 (%3) into a directly instead of going through %1.
57         ld      a,%2 (%3)
58 } if notVolatile(%1), notUsed(%1)
59
60 replace restart {
61         ld      %1,#%2
62         ld      a,%3 (%1)
63 } by {
64         ; peephole 0d loaded %2 into a directly instead of going through %1.
65         ld      a,(#%2 + %3)
66 } if notUsed(%1)
67
68 replace restart {
69         srl     %1
70         ld      a,%1
71 } by {
72         ld      a,%1
73         ; peephole 0e shifted in a instead of %1.
74         srl     a
75 } if notVolatile(%1), notUsed(%1)
76
77 replace restart {
78         ld      %1,(hl)
79         ld      a,%2 (%3)
80         sub     a,%1
81 } by {
82         ld      a,%2 (%3)
83         ; peephole 0f used (hl) in sub directly instead of going through %1.
84         sub     a,(hl)
85 } if notVolatile(%1), notUsed(%1)
86
87 replace restart {
88         inc     de
89         inc     de
90         ld      l,e
91         ld      h,d
92 } by {
93         ld      l,e
94         ld      h,d
95         ; peephole 0g incremented in hl instead of de.
96         inc     hl
97         inc     hl
98 } if notUsed('de')
99
100 replace restart {
101         inc     de
102         ld      l,e
103         ld      h,d
104 } by {
105         ld      l,e
106         ld      h,d
107         ; peephole 0h incremented in hl instead of de.
108         inc     hl
109 } if notUsed('de')
110
111 replace restart {
112         ld      e,%1
113         ld      d,%2
114         ld      l,e
115         ld      h,d
116 } by {
117         ; peephole 0i loaded %2%1 into hl directly instead of going through de.
118         ld      l,%1
119         ld      h,%2
120 } if notUsed('de')
121
122 replace restart {
123         ld      bc,#%2 + %3
124         ld      a,(bc)
125         ld      c,a
126 } by {
127         ; peephole 0j used hl for #%2 + %3 instead of bc, not going through a.
128         ld      hl,#%2 + %3
129         ld      c,(hl)
130 } if notUsed('a'), notUsed('hl')
131
132 replace restart {
133         ex      de,hl
134         push    hl
135 } by {
136         ; peephole 0k pushed de directly instead of going through hl.
137         push    de
138 } if notUsed('de'), notUsed('hl')
139
140 replace restart {
141         ex      de,hl
142         push    de
143 } by {
144         ; peephole 0k' pushed de directly instead of going through hl.
145         push    hl
146 } if notUsed('de'), notUsed('hl')
147
148 replace restart {
149         ex      de,hl
150         push    bc
151         push    de
152 } by {
153         ; peephole 0l pushed hl directly instead of going through de.
154         push    bc
155         push    hl
156 } if notUsed('de'), notUsed('hl')
157
158 replace restart {
159         ld      l,c
160         ld      h,b
161         push    hl
162 } by {
163         ; peephole 0m pushed bc directly instead of going through hl.
164         push    bc
165 } if notUsed('hl')
166
167 replace restart {
168         ld      c,a
169         push    de
170         ld      a,c
171 } by {
172         ; peephole 0n removed redundant load of a through c.
173         push    de
174 } if notUsed('c')
175
176 replace restart {
177         ld      c,e
178         ld      b,d
179         ld      a,(bc)
180 } by {
181         ; peephole 0o used de directly instead of going through bc.
182         ld      a,(de)
183 } if notUsed('bc')
184
185 replace restart {
186         pop     de
187         ld      l,e
188         ld      h,d
189 } by {
190         ; peephole 0p popped hl directly instead of going through de.
191         pop     hl
192 } if notUsed('de')
193
194 replace restart {
195         ld      %1,a
196         ld      %2 (%3),%1
197 } by {
198         ; peephole 0q loaded a into %2 (%3) directly instead of going through %1.
199         ld      %2 (%3),a
200 } if notVolatile(%1), notUsed(%1)
201
202 replace restart {
203         ld      %1 (ix),%2
204         ld      %3, %1 (ix)
205 } by {
206         ; peephole 0r loaded %3 from %2 instead of going through %1 (ix).
207         ld      %1 (ix),%2
208         ld      %3, %2
209 }
210 // Don't need to check for volatile, since ix is used for the stack.
211
212 replace restart {
213         ld      %1, %2 (%3)
214         ld      b, %1
215 } by {
216         ; peephole 0s loaded b from %2 (%3) instead of going through %1.
217         ld      b, %2 (%3)
218 } if notVolatile(%1), notUsed(%1)
219
220 replace restart {
221         ld      %1,a
222         ld      %2,%3
223         ld      %4,%1
224 } by {
225         ; peephole 0t loaded %4 from a instead of going through %1.
226         ld      %1,a
227         ld      %2,%3
228         ld      %4,a
229 } if notVolatile(%1), operandsNotRelated(%1 %3), operandsNotRelated(%1 %2)
230
231 replace restart {
232         ld      %1,(hl)
233         ld      e,%1
234 } by {
235         ; peephole 0u loaded e from (hl) instead of going through %1.
236         ld      e,(hl)
237 } if notUsed(%1)
238
239 replace restart {
240         ld      %1,l
241         ld      %2 (%3),%1
242 } by {  
243         ; peephole 0v loaded %2 (%3) from l instead of going through %1.
244         ld      %2 (%3),l
245 } if notUsed(%1)
246
247 replace restart {
248         ld      l,%1 (ix)
249         ld      h,%2 (ix)
250         ld      %3,(hl)
251         srl     %3
252         ld      l,%1 (ix)
253         ld      h,%2 (ix)
254         ld      (hl),%3
255 } by {  
256         ld      l,%1 (ix)
257         ld      h,%2 (ix)
258         ; peephole 0w shifted (hl) in place.
259         srl     (hl)
260         ld      %3,(hl)
261 } if notVolatile(%3)
262 // Don't check for volatile since ix points to the stack.
263
264 replace restart {
265         push    af
266         inc     sp
267         ld      a,e
268         push    af
269         inc     sp
270 } by {
271         ; peephole 0x pushed de instead of pushing a twice.
272         ld      d,a
273         push    de
274 } if notUsed('d'), notUsed('a')
275
276 replace restart {
277         push    af
278         inc     sp
279         ld      a,c
280         push    af
281         inc     sp
282 } by {
283         ; peephole 0y pushed bc instead of pushing a twice.
284         ld      b,a
285         push    bc
286 } if notUsed('b'), notUsed('a')
287
288 replace restart {
289         ld      a,#%1
290         ld      d,a
291 } by {
292         ; peephole 0z loaded #%1 into d directly instead of going through a.
293         ld      d,#%1
294 } if notUsed('a')
295
296 replace restart {
297         ld      a,%1 (ix)
298         push    af
299         inc     sp
300         ld      a,%2 (ix)
301         push    af
302         inc     sp
303 } by {
304         ; peephole 0za pushed %1 (ix), %2(ix) through hl instead of af.
305         ld      h,%1 (ix)
306         ld      l,%2 (ix)
307         push    hl
308 } if notUsed('a'), notUsed('hl')
309
310 replace restart {
311         ld      c,l
312         ld      b,h
313         push    bc
314 } by {
315         ; peephole 0zb pushed hl instead of bc.
316         push    hl
317 } if notUsed('bc')
318
319 // Doesn'T work due to bug #1947081
320 //replace restart {
321 //      pop     %1
322 //      push    %1
323 //} by {
324 //      ; peephole 0zc eleminated dead pop/push pair.
325 //} if notUsed(%1)
326
327 replace restart {
328         ld      iy,#%1
329         or      a,%2 (iy)
330 } by {
331         ; peephole 0zd used hl instead of iy.
332         ld      hl,#%1 + %2
333         or      a,(hl)
334 } if notUsed('iy'), notUsed('hl')
335
336 replace restart {
337         ld      iy,#%1
338         ld      %2,%3 (%4)
339 } by {
340         ; peephole 0ze used hl instead of iy.
341         ld      hl,#%1 + %3
342         ld      %2,(hl)
343 } if notUsed('iy'), notUsed('hl')
344
345 replace restart {
346         ld      iy,#%1
347         ld      %2 (%3), %4
348 } by {
349         ; peephole 0zf used hl instead of iy.
350         ld      hl,#%1 + %2
351         ld      (hl), %4
352 } if notUsed('iy'), notUsed('hl')
353
354 replace restart {
355         ld      e,l
356         ld      d,h
357         ld      %1,(de)
358 } by {
359         ; peephole 0zg loaded %1 from (hl) directly instead of going through (de).
360         ld      %1,(hl)
361 } if notUsed('de')
362
363 replace restart {
364         ld      c,l
365         ld      b,h
366         ld      %1,(bc)
367 } by {
368         ; peephole 0zh loaded %1 from (hl) directly instead of going through (bc).
369         ld      %1,(hl)
370 } if notUsed('bc')
371
372 replace restart {
373         ld      c,l
374         ld      b,h
375         inc     bc
376 } by {
377         ; peephole 0zi incremented in hl instead of bc.
378         inc     hl
379         ld      c,l
380         ld      b,h
381 } if notUsed('hl')
382
383 replace restart {
384         ld      a,%1 (%2)
385         bit     %3,a
386 } by {
387         ; peephole 0zj tested bit of %1 (%2) directly instead of going through a.
388         bit     %3,%1 (%2)
389 } if notUsed('a')
390
391 replace restart {
392         ld      bc, #%1 + %2
393         ld      l,c
394         ld      h,b
395 } by {
396         ; peephole 0zk stored constant #%1 + %2 into hl directly instead of going through bc.
397         ld      hl, #%1 + %2
398 } if notUsed('bc')
399
400 replace restart {
401         jp      NC,%1
402         jp      %2
403 %1:
404 } by {
405         jp      C,%2
406         ; peephole 3 removed jp by using inverse jump logic
407 %1:
408 } if labelRefCountChange(%1 -1)
409
410 replace restart {
411         jp      C,%1
412         jp      %2
413 %1:
414 } by {
415         jp      NC,%2
416         ; peephole 4 removed jp by using inverse jump logic
417 %1:
418 } if labelRefCountChange(%1 -1)
419
420 replace restart {
421         jp      NZ,%1
422         jp      %2
423 %1:
424 } by {
425         jp      Z,%2
426         ; peephole 5 removed jp by using inverse jump logic
427 %1:
428 } if labelRefCountChange(%1 -1)
429
430 replace restart {
431         jp      Z,%1
432         jp      %2
433 %1:
434 } by {
435         jp      NZ,%2
436         ; peephole 6 removed jp by using inverse jump logic
437 %1:
438 } if labelRefCountChange(%1 -1)
439
440 replace restart {
441         jp      %5
442 } by {
443         jp      %6
444         ; peephole 7 redirected jump-to-jump at %5 by jump to %6
445 } if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
446
447 replace restart {
448         jp      %1,%5
449 } by {
450         jp      %1,%6
451         ; peephole 8 redirected jump-to-jump at %5 by jump to %6
452 } if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
453
454 replace restart {
455         xor     a,a
456         ld      a,#0x00
457 } by {
458         xor     a,a
459         ; peephole 10 removed redundant load of 0 into a.
460 }
461
462 replace {
463         ld      e,#0x%1
464         ld      d,#0x%2
465 } by {
466         ld      de,#0x%2%1
467         ; peephole 11 combined constant loads into register pair.
468 }
469
470 replace {
471         ld      l,#0x%1
472         ld      h,#0x%2
473 } by {
474         ld      hl,#0x%2%1
475         ; peephole 12 combined constant loads into register pair.
476 }
477
478 replace {
479         ld      c,#0x%1
480         ld      b,#0x%2
481 } by {
482         ld      bc,#0x%2%1
483         ; peephole 13 combined constant loads into register pair.
484 }
485
486 replace restart {
487         ld      %1,a
488         ld      a,%1
489 } by {
490         ld      %1,a
491         ; peephole 14 removed redundant load from %1 into a.
492 } if notVolatile(%1)
493 // This gives many false negatives and without the test no problems are encountered in the regression tests
494 // Maybe we can try this after 2.7.0 release
495
496 replace restart {
497         ld      a,%1
498         ld      %1,a
499 } by {
500         ld      a,%1
501         ; peephole 15 removed redundant load from a into %1.
502 } if notVolatile(%1)
503 // This gives many false negatives and without the test no problems are encountered in the regression tests
504 // Maybe we can try this after 2.7.0 release
505
506 replace restart {
507         ld      %1,a
508         ld      a,%2
509         or      a,%1
510 } by {
511         ld      %1,a
512         or      a,%2
513         ; peephole 17 removed load by reordering or arguments.
514 } if notVolatile(%1)
515
516 replace restart {
517         ld      %1,a
518         xor     a,a
519         or      a,%1
520 } by {
521         ld      %1,a
522         or      a,a
523         ; peephole 18 used value still in a instead of loading it from %1.
524 }
525
526 replace restart {
527         or      a,%1
528         or      a,a
529 } by {
530         or      a,%1
531         ; peephole 19 removed redundant or after or.
532 }
533
534 replace restart {
535         or      a,%1 (%2)
536         or      a,a
537 } by {
538         or      a,%1 (%2)
539         ; peephole 19a removed redundant or after or.
540 }
541
542 replace restart {
543         and     a,%1
544         or      a,a
545 } by {
546         and     a,%1
547         ; peephole 20 removed redundant or after and.
548 }
549
550 replace restart {
551         and     a,%1 (%2)
552         or      a,a
553 } by {
554         and     a,%1 (%2)
555         ; peephole 20a removed redundant or after and.
556 }
557
558 replace restart {
559         xor     a,%1
560         or      a,a
561 } by {
562         xor     a,%1
563         ; peephole 21 removed redundant or after xor.
564 }
565
566 replace restart {
567         xor     a,%1 (%2)
568         or      a,a
569 } by {
570         xor     a,%1 (%2)
571         ; peephole 21a removed redundant or after xor.
572 }
573
574 replace {
575         ld      %1,%2
576         ld      a,%2
577 } by {
578         ld      a,%2
579         ld      %1,a
580         ; peephole 23 load value in a first and use it next
581 } if notVolatile(%1 %2)
582
583 replace restart {
584         ld      %1,%2
585         ld      %3,%4
586         ld      %2,%1
587         ld      %4,%3
588 } by {
589         ld      %1,%2
590         ld      %3,%4
591         ; peephole 24 removed redundant load from %3%1 into %4%2
592 } if notVolatile(%1 %2 %3 %4)
593
594 replace restart {
595         ld      a,c
596         push    af
597         inc     sp
598         ld      a,#%2
599         push    af
600         inc     sp
601         call    %3
602 } by {
603         ld      b,c
604         ld      c,#%2
605         push    bc
606         ; peephole 31 moved and pushed arguments c and #%2 through bc instead of pushing them individually.
607         call    %3
608 }
609
610 replace restart {
611         ld      a,e
612         push    af
613         inc     sp
614         ld      a,#%2
615         push    af
616         inc     sp
617         call    %3
618 } by {
619         ld      d,e
620         ld      e,#%2
621         push    de
622         ; peephole 32 moved and pushed arguments e and #%2 through de instead of pushing them individually.
623         call    %3
624 }
625
626 replace restart {
627         ld      a,%1
628         sub     a,%2
629         jp      %3,%4
630         ld      a,%1
631 } by {
632         ld      a,%1
633         cp      a,%2
634         jp      %3,%4
635         ; peephole 33 removed load by replacing sub with cp
636         assert  a=%1
637 } if notVolatile(%1)
638
639 replace restart {
640         assert  a=%1
641         sub     a,%2
642         jp      %3,%4
643         ld      a,%1
644 } by {
645         cp      a,#%2
646         jp      %3,%4
647         ; peephole 34 removed load by replacing sub with cp
648         assert  a=%1
649 }
650
651 replace restart {
652         assert  a=%1
653 } by {
654 }
655
656 replace restart {
657         sub     a,#0xFF
658         jp      Z,%1
659 } by {
660         inc     a
661         ; peephole 35 replaced sub a,#0xFF by inc a.
662         jp      Z,%1
663 }
664
665 replace restart {
666         sub     a,#0xFF
667         jp      NZ,%1
668 } by {
669         inc     a
670         ; peephole 36 replaced sub a,#0xFF by inc a.
671         jp      NZ,%1
672 }
673
674 replace restart {
675         ld      bc,#%1 + %2
676         ld      a,c
677         add     a,%3
678         ld      c,a
679         ld      a,b
680         adc     a,%4
681         ld      b,a
682 } by {
683         ld      a,#<(%1 + %2)
684         add     a,%3
685         ld      c,a
686         ld      a,#>(%1 + %2)
687         ; peephole 37 directly used (%1 + %2) in calculation instead of placing it in bc first.
688         adc     a,%4
689         ld      b,a
690 }
691
692 replace restart {
693         ld      de,#%1 + %2
694         ld      a,e
695         add     a,%3
696         ld      e,a
697         ld      a,d
698         adc     a,%4
699         ld      d,a
700 } by {
701         ld      a,#<(%1 + %2)
702         add     a,%3
703         ld      e,a
704         ld      a,#>(%1 + %2)
705         ; peephole 38 directly used (%1 + %2) in calculation instead of placing it in de first.
706         adc     a,%4
707         ld      d,a
708 }
709
710 replace restart {
711         rlca
712         ld      a,#0x00
713         rla
714 } by {
715         rlca
716         and     a,#0x01
717         ; peephole 39 replaced zero load, rla by and since rlca writes the same value to carry bit and least significant bit.
718 }
719
720 replace restart {
721         ld      %1,%2
722         push    %1
723         pop     %4
724         ld      %1,%3
725 } by {
726         ld      %4,%2
727         ; peephole 40 moved %2 directly into de instead of going through %1.
728         ld      %1,%3
729 }
730
731 replace restart {
732         add     a,#0x00
733         ld      %2,a
734         ld      a,%3
735         adc     a,%4
736 } by {
737         ; peephole 41 removed lower part of multibyte addition.
738         ld      %2,a
739         ld      a,%3
740         add     a,%4
741 }
742
743 replace restart {
744         ld      %1,a
745         ld      a,%2
746         add     a,%1
747 } by {
748         ; peephole 42 removed loads by exploiting commutativity of addition.
749         add     a,%2
750 } if notVolatile(%1), notUsed(%1), operandsNotRelated(%2 '(bc)' '(de)')
751
752 replace restart {
753         ld      %1 (ix),a
754         ld      a,#%2
755         add     a,%1 (ix)
756 } by {
757         ld      %1 (ix),a
758         ; peephole 42a removed loads by exploiting commutativity of addition.
759         add     a,#%2
760 }
761 // Don't need to check for volatile, since ix is used to access the stack.
762
763 // sdcc does not use the H flag. sla resets it, while add sets it.
764 // To ensure that the state of the H flag is not changed by this
765 // peephole uncomment the add %3, %4 at the end (since it overwrite the H flag).
766 replace restart {
767         ld      %1, a
768         sla     %1
769         ld      a, %2
770         //add   %3, %4
771 } by {
772         add     a, a
773         ; peephole 42b shifts in accumulator insted of %1
774         ld      %1, a
775         ld      a, %2
776         //add   %3, %4
777 }
778
779 replace restart {
780         ld      %1,a
781         ld      a,%2
782         add     a,%1
783 } by {
784         ld      %1, a
785         ; peephole 43 removed load by exploiting commutativity of addition.
786         add     a,%2
787 } if operandsNotRelated(%2 '(bc)' '(de)')
788
789 replace restart {
790         ld      c,l
791         ld      b,h
792         ld      hl,#%1
793         add     hl,bc
794 } by {
795         ; peephole 43a removed loads by exploiting commutativity of addition.
796         ld      bc,#%1
797         add     hl,bc
798 } if notUsed('bc')
799
800 replace restart {
801         ld      hl,#%1
802         add     hl,%2
803         ld      bc,#%4
804         add     hl,bc
805 } by {
806         ; peephole 43b removed loads by exploiting commutativity of addition.
807         ld      hl,#%1 + %4
808         add     hl,%2
809 } if notUsed('bc')
810
811 replace restart {
812         ld      c,e
813         ld      b,d
814         ld      hl,#%1
815         add     hl,bc
816 } by {
817         ; peephole 43c removed loads by exploiting commutativity of addition.
818         ld      hl,#%1
819         add     hl,de
820 } if notUsed('bc')
821
822 replace restart {
823         or      a,%1
824         jp      NZ,%2
825         xor     a,a
826         or      a,%3
827 } by {
828         or      a,%1
829         jp      NZ,%2
830         ; peephole 44 removed redundant zeroing of a (which has just been tested to be #0x00).
831         or      a,%3
832 }
833
834 replace restart {
835         or      a,%1
836         jp      NZ,%2
837         ld      %3,#0x00
838 } by {
839         or      a,%1
840         jp      NZ,%2
841         ld      %3,a
842         ; peephole 45 replaced constant #0x00 by a (which has just been tested to be #0x00).
843 }
844
845 replace restart {
846         and     a,%1
847         jp      NZ,%2
848         ld      %3,#0x00
849 } by {
850         and     a,%1
851         jp      NZ,%2
852         ld      %3,a
853         ; peephole 46 replaced constant #0x00 by a (which has just been tested to be #0x00).
854 }
855
856 replace restart {
857         sub     a,%1
858         jp      NZ,%2
859         ld      %3,#0x00
860 } by {
861         sub     a,%1
862         jp      NZ,%2
863         ld      %3,a
864         ; peephole 47 replaced constant #0x00 by a (which has just been tested to be #0x00).
865 }
866
867 replace restart {
868         dec     a
869         jp      NZ,%1
870         ld      %2,#0x00
871 } by {
872         dec     a
873         jp      NZ,%1
874         ld      %2,a
875         ; peephole 48 replaced constant #0x00 by a (which has just been tested to be #0x00).
876 }
877
878 //replace restart {
879 //      or      a,%1
880 //      jp      NZ,%2
881 //      ld      a,%3
882 //      or      a,a
883 //} by {
884 //      or      a,%1
885 //      jp      NZ,%2
886 //      or      a,%3
887 //      ; peephole 49 shortened or using a (which has just been tested to be #0x00).
888 //} if operandsNotSame3(%3 '(bc)' '(de)')
889
890 //replace restart {
891 //      and     a,%1
892 //      jp      NZ,%2
893 //      ld      a,%3
894 //      or      a,a
895 //} by {
896 //      and     a,%1
897 //      jp      NZ,%2
898 //      or      a,%3
899 //      ; peephole 50 shortened or using a (which has just been tested to be #0x00).
900 //} if operandsNotSame3(%3 '(bc)' '(de)')
901
902 replace restart {
903         sub     a,%1
904         jp      NZ,%2
905         ld      a,%3
906         or      a,a
907 } by {
908         sub     a,%1
909         jp      NZ,%2
910         or      a,%3
911         ; peephole 51 shortened or using a (which has just been tested to be #0x00).
912 }
913 //if operandsNotSame3(%3 '(bc)' '(de)')
914
915 replace restart {
916         dec     a
917         jp      NZ,%1
918         ld      a,%2
919         or      a,a
920 } by {
921         dec     a
922         jp      NZ,%1
923         or      a,%2
924         ; peephole 52 shortened or using a (which has just been tested to be #0x00).
925 }
926 //if operandsNotSame3(%2 '(bc)' '(de)')
927
928 replace restart {
929         or      a,%1
930         jp      NZ,%2
931         push    %3
932         ld      %4,#0x00
933 } by {
934         or      a,%1
935         jp      NZ,%2
936         push    %3
937         ld      %4,a
938         ; peephole 53 replaced constant #0x00 by a (which has just been tested to be #0x00).
939 }
940
941 replace restart {
942         and     a,%1
943         jp      NZ,%2
944         push    %3
945         ld      %4,#0x00
946 } by {
947         sub     a,%1
948         jp      NZ,%2
949         push    %3
950         ld      %4,a
951         ; peephole 54 replaced constant #0x00 by a (which has just been tested to be #0x00).
952 }
953
954 replace restart {
955         sub     a,%1
956         jp      NZ,%2
957         push    %3
958         ld      %4,#0x00
959 } by {
960         sub     a,%1
961         jp      NZ,%2
962         push    %3
963         ld      %4,a
964         ; peephole 55 replaced constant #0x00 by a (which has just been tested to be #0x00).
965 }
966
967 replace restart {
968         dec     a
969         jp      NZ,%1
970         push    %2
971         ld      %3,#0x00
972 } by {
973         dec     a
974         jp      NZ,%1
975         push    %2
976         ld      %3,a
977         ; peephole 56 replaced constant #0x00 by a (which has just been tested to be #0x00).
978 }
979
980 replace restart {
981         ld      de,#%1 + %2
982         inc     de
983 } by {
984         ld      de,#%1 + %2+1
985         ; peephole 59 moved increment of de to constant.
986 }
987
988 replace restart {
989         ld      bc,#%1 + %2
990         inc     bc
991 } by {
992         ld      bc,#%1 + %2+1
993         ; peephole 62 moved increment of bc to constant.
994 }
995
996 replace restart {
997         ld      bc,#%1
998         ld      a,c
999         add     a,#0x%2
1000         ld      c,a
1001         ld      a,b
1002         adc     a,#0x%3
1003         ld      b,a
1004 } by {
1005         ld      bc,#%1 + 0x%3%2
1006         ; peephole 63 moved addition of constant 0x%3%2 to bc to constant.
1007 }
1008
1009 replace restart {
1010         call    %1
1011         ret
1012 } by {
1013         jp      %1
1014         ; peephole 65 replaced call at end of function by jump.
1015 }
1016
1017 // Callee saves ix.
1018 replace restart {
1019         call    %1
1020         pop     ix
1021         ret
1022 } by {
1023         pop     ix
1024         jp      %1
1025         ; peephole 66 replaced call at end of function by jump moving call beyond pop ix.
1026 }
1027
1028 replace restart {
1029         ld      %1,a
1030         ld      %2,%1
1031         ld      %3,%1
1032 } by {
1033         ; peephole 67 loaded %2, %3 from a instead of %1.
1034         ld      %1,a
1035         ld      %2,a
1036         ld      %3,a
1037 } if notVolatile(%1)
1038
1039 replace restart {
1040         ld      %1,a
1041         ld      %2,a
1042         ld      %3,%1
1043 } by {
1044         ld      %1,a
1045         ld      %2,a
1046         ; peephole 68 loaded %3 from a instead of %1.
1047         ld      %3,a
1048 } if notVolatile(%1)
1049
1050 replace restart {
1051         ld      %1,l
1052         xor     a,a
1053         or      a,%1
1054 } by {  
1055         ld      %1,l
1056         xor     a,a
1057         ; peephole 69 used l in or instead of %1.
1058         or      a,l
1059 } if notVolatile(%1)
1060
1061 replace restart {
1062         ld      %1,#%2
1063         ld      %3,%4
1064         ld      %1,#%2
1065 } by {
1066         ld      %1,#%2
1067         ld      %3,%4
1068         ; peephole 70 removed load of #%2 into %1 since it's still there.
1069 } if notVolatile(%1), operandsNotRelated(%3 %1)
1070
1071 replace restart {
1072         ld      hl,#%1
1073         ld      de,#%1
1074 } by {
1075         ; peephole 70a used #%1 from hl for load into de.
1076         ld      hl,#%1
1077         ld      e,l
1078         ld      d,h
1079 }
1080
1081 replace restart {
1082         ld      hl,#%1
1083         push    hl
1084         ld      l,e
1085         ld      h,d
1086         jp      (hl)
1087 %1:
1088 } by {
1089         ; peephole 71 used ex to get de into hl.
1090         ex      de,hl
1091         ld      de,#%1
1092         push    de
1093         jp      (hl)
1094 %1:
1095 }
1096 // Lets' hope this is never applied to a jump table. It's fine for calls.
1097
1098 // Should be after 0z.
1099 replace restart {
1100         ld      %1 (ix),l
1101         ld      %2 (ix),h
1102         ld      %3,%1 (ix)
1103         ld      %4,%2 (ix)
1104 } by {  
1105         ld      %1 (ix),l
1106         ld      %2 (ix),h
1107         ; peephole 72 used hl instead of %2 (ix), %1 (ix) to load %4%3.
1108         ld      %3,l
1109         ld      %4,h
1110 } if operandsNotRelated('h' %3)
1111 // Don't check for volatile since ix points to the stack.
1112
1113 // These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed().
1114 replace restart {
1115         ld      d,h
1116         ld      e,l
1117 } by {
1118         ; peephole 73 used ex to load hl into de.
1119         ex      de,hl
1120 } if notUsed('hl')
1121
1122 replace restart {
1123         ld      e,l
1124         ld      d,h
1125 } by {
1126         ; peephole 74 used ex to load hl into de.
1127         ex      de,hl
1128 } if notUsed('hl')
1129
1130 replace restart {
1131         ld      l,e
1132         ld      h,d
1133 } by {
1134         ; peephole 75 used ex to load de into hl.
1135         ex      de,hl
1136 } if notUsed('de')
1137
1138 // peeph-z80.def - Z80 peephole rules
1139 //
1140 //
1141 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2007
1142 //
1143 // This program is free software; you can redistribute it and/or modify it
1144 // under the terms of the GNU General Public License as published by the
1145 // Free Software Foundation; either version 2, or (at your option) any
1146 // later version.
1147 //
1148 // This program is distributed in the hope that it will be useful,
1149 // but WITHOUT ANY WARRANTY; without even the implied warranty of
1150 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1151 // GNU General Public License for more details.
1152 //
1153 // You should have received a copy of the GNU General Public License
1154 // along with this program; if not, write to the Free Software
1155 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1156
1157 replace restart {
1158         ld      %1,#%2
1159         ld      a,%3 (%1)
1160         ld      %4,a
1161         ld      %1,#%5
1162 } by {
1163         ld      a,(#%2 + %3)
1164         ; peephole z1 used #%2 directly instead of going through %1 using indirect addressing.
1165         ld      %4,a
1166         ld      %1,#%5
1167 }
1168
1169 replace restart {
1170         ld      %1,#%2
1171         ld      %3 (%1),a
1172 %4:
1173         ld      %1,%5
1174 } by {
1175         ld      (#%2 + %3),a
1176         ; peephole z2 directly used #%2 instead of going through %1 using indirect addressing.
1177 %4:
1178         ld      %1,%5
1179 }
1180
1181 replace restart {
1182         pop     af
1183         ld      %1,#%2
1184         ld      %3 (%1),%4
1185         ld      %1,#%5
1186 } by {
1187         ld      a,%4
1188         ld      (#%2 + %3),a
1189         ; peephole z3 used #%2 directly instead of going through %1 using indirect addressing.
1190         pop     af
1191         ld      %1,#%5
1192 } if operandsNotRelated(%3 'a')
1193
1194 replace restart {
1195         ld      bc,#%1 + %2
1196         ld      a,%3
1197         ld      (bc),a
1198 } by {
1199         ld      a,%3
1200         ld      (#%1 + %2),a
1201         ; peephole z4 directly used address #%1 + %2 instead of placing it in bc first.
1202 } if notUsed('bc')
1203
1204 replace restart {
1205         ld      bc,#%1 + %2 + %6
1206         ld      a,%3
1207         ld      (bc),a
1208 } by {
1209         ld      a,%3
1210         ld      (#%1 + %2 + %6),a
1211         ; peephole z5 directly used address #%1 + %2 + %6 instead of placing it in bc first.
1212 } if notUsed('bc')
1213
1214 replace restart {
1215         ld      c,%1
1216         ld      l,c
1217         ret
1218 } by {
1219         ld      l,%1
1220         ; peephole z8 moved %1 directly into l instead of going through c.
1221         ret
1222 }
1223
1224 replace restart {
1225         ld      b,h
1226         ld      c,l
1227         pop     af
1228         push    bc
1229         call    %1
1230 } by {
1231         ex      (sp),hl
1232         ; peephole z9 moved hl directly to the stack instead of going through bc.
1233         call    %1
1234 }
1235
1236 replace restart {
1237         ld      d,h
1238         ld      e,l
1239         pop     af
1240         push    de
1241         call    %1
1242 } by {
1243         ex      (sp),hl
1244         ; peephole z10 moved hl directly to the stack instead of going through de.
1245         call    %1
1246 }
1247
1248 replace restart {
1249         jp      %5
1250 } by {
1251         ret
1252         ; peephole z11 replaced jump by return.
1253 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1254
1255 replace restart {
1256         jp      %1,%5
1257 } by {
1258         ret     %1
1259         ; peephole z11a replaced jump by return.
1260 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1261
1262 // Should be one of the last ones. Opens the code to further peephole optimization.
1263 replace restart {
1264 %1:
1265 } by {
1266         ; peephole z12 removed unused label %1.
1267 } if labelRefCount(%1 0)
1268
1269 // Applying z11 or z11a followed by z12 will often leave a dead ret at the end of the function. Remove it.
1270 replace {
1271         jp      %5
1272         ret
1273 } by {
1274         jp      %5
1275         ; peephole z13 removed unused ret.
1276 }
1277
1278 // These four need two be here since the peephole optimizer continues to apply rules further down the file even for replace restart rules.
1279 replace restart {
1280         jp      NC,%1
1281         jp      %2
1282 %1:
1283 } by {
1284         jp      C,%2
1285         ; peephole 5' removed jp by using inverse jump logic
1286 %1:
1287 } if labelRefCountChange(%1 -1)
1288
1289 replace restart {
1290         jp      C,%1
1291         jp      %2
1292 %1:
1293 } by {
1294         jp      NC,%2
1295         ; peephole 5' removed jp by using inverse jump logic
1296 %1:
1297 } if labelRefCountChange(%1 -1)
1298
1299 replace restart {
1300         jp      NZ,%1
1301         jp      %2
1302 %1:
1303 } by {
1304         jp      Z,%2
1305         ; peephole 5' removed jp by using inverse jump logic
1306 %1:
1307 } if labelRefCountChange(%1 -1)
1308
1309 replace restart {
1310         jp      Z,%1
1311         jp      %2
1312 %1:
1313 } by {
1314         jp      NZ,%2
1315         ; peephole 6' removed jp by using inverse jump logic
1316 %1:
1317 } if labelRefCountChange(%1 -1)
1318
1319 // These should be the last rules, so that the peepholes above need to look at jp only.
1320 replace {
1321         jp      %5
1322 } by {
1323         jr      %5
1324         ; peephole z14 changed absolute to relative unconditional jump.
1325 } if labelInRange()
1326
1327 replace {
1328         jp      Z,%5
1329 } by {
1330         jr      Z,%5
1331         ; peephole z15 changed absolute to relative conditional jump.
1332 } if labelInRange()
1333
1334 replace {
1335         jp      NZ,%5
1336 } by {
1337         jr      NZ,%5
1338         ; peephole z16 changed absolute to relative conditional jump.
1339 } if labelInRange()
1340
1341 replace {
1342         jp      C,%5
1343 } by {
1344         jr      C,%5
1345         ; peephole z17 changed absolute to relative conditional jump.
1346 } if labelInRange()
1347
1348 replace {
1349         jp      NC,%5
1350 } by {
1351         jr      NC,%5
1352         ; peephole z18 changed absolute to relative conditional jump.
1353 } if labelInRange()