diff --git a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala index 3e05ca27..b0020f53 100644 --- a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala +++ b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala @@ -508,6 +508,13 @@ object AlwaysGoodOptimizations { (Elidable & HasOpcode(PLY)) ~~> { code => code.head :: (code.drop(2).init :+ code.head) }, + (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ + (Elidable & HasOpcode(PHA)) ~ + (Not(ConcernsStack) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).*.capture(2) ~ + Where(ctx => ctx.isExternallyLinearBlock(2))~ + (Elidable & HasOpcode(PLA)) ~~> { code => + code.head :: (code.drop(2).init :+ code.head) + }, ) val IncrementingIndexRegistersAfterTransfer = new RuleBasedAssemblyOptimization("Incrementing index registers after transfer", @@ -839,7 +846,7 @@ object AlwaysGoodOptimizations { HasOpcode(TAX) ~ (Elidable & Set(TXA, TAX)) ~~> (_.init), HasOpcode(TSX) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init), HasOpcode(TXS) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init), - HasOpcodeIn(Set(TXA, TAX)) ~ + HasOpcodeIn(Set(TXA, TAX, LAX, LXA)) ~ (Linear & Not(ChangesNAndZ) & Not(ChangesA) & Not(ChangesX)).* ~ (Elidable & HasOpcodeIn(Set(TXA, TAX))) ~~> (_.init), HasOpcodeIn(Set(TYA, TAY)) ~ @@ -1079,7 +1086,7 @@ object AlwaysGoodOptimizations { (HasOpcode(LABEL) & MatchParameter(3) & HasCallerCount(1)) ~ (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init), - HasOpcodeIn(Set(TXA, TAX)) ~ + HasOpcodeIn(Set(TXA, TAX, LAX, LXA)) ~ (Not(Set(TXA, TAX)) & Linear & Not(ChangesA) & Not(ChangesX)).* ~ (Elidable & HasOpcodeIn(Set(TXA, TAX)) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init), diff --git a/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzer.scala b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzer.scala index 50db8fbd..05d12a54 100644 --- a/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzer.scala @@ -92,9 +92,30 @@ case class CpuImportance(a: Importance = UnknownImportance, object ReverseFlowAnalyzer { - val aluAdders = Set(Opcode.ADC, Opcode.SBC, Opcode.ISC, Opcode.DCP, Opcode.ADC_W, Opcode.SBC_W) - val actuallyRead = Set(AddrMode.IndexedZ, AddrMode.IndexedSY, AddrMode.IndexedY, AddrMode.LongIndexedY, AddrMode.LongIndexedZ, AddrMode.IndexedX, AddrMode.Indirect, AddrMode.AbsoluteIndexedX) - val absoluteLike = Set(AddrMode.ZeroPage, AddrMode.Absolute, AddrMode.LongAbsolute) + private val aluAdders = Set(Opcode.ADC, Opcode.SBC, Opcode.ISC, Opcode.DCP, Opcode.ADC_W, Opcode.SBC_W) + private val actuallyRead = Set(AddrMode.IndexedZ, AddrMode.IndexedSY, AddrMode.IndexedY, AddrMode.LongIndexedY, AddrMode.LongIndexedZ, AddrMode.IndexedX, AddrMode.Indirect, AddrMode.AbsoluteIndexedX) + private val absoluteLike = Set(AddrMode.ZeroPage, AddrMode.Absolute, AddrMode.LongAbsolute) + private val importanceBeforeJsr: CpuImportance = CpuImportance( + a = Unimportant, + ah = Unimportant, + x = Unimportant, + y = Unimportant, + iz = Unimportant, + z = Unimportant, + n = Unimportant, + c = Unimportant, + v = Unimportant, + d = Important, + m = Important, + w = Important, + r0 = Unimportant, + r1 = Unimportant) + private val finalImportance: CpuImportance = CpuImportance( + a = Important, ah = Important, + x = Important, y = Important, iz = Important, + c = Important, v = Important, d = Important, z = Important, n = Important, + m = Important, w = Important, + r0 = Important, r1 = Important) //noinspection RedundantNewCaseClass def analyze(f: NormalFunction, code: List[AssemblyLine]): List[CpuImportance] = { @@ -102,16 +123,10 @@ object ReverseFlowAnalyzer { val codeArray = code.toArray var changed = true - val finalImportance = new CpuImportance( - a = Important, ah = Important, - x = Important, y = Important, iz = Important, - c = Important, v = Important, d = Important, z = Important, n = Important, - m = Important, w = Important, - r0 = Important, r1 = Important) changed = true while (changed) { changed = false - var currentImportance: CpuImportance = finalImportance + var currentImportance = finalImportance for (i <- codeArray.indices.reverse) { import millfork.assembly.mos.Opcode._ import AddrMode._ @@ -134,21 +149,7 @@ object ReverseFlowAnalyzer { case AssemblyLine(JSR | JMP, Absolute | LongAbsolute, MemoryAddressConstant(fun: FunctionInMemory), _) => // this case has to be handled first, because the generic JSR importance handler is too conservative - var result = new CpuImportance( - a = Unimportant, - ah = Unimportant, - x = Unimportant, - y = Unimportant, - iz = Unimportant, - z = Unimportant, - n = Unimportant, - c = Unimportant, - v = Unimportant, - d = Important, - m = Important, - w = Important, - r0 = Unimportant, - r1 = Unimportant) + var result = importanceBeforeJsr fun.params match { case AssemblyParamSignature(params) => params.foreach(_.variable match { @@ -180,7 +181,10 @@ object ReverseFlowAnalyzer { case AssemblyLine(AND, _, NumericConstant(0, _), _) => currentImportance = currentImportance.copy(n = Unimportant, z = Unimportant, a = Unimportant) - case AssemblyLine(opcode, addrMode, _, _) if ReverseFlowAnalyzerPerOpcode.hasDefinition(opcode) => + case AssemblyLine(opcode, Implied, _, _) if ReverseFlowAnalyzerPerImpiedOpcode.hasDefinition(opcode) => + currentImportance = ReverseFlowAnalyzerPerImpiedOpcode.get(opcode)(currentImportance) + + case AssemblyLine(opcode, addrMode, _, _) if addrMode != Implied && ReverseFlowAnalyzerPerOpcode.hasDefinition(opcode) => currentImportance = ReverseFlowAnalyzerPerOpcode.get(opcode)(currentImportance) if (addrMode == AbsoluteX || addrMode == LongAbsoluteX || addrMode == IndexedX || addrMode == ZeroPageX || addrMode == AbsoluteIndexedX) currentImportance = currentImportance.copy(x = Important) @@ -275,7 +279,7 @@ object ReverseFlowAnalyzer { if th.name == "__reg" => currentImportance = currentImportance.copy(r0 = Important, r1 = Important) case _ => () } - } else if (OpcodeClasses.ReadsM(currentLine.opcode) || OpcodeClasses.ReadsMemoryIfNotImpliedOrImmediate(currentLine.opcode)) { + } else if (OpcodeClasses.ReadsMemoryIfNotImpliedOrImmediate(currentLine.opcode)) { if (OpcodeClasses.AccessesWordInMemory(currentLine.opcode)) { currentLine.parameter match { case MemoryAddressConstant(th: Thing) @@ -294,10 +298,10 @@ object ReverseFlowAnalyzer { } } } - // importanceArray.zip(codeArray).foreach{ - // case (i, y) => if (y.isPrintable) println(f"$y%-32s $i%-32s") - // } - // println("---------------------") +// importanceArray.zip(codeArray).foreach{ +// case (i, y) => if (y.isPrintable) println(f"$y%-32s $i%-32s") +// } +// println("---------------------") importanceArray.toList } diff --git a/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerImpliedOpcode.scala b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerImpliedOpcode.scala new file mode 100644 index 00000000..58feb110 --- /dev/null +++ b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerImpliedOpcode.scala @@ -0,0 +1,182 @@ +package millfork.assembly.mos.opt + +import millfork.assembly.mos.Opcode +import millfork.assembly.mos.Opcode._ + +/** + * @author Karol Stasiak + */ +object ReverseFlowAnalyzerPerImpiedOpcode { + + private val finalImportance = CpuImportance( + a = Important, ah = Important, + x = Important, y = Important, iz = Important, + c = Important, v = Important, d = Important, z = Important, n = Important, + m = Important, w = Important) + + private def allAddingOutputsUnimportant(currentImportance: CpuImportance): Boolean = + currentImportance.a == Unimportant && + currentImportance.c == Unimportant && + currentImportance.z == Unimportant && + currentImportance.n == Unimportant && + currentImportance.v == Unimportant + + private def allLoadingAccuOutputsUnimportant(currentImportance: CpuImportance): Boolean = + currentImportance.a == Unimportant && + currentImportance.z == Unimportant && + currentImportance.n == Unimportant + + private def allCompareOutputsAreUnimportant(currentImportance: CpuImportance): Boolean = + currentImportance.z == Unimportant && + currentImportance.n == Unimportant&& + currentImportance.c == Unimportant + + private val map: Map[Opcode.Value, CpuImportance => CpuImportance] = Map( + NOP -> identity, + SEI -> identity, + CLI -> identity, + WAI -> identity, + STP -> identity, + BRK -> (_ => finalImportance), + COP -> (_ => finalImportance), + RTS -> (_ => finalImportance), + RTL -> (_ => finalImportance), + + RTI -> (_ => CpuImportance( + a = Unimportant, ah = Unimportant, + x = Unimportant, y = Unimportant, iz = Unimportant, + z = Unimportant, n = Unimportant, c = Unimportant, v = Unimportant, d = Unimportant, + m = Unimportant, w = Unimportant)), + + TAX -> (currentImportance => { + currentImportance.copy( + a = currentImportance.x ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, + x = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TAY -> (currentImportance => { + currentImportance.copy( + a = currentImportance.y ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, + y = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TXA -> (currentImportance => { + currentImportance.copy( + x = currentImportance.a ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z, + a = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TYA -> (currentImportance => { + currentImportance.copy( + y = currentImportance.a ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z, + a = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TAZ -> (currentImportance => { + currentImportance.copy( + a = currentImportance.iz ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, + iz = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TZA -> (currentImportance => { + currentImportance.copy( + iz = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z, + a = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TXY -> (currentImportance => { + currentImportance.copy( + x = currentImportance.y ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z, + y = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TYX -> (currentImportance => { + currentImportance.copy( + y = currentImportance.x ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z, + x = Unimportant, + n = Unimportant, z = Unimportant, m = Important, w = Important) + }), + TSX -> (_.copy(x = Unimportant, n = Unimportant, z = Unimportant, w = Important)), + TXS -> (_.copy(x = Important, w = Important)), + XBA -> (currentImportance => { + currentImportance.copy( + ah = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z, + a = currentImportance.ah, + n = Unimportant, z = Unimportant) + }), + TCD -> (_.copy(a = Important, ah = Important)), + TDC -> (_.copy(a = Unimportant, ah = Unimportant, n = Unimportant, z = Unimportant)), + TCS -> (_.copy(a = Important, ah = Important)), + TSC -> (_.copy(a = Unimportant, ah = Unimportant, n = Unimportant, z = Unimportant)), + + TRB -> (_.copy(a = Important, z = Unimportant, m = Important)), + TSB -> (_.copy(a = Important, z = Unimportant, m = Important)), + + HuSAX -> (currentImportance => { + currentImportance.copy(a = currentImportance.x, x = currentImportance.a, m = Important, w = Important) + }), + SAY -> (currentImportance => { + currentImportance.copy(y = currentImportance.a, a = currentImportance.y, m = Important, w = Important) + }), + SXY -> (currentImportance => { + currentImportance.copy(y = currentImportance.x, x = currentImportance.y, m = Important, w = Important) + }), + + ASL -> (_.copy(a = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)), + LSR -> (_.copy(a = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)), + ROL -> (_.copy(a = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)), + ROR -> (_.copy(a = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)), + + ASL_W -> (_.copy(a = Important, ah = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)), + LSR_W -> (_.copy(a = Important, ah = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)), + ROL_W -> (_.copy(a = Important, ah = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)), + ROR_W -> (_.copy(a = Important, ah = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)), + + DEC -> (_.copy(a = Important, n = Unimportant, z = Unimportant, m = Important)), + DEX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), + DEY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), + DEZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)), + + INC -> (_.copy(a = Important, n = Unimportant, z = Unimportant, m = Important)), + INX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), + INY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), + INZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)), + + DEC_W -> (_.copy(a = Important, ah = Important, n = Unimportant, z = Unimportant, m = Important)), + DEX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), + DEY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), + INC_W -> (_.copy(x = Important, ah = Important, n = Unimportant, z = Unimportant, m = Important)), + INX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), + INY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), + + PHP -> (_.copy(n = Important, c = Important, d = Important, z = Important, v = Important, m = Important, w = Important)), + PLP -> (_.copy(n = Unimportant, c = Unimportant, d = Unimportant, z = Unimportant, v = Unimportant, m = Unimportant, w = Unimportant)), + + PHA -> (_.copy(a = Important, m = Important)), + PLA -> (_.copy(a = Unimportant, m = Important, n = Unimportant, z = Unimportant)), + PHX -> (_.copy(x = Important, w = Important)), + PLX -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)), + PHY -> (_.copy(y = Important, w = Important)), + PLY -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)), + PHZ -> (_.copy(iz = Important, w = Important)), + PLZ -> (_.copy(iz = Unimportant, w = Important, n = Unimportant, z = Unimportant)), + + PHA_W -> (_.copy(a = Important, ah = Important, m = Important)), + PLA_W -> (_.copy(a = Unimportant, ah = Unimportant, m = Important, n = Unimportant, z = Unimportant)), + PHX_W -> (_.copy(x = Important, w = Important)), + PLX_W -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)), + PHY_W -> (_.copy(y = Important, w = Important)), + PLY_W -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)), + + CLC -> (_.copy(c = Unimportant)), + SEC -> (_.copy(c = Unimportant)), + CLD -> (_.copy(d = Unimportant)), + SED -> (_.copy(d = Unimportant)), + CLV -> (_.copy(v = Unimportant)), + + ) + + def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode) + + def get(opcode: Opcode.Value): CpuImportance => CpuImportance = map(opcode) +} diff --git a/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerOpcode.scala b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerOpcode.scala index 3928e883..f5b5c8a8 100644 --- a/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerOpcode.scala +++ b/src/main/scala/millfork/assembly/mos/opt/ReverseFlowAnalyzerPerOpcode.scala @@ -26,25 +26,20 @@ object ReverseFlowAnalyzerPerOpcode { currentImportance.z == Unimportant && currentImportance.n == Unimportant + private def allCompareOutputsAreUnimportant(currentImportance: CpuImportance): Boolean = + currentImportance.z == Unimportant && + currentImportance.n == Unimportant&& + currentImportance.c == Unimportant + private val map: Map[Opcode.Value, CpuImportance => CpuImportance] = Map( NOP -> identity, - SEI -> identity, - CLI -> identity, - + LABEL -> identity, JSR -> (_ => finalImportance), BSR -> (_ => finalImportance), BRK -> (_ => finalImportance), COP -> (_ => finalImportance), - RTS -> (_ => finalImportance), - RTL -> (_ => finalImportance), BYTE -> (_ => finalImportance), - RTI -> (_ => CpuImportance( - a = Unimportant, ah = Unimportant, - x = Unimportant, y = Unimportant, iz = Unimportant, - z = Unimportant, n = Unimportant, c = Unimportant, v = Unimportant, d = Unimportant, - m = Unimportant, w = Unimportant)), - BNE -> (_.copy(z = Important)), BEQ -> (_.copy(z = Important)), BMI -> (_.copy(n = Important)), @@ -54,71 +49,6 @@ object ReverseFlowAnalyzerPerOpcode { BCC -> (_.copy(c = Important)), BCS -> (_.copy(c = Important)), - TAX -> (currentImportance => { - currentImportance.copy( - a = currentImportance.x ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, - x = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TAY -> (currentImportance => { - currentImportance.copy( - a = currentImportance.y ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, - y = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TXA -> (currentImportance => { - currentImportance.copy( - x = currentImportance.a ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z, - a = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TYA -> (currentImportance => { - currentImportance.copy( - y = currentImportance.a ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z, - a = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TAZ -> (currentImportance => { - currentImportance.copy( - a = currentImportance.iz ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z, - iz = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TZA -> (currentImportance => { - currentImportance.copy( - iz = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z, - a = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TXY -> (currentImportance => { - currentImportance.copy( - x = currentImportance.y ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z, - y = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - TYX -> (currentImportance => { - currentImportance.copy( - y = currentImportance.x ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z, - x = Unimportant, - n = Unimportant, z = Unimportant, m = Important, w = Important) - }), - XBA -> (currentImportance => { - currentImportance.copy( - ah = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z, - a = currentImportance.ah, - n = Unimportant, z = Unimportant) - }), - - HuSAX -> (currentImportance => { - currentImportance.copy(a = currentImportance.x, x = currentImportance.a, m = Important, w = Important) - }), - SAY -> (currentImportance => { - currentImportance.copy(y = currentImportance.a, a = currentImportance.y, m = Important, w = Important) - }), - SXY -> (currentImportance => { - currentImportance.copy(y = currentImportance.x, x = currentImportance.y, m = Important, w = Important) - }), - DISCARD_XF -> (_.copy(x = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)), DISCARD_YF -> (_.copy(y = Unimportant, iz = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)), DISCARD_AF -> (_.copy(a = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)), @@ -128,6 +58,8 @@ object ReverseFlowAnalyzerPerOpcode { LDY -> (_.copy(y = Unimportant, n = Unimportant, z = Unimportant, w = Important)), LDZ -> (_.copy(iz = Unimportant, n = Unimportant, z = Unimportant)), LAX -> (_.copy(a = Unimportant, x = Unimportant, n = Unimportant, z = Unimportant)), + LXA -> (_.copy(a = Important, x = Unimportant, n = Unimportant, z = Unimportant)), + XAA -> (_.copy(a = Important, x = Important, n = Unimportant, z = Unimportant)), ORA -> (currentImportance => { val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance) @@ -150,6 +82,27 @@ object ReverseFlowAnalyzerPerOpcode { n = Unimportant, z = Unimportant, m = Important) }), + SLO -> (currentImportance => { + val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + m = Important) + }), + SRE -> (currentImportance => { + val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + m = Important) + }), + RLA -> (currentImportance => { + val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Important, + m = Important) + }), BIT -> (currentImportance => { currentImportance.copy( a = currentImportance.z, @@ -158,6 +111,33 @@ object ReverseFlowAnalyzerPerOpcode { v = Unimportant, m = Important) }), + CMP -> (currentImportance => { + val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + m = Important) + }), + DCP -> (currentImportance => { + val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant) + }), + CPX -> (currentImportance => { + val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance) + currentImportance.copy( + x = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + w = Important) + }), + CPY -> (currentImportance => { + val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance) + currentImportance.copy( + y = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + w = Important) + }), ADC -> (currentImportance => { val ignoreOutput = allAddingOutputsUnimportant(currentImportance) @@ -196,49 +176,35 @@ object ReverseFlowAnalyzerPerOpcode { STZ -> (importance => importance.copy(iz = Important, m = Important)), SAX -> (importance => importance.copy(a = Important, x = Important)), + INC -> (importance => importance.copy(n = Unimportant, z = Unimportant, m = Important)), + DEC -> (importance => importance.copy(n = Unimportant, z = Unimportant, m = Important)), + ROL -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Important, m = Important)), + ROR -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Important, m = Important)), + ASL -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Unimportant, m = Important)), + LSR -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Unimportant, m = Important)), + + + SBX -> (importance => importance.copy(a = Important, x = Important, n = Unimportant, z = Unimportant, c = Unimportant, m = Important)), + ANC -> (currentImportance => { + val ignoreOutput = allAddingOutputsUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + m = Important) + }), + ALR -> (currentImportance => { + val ignoreOutput = allAddingOutputsUnimportant(currentImportance) + currentImportance.copy( + a = if (ignoreOutput) Unimportant else Important, + n = Unimportant, z = Unimportant, c = Unimportant, + m = Important) + }), + STA_W -> (importance => importance.copy(a = Important, ah = Important, m = Important)), STX_W -> (importance => importance.copy(x = Important, w = Important)), STY_W -> (importance => importance.copy(y = Important, w = Important)), STZ_W -> (importance => importance.copy(iz = Important, m = Important)), - DEX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), - DEY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), - DEZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)), - - INX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), - INY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), - INZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)), - - DEX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), - DEY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), - INX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)), - INY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)), - - PHP -> (_.copy(n = Important, c = Important, d = Important, z = Important, v = Important, m = Important, w = Important)), - PLP -> (_.copy(n = Unimportant, c = Unimportant, d = Unimportant, z = Unimportant, v = Unimportant, m = Unimportant, w = Unimportant)), - - PHA -> (_.copy(a = Important, m = Important)), - PLA -> (_.copy(a = Unimportant, m = Important, n = Unimportant, z = Unimportant)), - PHX -> (_.copy(x = Important, w = Important)), - PLX -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)), - PHY -> (_.copy(y = Important, w = Important)), - PLY -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)), - PHZ -> (_.copy(iz = Important, w = Important)), - PLZ -> (_.copy(iz = Unimportant, w = Important, n = Unimportant, z = Unimportant)), - - PHA_W -> (_.copy(a = Important, ah = Important, m = Important)), - PLA_W -> (_.copy(a = Unimportant, ah = Unimportant, m = Important, n = Unimportant, z = Unimportant)), - PHX_W -> (_.copy(x = Important, w = Important)), - PLX_W -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)), - PHY_W -> (_.copy(y = Important, w = Important)), - PLY_W -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)), - - CLC -> (_.copy(c = Unimportant)), - SEC -> (_.copy(c = Unimportant)), - CLD -> (_.copy(d = Unimportant)), - SED -> (_.copy(d = Unimportant)), - CLV -> (_.copy(v = Unimportant)), - ) def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode) diff --git a/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala b/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala index dddee16d..f7beb8b2 100644 --- a/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/mos/opt/RuleBasedAssemblyOptimization.scala @@ -847,6 +847,56 @@ case class RefersTo(identifier: String, offset: Int = 999) extends TrivialAssemb override def toString: String = s"<$identifier+$offset>" } +case class RefersToOrUses(identifier: String, offset: Int = 999) extends TrivialAssemblyLinePattern { + override def apply(line: AssemblyLine): Boolean = { + line.addrMode match { + case AddrMode.ZeroPage | AddrMode.Absolute | AddrMode.LongAbsolute | AddrMode.Indirect => line.parameter match { + case MemoryAddressConstant(th) => + (offset == 999 || offset == 0) && th.name == identifier + case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset == nn) && th.name == identifier + case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) => + (offset == 999 || offset == nn) && th.name == identifier + case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset == -nn) && th.name == identifier + case _ => false + } + case AddrMode.IndexedY | AddrMode.LongIndexedY | AddrMode.IndexedZ | AddrMode.LongIndexedZ => line.parameter match { + case MemoryAddressConstant(th) => + (offset == 999 || offset == 0 || offset == 1) && th.name == identifier + case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset == nn || offset == nn + 1) && th.name == identifier + case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) => + (offset == 999 || offset == nn || offset == nn + 1) && th.name == identifier + case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset == -nn || offset == -nn + 1) && th.name == identifier + case _ => false + } + case AddrMode.AbsoluteX | AddrMode.AbsoluteY | AddrMode.AbsoluteIndexedX => line.parameter match { + case MemoryAddressConstant(th) => + (offset == 999 || offset >= 0 && offset <= 255) && th.name == identifier + case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset >= nn && offset <= nn + 255) && th.name == identifier + case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) => + (offset == 999 || offset >= nn && offset <= nn + 255) && th.name == identifier + case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) => + (offset == 999 || offset >= -nn && offset <= -nn + 255) && th.name == identifier + case _ => false + } + case AddrMode.IndexedX => line.parameter match { + case MemoryAddressConstant(th) => th.name == identifier + case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) => th.name == identifier + case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) => th.name == identifier + case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) => th.name == identifier + case _ => false + } + case _ => false + } + } + + override def toString: String = s"<$identifier+$offset>" +} + case class CallsAnyOf(identifiers: Set[String]) extends TrivialAssemblyLinePattern { override def apply(line: AssemblyLine): Boolean = { (line.addrMode == AddrMode.Absolute || diff --git a/src/main/scala/millfork/assembly/mos/opt/ZeropageRegisterOptimizations.scala b/src/main/scala/millfork/assembly/mos/opt/ZeropageRegisterOptimizations.scala index 88157a05..8ada7079 100644 --- a/src/main/scala/millfork/assembly/mos/opt/ZeropageRegisterOptimizations.scala +++ b/src/main/scala/millfork/assembly/mos/opt/ZeropageRegisterOptimizations.scala @@ -3,7 +3,7 @@ package millfork.assembly.mos.opt import millfork.assembly.mos.Opcode._ import millfork.assembly.mos.AddrMode._ import millfork.assembly.AssemblyOptimization -import millfork.assembly.mos.AssemblyLine +import millfork.assembly.mos.{AssemblyLine, State} import millfork.env.{CompoundConstant, Constant, MathOperator} /** @@ -16,7 +16,7 @@ object ZeropageRegisterOptimizations { val ConstantMultiplication = new RuleBasedAssemblyOptimization("Constant multiplication", needsFlowInfo = FlowInfoRequirement.ForwardFlow, (HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1) & MatchA(4)) ~ - (Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ + (Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ (HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(5)) ~ (Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) => val product = ctx.get[Int](4) * ctx.get[Int](5) @@ -26,7 +26,7 @@ object ZeropageRegisterOptimizations { // TODO: constants other than power of 2: (Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1)) ~ - (Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ + (Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ (HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(4)) ~ Where(ctx => { val constant = ctx.get[Int](4) @@ -46,7 +46,7 @@ object ZeropageRegisterOptimizations { val constant = ctx.get[Int](4) (constant & (constant - 1)) == 0 }) ~ - (Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ + (Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~ (HasOpcode(STA) & RefersTo("__reg", 1)) ~ (Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) => val constant = ctx.get[Int](4) @@ -70,9 +70,18 @@ object ZeropageRegisterOptimizations { ) val DeadRegStoreFromFlow = new RuleBasedAssemblyOptimization("Dead zeropage register store from flow", - needsFlowInfo = FlowInfoRequirement.BackwardFlow, + needsFlowInfo = FlowInfoRequirement.BothFlows, (Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWithReg(0)) ~~> (_.tail), (Elidable & HasOpcode(STA) & RefersTo("__reg", 1) & DoesntMatterWhatItDoesWithReg(1)) ~~> (_.tail), + + (Elidable & HasOpcode(LDY) & RefersTo("__reg", 0)) ~ + (Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).*.capture(2) ~ + (Elidable & (HasA(0) & HasOpcode(STA) | HasOpcode(STZ)) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWith(State.A)) ~ + ((Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).* ~ + (Elidable & RefersToOrUses("__reg", 0) & HasAddrMode(IndexedY) & DoesntMatterWhatItDoesWithReg(0) & DoesntMatterWhatItDoesWith(State.Y))).capture(3) ~~> ((code, ctx) => + ctx.get[List[AssemblyLine]](2) ++ List(AssemblyLine.immediate(LDY, 0)) ++ ctx.get[List[AssemblyLine]](3) + ) + ) val All: List[AssemblyOptimization[AssemblyLine]] = List(