diff --git a/src/arch/zx48k/optimizer/basicblock.py b/src/arch/zx48k/optimizer/basicblock.py index eac5349c9..89ecf92db 100644 --- a/src/arch/zx48k/optimizer/basicblock.py +++ b/src/arch/zx48k/optimizer/basicblock.py @@ -12,6 +12,8 @@ from .common import LABELS, JUMP_LABELS from .errors import OptimizerInvalidBasicBlockError, OptimizerError from .cpustate import CPUState +from .patterns import RE_ID_OR_NUMBER + from ..peephole import evaluator from . import helpers @@ -377,6 +379,8 @@ def is_used(self, regs, i, top=None): if helpers.idx_args(regs[0][1:-1]) else [] rr = set(r16 + ix) + mem_vars = set([] if rr else RE_ID_OR_NUMBER.findall(regs[0])) + for mem in self[i:top]: # For memory accesses only mark as NOT uses if it's overwritten if mem.inst == 'ld' and mem.opers[0] == regs[0]: return False @@ -387,6 +391,9 @@ def is_used(self, regs, i, top=None): if rr and any(_ in r16 for _ in mem.destroys): # (hl) :: inc hl / (ix + n) :: inc ix return True + if mem.opers and mem_vars.intersection(RE_ID_OR_NUMBER.findall(mem.opers[-1])): + return True + return True regs = src.api.utils.flatten_list([helpers.single_registers(x) for x in regs]) # make a copy diff --git a/src/arch/zx48k/optimizer/patterns.py b/src/arch/zx48k/optimizer/patterns.py index ebb37127b..8055a3104 100644 --- a/src/arch/zx48k/optimizer/patterns.py +++ b/src/arch/zx48k/optimizer/patterns.py @@ -32,3 +32,6 @@ # matches a pragma line RE_PRAGMA = re.compile(r'^#[ \t]?pragma[ \t]opt[ \t]') + +# matches an ID or a number +RE_ID_OR_NUMBER = re.compile(r'[0-9]+|[a-zA-Z_][a-zA-Z_0-9]*') diff --git a/src/arch/zx48k/peephole/evaluator.py b/src/arch/zx48k/peephole/evaluator.py index f00778412..a3ca89b45 100644 --- a/src/arch/zx48k/peephole/evaluator.py +++ b/src/arch/zx48k/peephole/evaluator.py @@ -137,8 +137,8 @@ class Evaluator(object): || (or) + (addition or concatenation for strings) """ - UNARY = UNARY - BINARY = BINARY + UNARY = dict(UNARY) + BINARY = dict(BINARY) def __init__(self, expression, unary=None, binary=None): """ Initializes the object parsing the expression and preparing it for its (later) diff --git a/tests/arch/zx48k/optimizer/test_basicblock.py b/tests/arch/zx48k/optimizer/test_basicblock.py index 32be34c0b..6bced7ff3 100644 --- a/tests/arch/zx48k/optimizer/test_basicblock.py +++ b/tests/arch/zx48k/optimizer/test_basicblock.py @@ -3,14 +3,18 @@ import unittest from src.arch.zx48k.optimizer import basicblock from src.arch.zx48k import optimizer +from src.arch.zx48k.peephole import evaluator class TestBasicBlock(unittest.TestCase): """ Tests basic blocks implementation """ - def setUp(self): + def setUp(self) -> None: self.blk = basicblock.BasicBlock([]) + def tearDown(self) -> None: + evaluator.Evaluator.UNARY = dict(evaluator.UNARY) + def test_block_partition_jp(self): code = """ nop @@ -157,3 +161,11 @@ def test_basic_block_clean_ld_hl(self): self.blk.code = [x for x in code.split('\n') if x.strip()] self.assertEqual(1, len(self.blk)) self.assertEqual(['ld hl, (30000)'], self.blk.code) + + def test_mempos_requires(self): + code = """ + ld hl, (_k - 1) + ld (_k), a + """ + self.blk.code = [x for x in code.split('\n') if x.strip()] + self.assertTrue(self.blk.is_used(['(_k)'], 0)) diff --git a/tests/functional/opt4_due_0.asm b/tests/functional/opt4_due_0.asm new file mode 100644 index 000000000..7ea4e4285 --- /dev/null +++ b/tests/functional/opt4_due_0.asm @@ -0,0 +1,51 @@ + org 32768 +__START_PROGRAM: + di + push ix + push iy + exx + push hl + exx + ld hl, 0 + add hl, sp + ld (__CALL_BACK__), hl + ei + jp __MAIN_PROGRAM__ +ZXBASIC_USER_DATA: + ; Defines USER DATA Length in bytes +ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA + .__LABEL__.ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_LEN + .__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA +_k: + DEFB 05h +_n: + DEFB 00 +ZXBASIC_USER_DATA_END: +__MAIN_PROGRAM__: + ld a, (_k) + xor 31 + ld (_k), a + ld a, (_n) + add a, a + add a, a + add a, a + add a, a + add a, a + ld hl, (_k - 1) + or h + ld (_k), a + ld bc, 0 +__END_PROGRAM: + di + ld hl, (__CALL_BACK__) + ld sp, hl + exx + pop hl + pop iy + pop ix + exx + ei + ret +__CALL_BACK__: + DEFW 0 + END diff --git a/tests/functional/opt4_due_0.bas b/tests/functional/opt4_due_0.bas new file mode 100644 index 000000000..3b9ca53b7 --- /dev/null +++ b/tests/functional/opt4_due_0.bas @@ -0,0 +1,9 @@ + + +DIM k as UByte = 5 +DIM n as UByte + +k = k bXOR %11111 +k = (n << 5) bOR k + +