Skip to content

Commit 90c3870

Browse files
authored
Merge pull request #752 from boriel-basic/fix/O2_Optimizer_with_next
Fix/o2 optimizer with next
2 parents 4c87690 + 4c7fbe1 commit 90c3870

File tree

9 files changed

+78
-5
lines changed

9 files changed

+78
-5
lines changed

src/arch/z80/optimizer/memcell.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def affects(self, reglist: list[str] | str) -> bool:
323323
reglist = [reglist]
324324

325325
reglist = helpers.single_registers(reglist)
326-
return bool([x for x in self.destroys if x in reglist])
326+
return any(x for x in self.destroys if x in reglist)
327327

328328
def needs(self, reglist: list[str] | str) -> bool:
329329
"""Returns if this instruction need any of the registers
@@ -333,7 +333,7 @@ def needs(self, reglist: list[str] | str) -> bool:
333333
reglist = [reglist]
334334

335335
reglist = helpers.single_registers(reglist)
336-
return bool([x for x in self.requires if x in reglist])
336+
return any(x for x in self.requires if x in reglist)
337337

338338
@property
339339
def used_labels(self) -> list[str]:

src/arch/z80/peephole/evaluator.py

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class FN(str, Enum):
4444
CTEST = "CTEST"
4545
NEEDS = "NEEDS"
4646
FLAGVAL = "FLAGVAL"
47+
OP1 = "OP1"
48+
OP2 = "OP2"
4749

4850

4951
# Reg expr patterns
@@ -74,6 +76,8 @@ class FN(str, Enum):
7476
FN.CTEST: lambda x: memcell.MemCell(x, 1).condition_flag, # condition test, if any. E.g. retz returns 'z'
7577
FN.NEEDS: lambda x: memcell.MemCell(x[0], 1).needs(x[1]),
7678
FN.FLAGVAL: lambda x: helpers.new_tmp_val(),
79+
FN.OP1: lambda x: (x.strip().replace(",", " ", 1).split() + [""])[1],
80+
FN.OP2: lambda x: (x.strip().replace(",", " ", 1).split() + ["", ""])[2],
7781
}
7882

7983
# Binary operators

src/arch/z80/peephole/opts/028_o2_pop_up.opt

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ REPLACE {{
1818
}}
1919

2020
IF {{
21-
!(INSTR($2) IN (jp, jr, ret, call, djnz, rst)) && !NEEDS($2, (sp, $1)) && !IS_LABEL($2)
21+
!(INSTR($2) IN (jp, jr, ret, call, djnz, rst)) && !NEEDS($2, (sp, $1)) && !IS_LABEL($2) &&
22+
OP1($2) <> "sp" && OP2($2) <> "sp"
2223
}}
2324

2425
WITH {{

src/arch/z80/peephole/opts/028_o3_pop_up.opt

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ REPLACE {{
1818

1919
IF {{
2020
!(INSTR($2) IN (jp, jr, ret, call, djnz, rst)) && !NEEDS($2, (sp, $1)) && !IS_LABEL($2)
21+
&& OP1($2) <> "sp"
2122
}}
2223

2324
WITH {{

tests/arch/zx48k/optimizer/test_optimizer.py

+23
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,26 @@ def test_unrequired_or_a(self):
4141
with mock_options_level(4):
4242
optimized_code = optimizer.Optimizer().optimize(code)
4343
assert optimized_code.split("\n")[:2] == ["call .core.__LTI8", "ld bc, 0"]
44+
45+
def test_ld_sp_requires_sp(self):
46+
code_src = """
47+
ld sp, hl
48+
pop iy
49+
"""
50+
code = [x.strip() for x in code_src.split("\n") if x.strip()]
51+
52+
with mock_options_level(4):
53+
optimized_code = optimizer.Optimizer().optimize(code)
54+
assert optimized_code.split("\n")[:2] == ["ld sp, hl", "pop iy"]
55+
56+
def test_hd_sp_requires_sp(self):
57+
code_src = """
58+
add hl, sp
59+
pop iy
60+
jp (hl)
61+
"""
62+
code = [x.strip() for x in code_src.split("\n") if x.strip()]
63+
64+
with mock_options_level(3):
65+
optimized_code = optimizer.Optimizer().optimize(code)
66+
assert optimized_code.split("\n") == ["add hl, sp", "pop iy", "jp (hl)"]

tests/functional/test.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import sys
1313
import tempfile
1414
from collections.abc import Callable, Iterable
15+
from typing import Final
1516

1617
reOPT = re.compile(r"^opt([0-9]+)_") # To detect -On tests
1718
reBIN = re.compile(r"^(?:.*/)?(tzx|tap)_.*") # To detect tzx / tap test
@@ -39,6 +40,8 @@
3940
import src.api.utils # noqa
4041
from src import zxbasm, zxbc, zxbpp # noqa
4142

43+
DEFAULT_TIMEOUT: Final[int] = 3 # Default test timeout in seconds
44+
4245
# global FLAGS
4346
CLOSE_STDERR = False # Whether to show compiler error or not (usually not when doing tests)
4447
PRINT_DIFF = False # Will show diff on test failure
@@ -51,7 +54,7 @@
5154
STDERR: str = ""
5255
INLINE: bool = True # Set to false to use system Shell
5356
RAISE_EXCEPTIONS = False # True if we want the testing to abort on compiler crashes
54-
TIMEOUT = 3 # Max number of seconds a test should last
57+
TIMEOUT = DEFAULT_TIMEOUT # Max number of seconds a test should last
5558

5659
_timeout = lambda: TIMEOUT
5760

@@ -604,6 +607,7 @@ def main(argv=None):
604607
global TIMEOUT
605608

606609
COUNTER = FAILED = EXIT_CODE = 0
610+
TIMEOUT = DEFAULT_TIMEOUT
607611

608612
parser = argparse.ArgumentParser(description="Test compiler output against source code samples")
609613
parser.add_argument("-d", "--show-diff", action="store_true", help="Shows output difference on failure")
@@ -626,6 +630,12 @@ def main(argv=None):
626630
action="store_true",
627631
help="If an exception is raised (i.e." "the compiler crashes) the testing will " "stop with such exception",
628632
)
633+
parser.add_argument(
634+
"--timeout",
635+
type=int,
636+
default=TIMEOUT,
637+
help=f"Sets test timeout in seconds. Default is {TIMEOUT}. Set 0 to disable.",
638+
)
629639
args = parser.parse_args(argv)
630640

631641
STDERR = args.stderr
@@ -643,6 +653,7 @@ def main(argv=None):
643653
PRINT_DIFF = args.show_diff
644654
VIM_DIFF = args.show_visual_diff
645655
UPDATE = args.force_update
656+
TIMEOUT = args.timeout
646657

647658
if VIM_DIFF:
648659
TIMEOUT = 0 # disable timeout for Vim-dif
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
org 32768
2+
.core.__START_PROGRAM:
3+
di
4+
push iy
5+
ld iy, 0x5C3A ; ZX Spectrum ROM variables address
6+
ld hl, 0
7+
add hl, sp
8+
ld (.core.__CALL_BACK__), hl
9+
ei
10+
jp .core.__MAIN_PROGRAM__
11+
.core.__CALL_BACK__:
12+
DEFW 0
13+
.core.ZXBASIC_USER_DATA:
14+
; Defines USER DATA Length in bytes
15+
.core.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_END - .core.ZXBASIC_USER_DATA
16+
.core.__LABEL__.ZXBASIC_USER_DATA_LEN EQU .core.ZXBASIC_USER_DATA_LEN
17+
.core.__LABEL__.ZXBASIC_USER_DATA EQU .core.ZXBASIC_USER_DATA
18+
.core.ZXBASIC_USER_DATA_END:
19+
.core.__MAIN_PROGRAM__:
20+
ld hl, 0
21+
ld b, h
22+
ld c, l
23+
.core.__END_PROGRAM:
24+
di
25+
ld hl, (.core.__CALL_BACK__)
26+
ld sp, hl
27+
pop iy
28+
ei
29+
ret
30+
;; --- end of user code ---
31+
END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
REM Test empty program for prologue and epilogue
2+
REM for ZX Next using O2 optimizer

tests/functional/zxnext/opt4_mul8.asm

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ _y:
3333
push hl
3434
call _printTest
3535
.core.__END_PROGRAM:
36-
pop iy
3736
di
3837
ld hl, (.core.__CALL_BACK__)
3938
ld sp, hl
39+
pop iy
4040
ei
4141
ret
4242
_printTest:

0 commit comments

Comments
 (0)