diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index afffa336..f3a6bd72 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -474,7 +474,7 @@ object AlwaysGoodI80Optimizations { //27-31 for5LargeRegisters(register => { (Elidable & HasOpcode(PUSH) & HasRegisterParam(register)) ~ - (Linear & IsLocallyAlignable).*.capture(1) ~ + (IsLocallyAlignable & Not(HasOpcode(POP) & HasRegisterParam(register))).*.capture(1) ~ Where(ctx => ctx.isAlignableBlock(1)) ~ (Elidable & HasOpcode(POP) & HasRegisterParam(register) & DoesntMatterWhatItDoesWith(register)) ~~> { (code, _) => shallowerStack(code.tail.init) @@ -482,11 +482,20 @@ object AlwaysGoodI80Optimizations { }), //32 (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.AF)) ~ - (Linear & Not(Changes(ZRegister.A)) & Not(ReadsStackPointer)).*.capture(2) ~ + (Not(Changes(ZRegister.A)) & Not(ReadsStackPointer)).*.capture(2) ~ Where(ctx => ctx.isStackPreservingBlock(2)) ~ (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.AF) & DoesntMatterWhatItDoesWithFlags) ~~> {code => code.tail.init }, + //32-36 + for5LargeRegisters(register => { + (Elidable & HasOpcode(PUSH) & HasRegisterParam(register)) ~ + (IsLocallyAlignable & Not(Changes(register))).*.capture(1) ~ + Where(ctx => ctx.isAlignableBlock(1)) ~ + (Elidable & HasOpcode(POP) & HasRegisterParam(register)) ~~> { (code, _) => + shallowerStack(code.tail.init) + } + }), ) private def shallowerStack(lines: List[ZLine]): List[ZLine] = lines match { diff --git a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala index 09b4fd8b..ed49fc66 100644 --- a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala @@ -163,7 +163,7 @@ class AssemblyMatchingContext(val compilationOptions: CompilationOptions) { import millfork.assembly.z80.ZOpcode._ get[List[ZLine]](i).foreach { // JSR and BSR are allowed - case ZLine0(RET | RST | RETI | RETN, _, _) => + case ZLine0(RET | RST | RETI | RETN | BYTE, _, _) => return false case ZLine0(JP | JR, OneRegister(_), _) => return false @@ -184,7 +184,7 @@ class AssemblyMatchingContext(val compilationOptions: CompilationOptions) { import millfork.assembly.z80.ZOpcode._ var pushCount = 0 get[List[ZLine]](i).foreach { - case ZLine0(RET | RST | RETI | RETN, _, _) => + case ZLine0(RET | RST | RETI | RETN | BYTE, _, _) => return false case ZLine0(PUSH, _, _) => pushCount += 1 @@ -203,7 +203,7 @@ class AssemblyMatchingContext(val compilationOptions: CompilationOptions) { import ZRegister.{SP, HL, IMM_16} @tailrec def impl(list: List[ZLine]): Boolean = list match { - case ZLine0(PUSH | POP | CALL | RET | RETI | RETN | EX_SP | EXX | EX_AF_AF | RST | RSTV | HALT | STOP, _, _) :: _ => false + case ZLine0(PUSH | POP | CALL | RET | RETI | RETN | EX_SP | EXX | EX_AF_AF | RST | RSTV | HALT | STOP | BYTE, _, _) :: _ => false case ZLine0(LD_DESP | LD_HLSP, _, c) :: xs => if (c.isProvablyInRange(2, 127)) impl(xs) else false case ZLine0(LD_16, TwoRegisters(HL, IMM_16), c) :: ZLine0(ADD_16, TwoRegisters(HL, SP), _) :: xs => if (c.isProvablyInRange(2, 127)) impl(xs) else false case ZLine0(_, TwoRegisters(SP, _), _) :: _ => false diff --git a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala index c0a2b8e4..055c916c 100644 --- a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala +++ b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala @@ -871,4 +871,24 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers { } } + + test("Some combinations of shifting and indexing") { + EmuZ80BenchmarkRun( + """ + |volatile byte x + | + |noinline void f() { + | pointer(x/8)[0] |= 0x80>>(x&7) + |} + | + |void main() { + | byte i + | for i,0,parallelto,255 { pointer(i)[0] = 0 } + | x = $91 + | f() + |} + |""".stripMargin) { m => + m.readByte(0x91/8) should be (0x80>>(0x91 & 7)) + } + } }