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