1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-04-09 09:41:23 +00:00

6502: Fix optimization bug (fixes ) and add more optimizations involving ARR

This commit is contained in:
Karol Stasiak 2020-01-24 02:18:36 +01:00
parent d6fd1e8b77
commit 5c40d581c0
3 changed files with 46 additions and 4 deletions
src

@ -1839,8 +1839,8 @@ object AlwaysGoodOptimizations {
val ifSet = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) 0 else nonZero)
val ifClear = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) nonZero else 0)
val jump = Elidable & HasOpcodeIn(Set(JMP, if (firstSet) BCS else BCC, if (zeroIfSet) BEQ else BNE)) & MatchParameter(1)
val elseLabel = Elidable & HasOpcode(LABEL) & MatchParameter(0)
val afterLabel = Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)
val elseLabel = (Elidable & HasOpcode(LABEL) & MatchParameter(0)).capture(10)
val afterLabel = Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z) & IsNotALabelUsedManyTimes
val store = Elidable & (Not(ReadsC) & Linear | HasOpcodeIn(RTS, JSR, RTI, RTL, BSR))
val secondReturn = (Elidable & (HasOpcodeIn(RTS, RTI) | NoopDiscardsFlags)).*.capture(6)
val where = Where { ctx =>
@ -1851,13 +1851,22 @@ object AlwaysGoodOptimizations {
if (firstSet) test ~ ifSet ~ store.*.capture(4) ~ jump ~ elseLabel ~ ifClear ~ store.*.capture(5) ~ afterLabel ~ secondReturn ~ where
else test ~ ifClear ~ store.*.capture(4) ~ jump ~ elseLabel ~ ifSet ~ store.*.capture(5) ~ afterLabel ~ secondReturn ~ where
pattern ~~> { (_, ctx) =>
val elseLabelUseCount = ctx.get[Constant](0) match {
case MemoryAddressConstant(Label(label)) => ctx.labelUseCount(label)
case _ => 9999
}
List(
AssemblyLine.immediate(LDA, 0),
AssemblyLine.implied(if (shift >= 4) ROR else ROL)) ++
(if (shift >= 4) List.fill(7 - shift)(AssemblyLine.implied(LSR)) else List.fill(shift)(AssemblyLine.implied(ASL))) ++
(if (zeroIfSet) List(AssemblyLine.immediate(EOR, nonZero)) else Nil) ++
ctx.get[List[AssemblyLine]](5) ++
ctx.get[List[AssemblyLine]](6)
ctx.get[List[AssemblyLine]](6) ++ (
if (elseLabelUseCount == 1) Nil
else ctx.get[List[AssemblyLine]](10) ++ List(
AssemblyLine.immediate(LDA, if (firstSet) (if (zeroIfSet) nonZero else 0) else (if (zeroIfSet) 0 else nonZero))
) ++ ctx.get[List[AssemblyLine]](5) ++ ctx.get[List[AssemblyLine]](6)
)
}
}

@ -178,9 +178,13 @@ object UndocumentedOptimizations {
val UseArr = new RuleBasedAssemblyOptimization("Using undocumented instruction ARR",
needsFlowInfo = FlowInfoRequirement.BothFlows,
(HasClear(State.D) & Elidable & HasOpcode(AND) & HasAddrMode(Immediate)) ~
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V, State.N, State.Z)) ~~> { code =>
List(AssemblyLine.immediate(ARR, code.head.parameter))
},
(HasClear(State.D) & Elidable & HasOpcode(LDA) & HasAddrMode(Immediate) & HasImmediate(0)) ~
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V, State.N, State.Z)) ~~> { code =>
List(AssemblyLine.immediate(ARR, 0))
},
)
private def extraRmw(legal: Opcode.Value, illegal: Opcode.Value) =

@ -816,4 +816,33 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
m.readByte(0xc000) should equal(51)
}
}
test("Test bug #41") {
val code =
"""
|struct Entity {
| byte x,
| byte y
|}
|
|array(Entity) entities [2]
|
|byte output @$c000
|
|void main() {
| if test(0, 200) {
| output = 1
| }
|}
|
|inline bool test(byte i, byte y) {
| return y >= entities[i].y && y <= entities[i].y + 8
|}
|
|""".stripMargin
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(code) { m =>
}
EmuUndocumentedRun(code)
}
}