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