1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-04 16:29:52 +00:00

More bit-packing and transfer optimizations

This commit is contained in:
Karol Stasiak 2018-01-08 12:00:46 +01:00
parent 4676b0d48e
commit d696704af9
2 changed files with 39 additions and 6 deletions

View File

@ -528,10 +528,10 @@ object AlwaysGoodOptimizations {
val PointlessLoadBeforeTransfer = new RuleBasedAssemblyOptimization("Pointless load before transfer",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
loadBeforeTransfer(LDX, LDA, ConcernsX, State.X, TXA, Set(ZeroPage, Absolute, IndexedY, AbsoluteY)),
loadBeforeTransfer(LDA, LDX, ConcernsA, State.A, TAX, Set(ZeroPage, Absolute, IndexedY, AbsoluteY)),
loadBeforeTransfer(LDY, LDA, ConcernsY, State.Y, TYA, Set(ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)),
loadBeforeTransfer(LDA, LDY, ConcernsA, State.A, TAY, Set(ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)),
loadBeforeTransfer(LDX, LDA, ConcernsX, State.X, TXA, Set(Immediate, ZeroPage, Absolute, IndexedY, AbsoluteY)),
loadBeforeTransfer(LDA, LDX, ConcernsA, State.A, TAX, Set(Immediate, ZeroPage, Absolute, IndexedY, AbsoluteY)),
loadBeforeTransfer(LDY, LDA, ConcernsY, State.Y, TYA, Set(Immediate, ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)),
loadBeforeTransfer(LDA, LDY, ConcernsA, State.A, TAY, Set(Immediate, ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)),
)
private def immediateLoadBeforeTwoTransfers(ld1: Opcode.Value, ld2: Opcode.Value, concerns1: AssemblyLinePattern, overwrites1: State.Value, t12: Opcode.Value, t21: Opcode.Value) =
@ -916,9 +916,21 @@ object AlwaysGoodOptimizations {
(Elidable & (HasOpcode(ORA) | HasOpcode(ADC) & HasClear(State.C) & HasClear(State.D)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z, State.V, State.A)) ~~> { (code, ctx) =>
ctx.get[List[AssemblyLine]](3) ++
List(AssemblyLine.implied(ROR), code.head.copy(opcode = ROL)) ++
List(AssemblyLine.implied(LSR), code.head.copy(opcode = ROL)) ++
ctx.get[List[AssemblyLine]](2)
},
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.A)) ~
(Linear & DoesNotConcernMemoryAt(0, 1)).* ~
(Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code =>
code.last :: code.drop(2).init
},
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.A)) ~
(Linear & DoesNotConcernMemoryAt(0, 1)).* ~
(Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code =>
code.last :: code.drop(2).init
},
)
private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => {

View File

@ -1,6 +1,5 @@
package millfork.test
import millfork.error.ErrorReporting
import millfork.test.emu.EmuBenchmarkRun
import org.scalatest.{FunSuite, Matchers}
@ -126,4 +125,26 @@ class BitPackingSuite extends FunSuite with Matchers {
m.readByte(0xc000) should equal(0x56)
}
}
test("Reverse byte") {
EmuBenchmarkRun("""
| word output_addr @$C000
| void main () {
| byte i
| byte input
| byte output
| output_addr = output.addr
| input = $5A
| output = 0
| for i,0,paralleluntil,8 {
| output <<= 1
| output |= input & 1
| input >>= 1
| }
| }
""".stripMargin){m =>
val addr = m.readWord(0xc000)
m.readByte(addr) should equal(0x5A)
}
}
}