struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / src / mos6502 / peeph.def
blob20a017f81ec1552d2ee2959f4c408e2127c67752
1 ////////////////////////////////////////////////////////
2 // Rules for common codegen patterns
3 ////////////////////////////////////////////////////////
5 replace restart {
6 sta %1
7 stx %2
8 lda %1
9 sta %3
10 lda %2
11 sta %4
12 } by {
13 sta %1
14 stx %2
15 ; Peephole Function_Entry_1 - eliminated unnecessary lda %1
16 sta %3
17 ; Peephole Function_Entry_1 - eliminated unnecessary lda %2
18 stx %4
19 } if notVolatile(%1), notVolatile(%2)
21 replace restart {
22 sta %1
23 stx %2
24 lda %2
25 sta %4
26 lda %1
27 sta %3
28 } by {
29 sta %1
30 stx %2
31 ; Peephole Function_Entry_1a - eliminated unnecessary lda %1
32 sta %3
33 ; Peephole Function_Entry_1a - eliminated unnecessary lda %2
34 stx %4
35 } if notVolatile(%1), notVolatile(%2)
37 replace restart {
38 sta %1
39 stx %2
40 lda %1
41 ldx %2
42 } by {
43 sta %1
44 stx %2
45 ; Peephole Function_Entry_2 - eliminated redundant lda %1/ldx %2
46 } if notVolatile(%1), notVolatile(%2)
48 replace restart {
49 sta %1
50 stx %2
51 ldx %2
52 lda %1
53 } by {
54 sta %1
55 stx %2
56 ; Peephole Function_Entry_2a - eliminated redundant lda %1/ldx %2
57 } if notVolatile(%1), notVolatile(%2)
59 replace restart {
60 ldx %1
61 ldy %2
62 clc
63 txa
64 adc %3
65 sta %4
66 tya
67 adc %5
68 sta %6
69 } by {
70 ; Peephole genpointer YX - eliminated ldx/ldy
71 lda %1
72 ; Peephole genpointer YX - replaced txa with lda
73 clc
74 adc %3
75 sta %4
76 lda %2
77 ; Peephole genpointer YX - replaced tya with lda
78 adc %5
79 sta %6
82 // TODO: Enable when notUsed() gets implemented!
83 //replace restart {
84 // lda %1
85 // ldx %2
86 // clc
87 // adc %3
88 // sta %4
89 // txa
90 // adc %5
91 // sta %6
92 //} by {
93 // lda %1
94 // ; Peephole genpointer XA - eliminated ldx
95 // clc
96 // adc %3
97 // sta %4
98 // lda %2
99 // ; Peephole genpointer XA - replaced txa with lda
100 // adc %5
101 // sta %6
102 //} if notUsed('x')
105 ////////////////////////////////////////////////////////
106 // Remove unnecessary loads
107 ////////////////////////////////////////////////////////
109 replace restart {
110 sta %1
111 lda %1
112 } by {
113 sta %1
114 ; Peephole load 1 - removed redundant lda
115 } if notVolatile(%1), notUsed('n' 'z')
117 // ora is cheaper than lda (except for lda from immediate, but that can't happen for the two rules below)
118 replace restart {
119 sta %1
120 lda %1
121 } by {
122 sta %1
123 ora #0x00
124 ; Peephole load 1a - replaced redundant lda by ora
125 } if notVolatile(%1)
127 replace restart {
128 sta %1, %2
129 lda %1, %2
130 } by {
131 sta %1, %2
132 ; Peephole load 2 - removed redundant lda
133 } if notVolatile(%1), notUsed('n' 'z')
135 replace restart {
136 sta %1, %2
137 lda %1, %2
138 } by {
139 sta %1, %2
140 ora #0x00
141 ; Peephole load 2a - replaced redundant lda by ora
142 } if notVolatile(%1)
144 replace restart {
145 stx %1
146 ldx %1
147 } by {
148 stx %1
149 ; Peephole load 3 - eliminated redundant ldx
150 } if notVolatile(%1), notUsed('n' 'z')
152 replace restart {
153 sty %1
154 ldy %1
155 } by {
156 sty %1
157 ; Peephole load 4 - eliminated redundant ldy
158 } if notVolatile(%1), notUsed('n' 'z')
160 ////////////////////////////////////////////////////////
161 // Remove dead loads
162 ////////////////////////////////////////////////////////
164 replace restart {
165 %1 %2, %4
166 %1 %3
167 } by {
168 ; Peephole load 5 - eliminated dead %1 %2
169 %1 %3
170 } if same(%1 'lda' 'ldx' 'ldy'), notVolatile(%2)
173 replace restart {
174 %1 %2
175 %1 %3, %4
176 } by {
177 ; Peephole load 6 - eliminated dead %1 %2
178 %1 %3, %4
179 } if same(%1 'lda' 'ldx' 'ldy'), notVolatile(%2)
181 replace restart {
182 %1 %2, %4
183 %1 %3, %5
184 } by {
185 ; Peephole load 7 - eliminated dead %1 %2
186 %1 %3, %5
187 } if same(%1 'lda' 'ldx' 'ldy'), notVolatile(%2)
190 replace restart {
191 %1 %2
192 %1 %3
193 } by {
194 ; Peephole load 8 - eliminated dead %1 %2
195 %1 %3
196 } if same(%1 'lda' 'ldx' 'ldy'), notVolatile(%2)
198 replace restart {
199 ldx %1
201 } by {
202 ; Peephole load 9 - removed dead ldx followed by %2
204 } if same(%2 'tax' 'tsx'), notVolatile(%1)
206 replace restart {
207 ldy %1
209 } by {
210 ; Peephole load 10 - removed dead ldy followed by tay
212 } if notVolatile(%1)
214 replace restart {
215 lda %1
217 } by {
218 ; Peephole load 11 - removed dead lda
220 } if same(%2 'txa' 'tya' 'pla'), notVolatile(%1)
222 replace restart {
223 lda %4
224 %1 %2
225 lda %3
226 } by {
227 ; Peephole load 12 - removed dead lda not followed by store or branch
228 %1 %2
229 lda %3
230 } if notSame(%1 'sta' 'adc' 'sbc' 'cmp' 'bne' 'beq' 'bpl' 'bmi' 'bcc' 'bcs' 'jsr' 'jmp'), notSame(%2 'a'), notVolatile(%4)
232 replace restart {
233 ldx %4
234 %1 %2
235 ldx %3
236 } by {
237 ; Peephole load 13 - removed dead ldx not followed by store or branch
238 %1 %2
239 ldx %3
240 } if notSame(%1 'stx' 'cpx' 'bne' 'beq' 'bpl' 'bmi' 'jsr' 'jmp'), notVolatile(%4)
242 replace restart {
243 ldy %4
244 %1 %2
245 ldy %3
246 } by {
247 ; Peephole load 14 - removed dead ldy not followed by store or branch
248 %1 %2
249 ldy %3
250 } if notSame(%1 'sty' 'cpy' 'bne' 'beq' 'bpl' 'bmi' 'jsr' 'jmp'), notVolatile(%4)
252 replace restart {
253 lda %3
255 lda %2
256 } by {
257 ; Peephole load 15 - removed dead lda
259 lda %2
260 } if notSame(%1 'pha' 'php' 'tax' 'tay'), notVolatile(%3)
262 replace restart {
263 ldx %3
265 ldx %2
266 } by {
267 ; Peephole load 16 - removed dead ldx
269 ldx %2
270 } if notSame(%1 'txa' 'txs' 'phx'), notVolatile(%3)
272 replace restart {
273 ldy %3
275 ldy %2
276 } by {
277 ; Peephole load 17 - removed dead ldy
279 ldy %2
280 } if notSame(%1 'tya' 'phy'), notVolatile(%3)
282 ////////////////////////////////////////////////////////
283 // Remove dead register operation/transfers
284 ////////////////////////////////////////////////////////
286 replace restart {
288 lda %2
289 } by {
290 ; Peephole regop 1 - removed dead %1 followed by lda
291 lda %2
292 } if same(%1 'txa' 'tya')
294 replace restart {
295 %1 %3
296 lda %2
297 } by {
298 ; Peephole regop 2 - removed dead %1 followed by lda
299 lda %2
300 } if same(%1 'and' 'eor' 'ora'), notVolatile(%3)
302 replace restart {
304 ldx %2
305 } by {
306 ; Peephole regop 3 - removed dead %1 followed by ldx
307 ldx %2
308 } if same(%1 'tax' 'tsx' 'inx' 'dex' )
310 replace restart {
313 } by {
314 ; Peephole regop 4 - removed dead %1 followed by tsx
316 } if same(%1 'tax' 'inx' 'dex' )
318 replace restart {
321 } by {
322 ; Peephole regop 5 - removed dead %1 followed by tax
324 } if same(%1 'tsx' 'inx' 'dex' )
326 replace restart {
328 ldy %2
329 } by {
330 ; Peephole regop 6 - removed dead %1 followed by ldy
331 ldy %2
332 } if same(%1 'tay' 'iny' 'dey' )
334 replace restart {
337 } by {
339 ; Peephole regop 7 - removed redundant txa
342 replace restart {
345 } by {
347 ; Peephole regop 8 - removed redundant tya preceded by tay
350 replace restart {
352 %1 %2
354 } by {
355 ; Peephole regop 9 - removed redundant tax
356 %1 %2
358 } if notSame(%1 'stx' 'cpx' 'bne' 'beq' 'bpl' 'bmi' 'jsr' 'jmp')
360 // if same(%1 'ora' 'and' 'eor' )
362 replace restart {
364 %1 %2
366 } by {
367 ; Peephole regop 10 - removed redundant tay
368 %1 %2
370 } if notSame(%1 'sty' 'cpy' 'bne' 'beq' 'bpl' 'bmi' 'jsr' 'jmp')
372 ////////////////////////////////////////////////////////
373 // Remove redundant/unnecessry stack operations
374 ////////////////////////////////////////////////////////
376 replace restart {
379 lda %1
380 } by {
381 ; Peephole stack 1 - removed dead pla/pha followed by lda
382 lda %1
385 replace restart {
389 } by {
390 ; Peephole stack 2 - removed dead pla/pha followed by txa/tya
392 } if same(%1 'txa' 'tya')
394 replace restart {
396 %1 %2
398 } by {
399 ; Peephole stack 3 - removed useless php/plp around a store
400 %1 %2
401 } if same(%1 'sta' 'stx' 'sty' )
404 replace restart {
407 } by {
408 ; Peephole stack 4 - removed dead php/plp
411 ////////////////////////////////////////////////////////
412 // Remove unnecessary ora #00
413 ////////////////////////////////////////////////////////
414 replace restart {
415 ora #0x00
416 } by {
417 ; Peephole or 1 - eliminated unnecessary ora #0x00
418 } if notUsed('n' 'z')
420 replace restart {
421 cmp #0x00
422 } by {
423 ; Peephole or 2 - eliminated unnecessary cmp #0x00
424 } if notUsed('n' 'z' 'c')
426 ////////////////////////////////////////////////////////
427 // Remove unnecessary cmp/cpx/cpy #00
428 ////////////////////////////////////////////////////////
430 replace restart {
431 lda %1
432 cmp #0x00
433 } by {
434 lda %1
435 ; Peephole cmp 1 - eliminated unnecessary cmp #0x00
436 } if notUsed('c')
438 replace restart {
439 lda %1,%2
440 cmp #0x00
441 } by {
442 lda %1,%2
443 ; Peephole cmp 2 - eliminated unnecessary cmp #0x00
444 } if notUsed('c')
446 replace restart {
448 cmp #0x00
449 } by {
451 ; Peephole cmp 3 - eliminated unnecessary cmp #0x00
452 } if same(%1 'pla' 'txa' 'tya' ), notUsed('c')
454 replace restart {
455 ldx %1
456 cpx #0x00
457 } by {
458 ldx %1
459 ; Peephole cmp 4 - eliminated unnecessary cpx #0x00
460 } if notUsed('c')
462 replace restart {
463 ldy %1
464 cpy #0x00
465 } by {
466 ldy %1
467 ; Peephole cmp 5 - eliminated unnecessary cpy #0x00
468 } if notUsed('c')
470 replace restart {
472 cpx #0x00
473 } by {
475 ; Peephole cmp 6 - eliminated unnecessary cpx #0x00
476 } if same(%1 'inx' 'dex' 'tax' ), notUsed('c')
478 replace restart {
480 cpy #0x00
481 } by {
483 ; Peephole cmp 7 - eliminated unnecessary cpy #0x00
484 } if same(%1 'iny' 'dey' 'tay' ), notUsed('c')
486 ////////////////////////////////////////////////////////
487 // Remove redundant stores
488 ////////////////////////////////////////////////////////
490 replace restart {
491 lda %2
492 sta %2
493 } by {
494 lda %2
495 ; Peephole store 1 - removed redundant sta
496 } if notVolatile(%2)
498 replace restart {
499 lda %2
501 sta %2
502 } by {
503 lda %2
505 ; Peephole store 2 - removed redundant sta
506 } if notSame(%1 'pla' 'txa' 'tya'), notVolatile(%2)
508 replace restart {
509 lda %2
510 %1 a
511 sta %2
512 } by {
513 ; Peephole store 3 - removed redundant sta
514 %1 %2
515 lda %2
516 } if same(%1 'asl' 'rol' 'ror'), notVolatile(%2)
518 replace restart {
519 ldx %2
520 stx %2
521 } by {
522 ldx %2
523 ; Peephole store 4 - removed redundant stx
524 } if notVolatile(%2)
526 replace restart {
527 ldx %2
529 stx %2
530 } by {
531 ldx %2
533 ; Peephole store 5 - removed redundant stx
534 } if notSame(%1 'tax' 'inx' 'dex'), notVolatile(%2)
536 replace restart {
537 ldy %2
538 sty %2
539 } by {
540 ldy %2
541 ; Peephole store 6 - removed redundant sty
542 } if notVolatile(%2)
544 replace restart {
545 ldy %2
547 sty %2
548 } by {
549 ldy %2
551 ; Peephole store 7 - removed redundant sty
552 } if notSame(%1 'tay' 'iny' 'dey'), notVolatile(%2)
554 ////////////////////////////////////////////////////////
555 // Replace jmp with branch
556 ////////////////////////////////////////////////////////
558 replace restart {
559 bne %1
560 jmp %5
562 } by {
563 beq %5
564 ; Peephole branch 1 - inverted bne and eliminated jmp
566 } if labelInRange(%5), labelRefCountChange(%1 -1)
568 replace restart {
569 beq %1
570 jmp %5
572 } by {
573 bne %5
574 ; Peephole branch 2 - inverted beq and eliminated jmp
576 } if labelInRange(%5), labelRefCountChange(%1 -1)
578 replace restart {
579 bcc %1
580 jmp %5
582 } by {
583 bcs %5
584 ; Peephole branch 3 - inverted bcc and eliminated jmp
586 } if labelInRange(%5), labelRefCountChange(%1 -1)
588 replace restart {
589 bcs %1
590 jmp %5
592 } by {
593 bcc %5
594 ; Peephole branch 4 - inverted bcs and eliminated jmp
596 } if labelInRange(%5), labelRefCountChange(%1 -1)
598 replace restart {
599 bpl %1
600 jmp %5
602 } by {
603 bmi %5
604 ; Peephole branch 5 - inverted bpl and eliminated jmp
606 } if labelInRange(%5), labelRefCountChange(%1 -1)
608 replace restart {
609 bmi %1
610 jmp %5
612 } by {
613 bpl %5
614 ; Peephole branch 6 - inverted bmi and eliminated jmp
616 } if labelInRange(%5), labelRefCountChange(%1 -1)
618 replace restart {
619 bvc %1
620 jmp %5
622 } by {
623 bvs %5
624 ; Peephole branch 7 - inverted bvc and eliminated jmp
626 } if labelInRange(%5), labelRefCountChange(%1 -1)
628 replace restart {
629 bvs %1
630 jmp %5
632 } by {
633 bvc %5
634 ; Peephole branch 8 - inverted bvs and eliminated jmp
636 } if labelInRange(%5), labelRefCountChange(%1 -1)
638 ////////////////////////////////////////////////////////
639 // Replace branch to jmp with branch
640 ////////////////////////////////////////////////////////
642 replace restart {
643 %1 %5
644 } by {
645 ; Peephole branch 9 - replaced branch to jmp with branch
646 %1 %6
647 } if same(%1 'bne' 'beq' 'bcc' 'bcs' 'bvc' 'bvs' 'bpl' 'bmi'), labelIsUncondJump(%5), notSame(%5 %6), labelInRange(%6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
649 replace restart {
650 jmp %5
651 } by {
652 ; Peephole branch 10 - replaced jmp to jmp with jmp
653 jmp %6
654 } if labelIsUncondJump(%5), notSame(%5 %6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
656 replace restart {
657 jmp %5
658 } by {
659 ; Peephole branch 11 - replaced jmp to rts with rts
661 } if optimizeReturn(), labelIsReturnOnly(%5), labelRefCountChange(%5 -1)
663 ////////////////////////////////////////////////////////
664 // Remove branch/jump to following label
665 ////////////////////////////////////////////////////////
667 replace restart {
668 %1 %2
670 } by {
671 ; Peephole branch 12 - eliminated branch to %2
673 } if same(%1 'bne' 'beq' 'bcc' 'bcs' 'bvc' 'bvs' 'bpl' 'bmi' 'jmp' 'bra'), labelRefCountChange(%2 -1)
675 ////////////////////////////////////////////////////////
676 // Tail call optimization
677 ////////////////////////////////////////////////////////
679 replace restart {
683 } by {
684 ; Peephole ret 1 - eliminated redundant rts
689 replace restart {
690 jsr %1
692 } by {
693 jmp %1
694 ; Peephole ret 2 - tail call optimization.
695 } if optimizeReturn()
697 ////////////////////////////////////////////////////////
698 // Unused label removal
699 ////////////////////////////////////////////////////////
701 // should be one of the last peepholes
702 replace restart {
704 } by {
705 ; Peephole label - removed redundant label %1
706 } if labelRefCount(%1 0)