struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / src / z80 / peeph-sm83.def
blobc9755f3045c778ecefdfa1f22d89b5210c1727db
1 // peeph-sm83.def - SM83 peephole rules
2 //
3 //
4 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2007
5 // (c) Sebastian 'basxto' Riedel (sdcc@basxto.de) 2020 - 2022
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option) any
10 // later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 replace{
22 ld hl, #%1
23 ld a, (hl)
24 } by {
25 ; sm83 peephole 0 used ldh instead of ld a, (hl).
26 ldh a, (#%1)
27 } if operandsLiteral(%1), immdInRange(0xff00 0xffff '|' %1 0 %2), notUsed('hl')
29 replace{
30 ld a, (#%1)
31 } by {
32 ; sm83 peephole 0b used ldh instead of ld.
33 ldh a, (#%1)
34 } if operandsLiteral(%1), immdInRange(0xff00 0xffff '|' %1 0 %2)
36 replace{
37 ld hl, #%1
38 ld (hl), a
39 } by {
40 ; sm83 peephole 1 used ldh instead of ld (hl), a.
41 ldh (#%1), a
42 } if operandsLiteral(%1), immdInRange(0xff00 0xffff '|' %1 0 %2), notUsed('hl')
44 replace{
45 ld (#%1), a
46 } by {
47 ; sm83 peephole 1b used ldh instead of ld.
48 ldh (#%1), a
49 } if operandsLiteral(%1), immdInRange(0xff00 0xffff '|' %1 0 %2)
51 replace {
52 ld a, (hl)
53 inc hl
54 } by {
55 ld a, (hl+)
56 ; sm83 peephole 2 used ldi to increment hl after load
59 replace {
60 ld %1, (hl)
61 inc hl
62 } by {
63 ld a, (hl+)
64 ld %1, a
65 ; sm83 peephole 2b used ldi to increment hl after load
66 } if notUsed('a')
68 replace {
69 ld %1, (hl)
70 dec hl
71 } by {
72 ld a, (hl-)
73 ld %1, a
74 ; sm83 peephole 3 used ldd to decrement hl after load
75 } if notUsed('a')
77 replace {
78 ld a, (hl)
79 dec hl
80 } by {
81 ld a, (hl-)
82 ; sm83 peephole 3b used ldd to decrement hl after load
85 replace {
86 ld (hl), a
87 inc hl
88 } by {
89 ld (hl+), a
90 ; sm83 peephole 4 used ldi to increment hl after load
93 replace {
94 ld (hl), %1
95 inc hl
96 } by {
97 ld a, %1
98 ld (hl+), a
99 ; sm83 peephole 4b used ldi to increment hl after load
100 } if notUsed('a')
102 replace {
103 ld (hl), a
104 dec hl
105 } by {
106 ld (hl-), a
107 ; sm83 peephole 5 used ldd to decrement hl after load
110 replace {
111 ld (hl), %1
112 dec hl
113 } by {
114 ld a, %1
115 ld (hl-), a
116 ; sm83 peephole 5b used ldd to decrement hl after load
117 } if notUsed('a')
119 replace {
120 ld (hl), a
121 inc %2
122 ld a, (%2)
123 inc hl
124 } by {
125 ld (hl+), a
126 ; sm83 peephole 7 used ldi to increment hl
127 inc %2
128 ld a, (%2)
129 } if notSame('hl' %2)
131 replace {
132 ld a, (hl)
133 ld (%2), a
134 inc %2
135 inc hl
136 } by {
137 ld a, (hl+)
138 ; sm83 peephole 8 used ldi to increment hl
139 ld (%2), a
140 inc %2
141 } if notSame('hl' %2)
143 replace {
144 dec hl
145 ld a, (hl+)
146 ld h, (hl)
147 ld l, a
148 } by {
149 ; sm83 peephole 9 reversed loading order of hl
150 ld a, (hl-)
151 ld l, (hl)
152 ld h, a
153 } if notUsed('a')
155 replace restart {
156 ldhl sp,#%1
157 ld %2, %3
158 ldhl sp,#%1
159 } by {
160 ; sm83 peephole 10a removed redundant ldhl.
161 ldhl sp,#%1
162 ld %2, %3
163 } if notSame('(hl+)' %2 %3), notSame('(hl+)' %2 %3)
165 // 10b and c are for pushing stack addresses
166 replace restart {
167 ldhl sp, #%1
168 ld %3, %4
169 ld %5, %6
170 ldhl sp, #%2
171 } by {
172 ldhl sp, #1
173 ld %3, %4
174 ld %5, %6
175 ; sm83 peephole 10b turned ldhl into dec hl
176 dec hl
177 } if operandsLiteral(%1 %2), notSame('l' %3 %5), notSame('l' %3 %5), immdInRange(0x01 0x01 '-' %1 %2 %3), operandsNotRelated('hl' %3 %4 %5 %6)
179 replace restart {
180 ldhl sp, #%1
181 ld %3, %4
182 ld %5, %6
183 ldhl sp, #%2
184 } by {
185 ldhl sp, #1
186 ld %3, %4
187 ld %5, %6
188 ; sm83 peephole 10c turned ldhl into inc hl
189 inc hl
190 } if operandsLiteral(%1 %2), notSame('l' %3 %5), notSame('l' %3 %5), immdInRange(0x01 0x01 '-' %2 %1 %3), operandsNotRelated('hl' %3 %4 %5 %6)
192 replace restart {
193 ldhl sp,#%1
194 dec hl
195 } by {
196 ; sm83 peephole 10d combined ld and dec.
197 ldhl sp,#%2
198 } if immdInRange(-128 127 '-' %1 1 %2)
200 replace restart {
201 ldhl sp,#%1
202 inc hl
203 } by {
204 ; sm83 peephole 10e combined ld and inc.
205 ldhl sp,#%2
206 } if immdInRange(-128 127 '+' %1 1 %2)
208 replace restart {
209 and a, #%1
210 swap a
211 and a, #%2
212 } by {
213 ; sm83 peephole 11 combined redundant ANDs #%2 and swapped #%1.
214 swap a
215 and a, #%7
216 } if operandsLiteral(%1 %2), immdInRange(0x00 0xff '/' %1 0x10 %3), immdInRange(0x00 0xfff '*' %1 0x10 %4), immdInRange(0x00 0xff '&' %4 0xF0 %5), immdInRange(0x00 0xff '|' %3 %5 %6), immdInRange(0x00 0xff '&' %2 %6 %x7)
218 replace restart {
219 ldh a, (%1)
220 inc a
221 ldh (%1), a
222 } by {
223 ; sm83 peephole 12 turned ldh into inc (hl).
224 ld hl, #((%1) | 0xFF00)
225 inc (hl)
226 } if notSame(%1 'c'), notUsed('a' 'hl')
228 replace restart {
229 ldh a, (%1)
230 dec a
231 ldh (%1), a
232 } by {
233 ; sm83 peephole 13 turned ldh into dec (hl).
234 ld hl, #((%1) | 0xFF00)
235 dec (hl)
236 } if notSame(%1 'c'), notUsed('a' 'hl')
238 replace restart {
239 ldh a, (%1)
240 srl a
241 ldh (%1), a
242 } by {
243 ; sm83 peephole 14 turned ldh into srl (hl).
244 ld hl, #((%1) | 0xFF00)
245 srl (hl)
246 } if notSame(%1 'c'), notUsed('a' 'hl')
248 replace restart {
251 } by {
252 ; sm83 peephole 16 removed redundant rra/rla
253 } if notUsed('cf' 'hf' 'nf' 'zf')
255 replace {
256 xor a, a
257 push af
258 inc sp
259 xor a, a
260 push af
261 inc sp
262 } by {
263 ; sm83 peephole 17a pushed double `xor a` fast
264 xor a, a
265 rrca
266 push af
267 xor a, a
270 //TODO: fails for unknown reasons
271 //replace {
272 // ld %1, #%2
273 // push %1
274 //} by {
275 // ; sm83 peephole 17b pushed #%2 faster
276 // xor a, a
277 // rra
278 // push af
279 //} if operandsLiteral(%2), immdInRange(0 0 '+' %2 0 %3), notUsed(%1 'af')
281 replace {
282 ld %1, #%2
283 push %1
284 } by {
285 ; sm83 peephole 18a pushed #%2 faster
286 sub a, a
287 push af
288 } if operandsLiteral(%2), immdInRange(0x00C0 0x00C0 '+' %2 0 %x3), notUsed(%1 'af')
291 // Those rules save 1 byte and 4 cycles each
292 replace {
293 ld %1, #%2
294 push %1
295 } by {
296 ; sm83 peephole 18b pushed #%2 faster
297 xor a, a
298 push af
299 } if operandsLiteral(%2), immdInRange(0x0080 0x0080 '+' %2 0 %x3), notUsed(%1 'af')
301 replace {
302 ld %1, #%2
303 push %1
304 } by {
305 ; sm83 peephole 18c pushed #%2 faster
306 xor a, a
308 push af
309 } if operandsLiteral(%2), immdInRange(0x0090 0x0090 '+' %2 0 %x3), notUsed(%1 'af')
311 replace {
312 ld %1, #%2
313 push %1
314 } by {
315 ; sm83 peephole 18d pushed #%2 faster
316 xor a, a
317 and a
318 push af
319 } if operandsLiteral(%2), immdInRange(0x00A0 0x00A0 '+' %2 0 %x3), notUsed(%1 'af')
321 replace {
322 ld %1, #%2
323 push %1
324 } by {
325 ; sm83 peephole 18e pushed #%2 faster
326 xor a, a
328 push af
329 } if operandsLiteral(%2), immdInRange(0x00D0 0x00D0 '+' %2 0 %x3), notUsed(%1 'af')
331 replace {
332 ld %1, #%2
333 push %1
334 } by {
335 ; sm83 peephole 18f pushed #%2 faster
336 xor a, a
337 inc a
338 push af
339 } if operandsLiteral(%2), immdInRange(0x0100 0x0100 '+' %2 0 %x3), notUsed(%1 'af')
341 replace {
342 ld %1, #%2
343 push %1
344 } by {
345 ; sm83 peephole 18g pushed #%2 faster
347 sbc a, a
348 push af
349 } if operandsLiteral(%2), immdInRange(0xFF30 0xFF30 '+' %2 0 %x3), notUsed(%1 'af')
351 replace {
352 ld %1, #%2
353 push %1
354 } by {
355 ; sm83 peephole 18h pushed #%2 faster
356 xor a, a
357 dec a
358 push af
359 } if operandsLiteral(%2), immdInRange(0xFF60 0xFF60 '+' %2 0 %x3), notUsed(%1 'af')
361 replace {
362 push af
363 inc sp
364 ld a, #%2
365 push af
366 inc sp
367 } by {
368 ; sm83 peephole 19 pushed #%2 via flags
369 cp a
370 push af
371 } if operandsLiteral(%2), immdInRange(0xC0 0xC0 '+' %2 0 %x3), notUsed('f')
373 replace restart {
374 inc hl
375 ld a, (hl-)
376 or a, (hl)
377 } by {
378 ld a, (hl+)
379 or a, (hl)
380 ; sm83 peephole 20 reversed ld and or.
381 } if notUsed('hl')
383 replace restart {
385 ld a, (hl+)
386 ld %3, a
387 ld a, (%6)
388 inc %6
389 sub a, %3
390 ld %4, a
391 jp NZ, %2
392 or a,%3
393 jp NZ, %1
395 } by {
397 ld a, (hl+)
398 ld %3, a
399 ld a, (%6)
400 inc %6
401 sub a, %3
402 jp NZ, %2
403 cp a,%3
404 jp NZ, %1
406 ; sm83 peephole 21 sped up loop body.
407 ld %4, a
408 } if canSplitReg(%6 %9 %10), operandsNotRelated(%3 %6 'hl'), operandsNotRelated(%3 %6 'hl'), notSame(%3 %4), labelRefCount(%2 1)
410 replace restart {
411 ld (hl+), a
412 ld (hl), %1
413 ld a, (hl-)
414 or a, (hl)
415 } by {
416 ld (hl+), a
417 ld (hl), %1
418 ; sm83 peephole 22 remove unnecessary load back
419 or a, %1
420 dec hl
423 replace {
424 pop %1
425 push %1
426 } by {
427 ; peephole sp1 removed not needed push
428 pop %1
429 } if notUsed('sp')
431 replace {
432 pop %1
433 pop %2
434 push %2
435 push %1
436 } by {
437 ; peephole sp2 removed not needed push
438 pop %1
439 pop %2
440 } if notUsed('sp'), notSame(%1 %2)
442 replace {
443 add sp, %1
444 } by {
445 ; peephole sp3 removed not needed add sp
446 } if notUsed('sp')
448 replace {
449 pop %1
450 } by {
451 ; peephole sp6 removed not needed pop
452 } if notUsed(%1), notUsed('sp')
454 // for 2B it wouldn't be worth it
455 replace {
456 inc sp
457 inc sp
458 inc sp
459 } by {
460 ; peephole sp7 increased SP by addition
461 add sp, #3
462 } if notUsed('f')
464 replace restart {
465 add sp, #%1
466 inc sp
467 } by {
468 ; peephole sp8a increased SP by addition
469 add sp, #%2
470 } if immdInRange(-128 127 '+' %1 1 %2), notUsed('hf' 'cf')
472 replace restart {
473 inc sp
474 add sp, #%1
475 } by {
476 ; peephole sp8b increased SP by addition
477 add sp, #%2
478 } if immdInRange(-128 127 '+' %1 1 %2)
480 replace restart {
481 add sp, #%1
482 add sp, #%2
483 } by {
484 ; peephole sp9 combined SP additions
485 add sp, #%3
486 } if immdInRange(-128 127 '+' %1 %2 %3), notUsed('hf' 'cf')
488 // only handle stack adjustment after calls to not
489 // disturb detection of uninitialized reads in emulators
490 replace {
491 call %2
492 add sp, #%1
493 } by {
494 call %2
495 ; peephole sp10a increased SP by %1 through pop
496 pop %3
497 } if immdInRange(2 2 '+' %1 0 %2), unusedReg(%3 'bc' 'de' 'hl'), notUsed('f')
499 // unusedReg does not support 'af'
500 replace {
501 call %2
502 add sp, #%1
503 } by {
504 call %2
505 ; peephole sp10b increased SP by %1 through pop
506 pop af
507 } if immdInRange(2 2 '+' %1 0 %2), notUsed('af')
509 // if f was used
510 replace {
511 call %2
512 inc sp
513 inc sp
514 } by {
515 call %2
516 ; peephole sp10c increased SP by 2 through pop
517 pop %3
518 } if unusedReg(%3 'bc' 'de' 'hl')