1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +00:00

Optimizations of adding one

This commit is contained in:
Karol Stasiak 2018-06-01 09:51:59 +02:00
parent 1d468e1313
commit b6e61f16ec
2 changed files with 71 additions and 0 deletions

View File

@ -1388,8 +1388,32 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasClear(State.D) & DoesntMatterWhatItDoesWith(State.V)) ~~> { code =>
List(code.head, AssemblyLine.implied(ROL))
},
(Elidable & HasOpcode(ADC) & HasImmediate(0) & HasClear(State.C) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcode(ROL) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = ASL))),
(Elidable & HasOpcode(ROR) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = LSR))),
(HasOpcode(AND) & HasImmediate(1)) ~
(Linear & Not(ChangesNAndZ) & Not(HasOpcode(CLC)) & Not(ChangesA)).* ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasAddrModeIn(Set(ZeroPage, ZeroPageX, Absolute, AbsoluteX))) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { code =>
val label = getNextLabel("in")
code.take(code.length - 3) ++ List(
AssemblyLine.relative(BEQ, label),
code.last.copy(opcode = INC),
AssemblyLine.label(label)
)
},
(HasOpcode(ANC) & HasImmediate(1)) ~
(Linear & Not(ChangesNAndZ) & Not(ChangesA) & (Not(ChangesC) | HasOpcode(CLC))).* ~
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasClear(State.D) & HasAddrModeIn(Set(ZeroPage, ZeroPageX, Absolute, AbsoluteX))) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.V, State.Z, State.N, State.A)) ~~> { code =>
val label = getNextLabel("in")
code.head.copy(opcode = AND) :: code.take(code.length - 2).tail ++ List(
AssemblyLine.relative(BEQ, label),
code.last.copy(opcode = INC),
AssemblyLine.label(label)
)
},
)
val IndexSequenceOptimization = new RuleBasedAssemblyOptimization("Index sequence optimization",
@ -1542,6 +1566,19 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(ROR) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> { code =>
code.init.last :: code.last :: code.drop(2).init.init
},
(Elidable & HasOpcode(ASL) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(INC) & MatchAddrMode(0) & MatchParameter(1)) ~~> { code =>
List(AssemblyLine.implied(SEC), code.head.copy(opcode = ROL))
},
(Elidable & HasOpcode(ASL) & HasAddrMode(AddrMode.Implied)) ~
(Elidable & HasOpcode(CLC)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(1) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(SEC), code.head.copy(opcode = ROL))
},
(Elidable & HasOpcode(ASL) & HasAddrMode(AddrMode.Implied)) ~
(Elidable & HasOpcodeIn(Set(ORA, EOR)) & HasImmediate(1)) ~~> { code =>
List(AssemblyLine.implied(SEC), code.head.copy(opcode = ROL))
},
)
private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => {

View File

@ -506,4 +506,38 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
m.readByte(0xc000) should equal(0x46)
}
}
test("Shift and increase") {
EmuBenchmarkRun(
"""
| byte output @$c000
| void main() {
| output = twicePlusOne(5)
| }
| noinline byte twicePlusOne (byte x) {
| return x * 2 + 1
| }
""".stripMargin
){m =>
m.readByte(0xc000) should equal(11)
}
}
test("Add one bit") {
EmuBenchmarkRun(
"""
| byte output @$c000
| void main() {
| output = 0
| increaseByBit(5)
| }
| noinline void increaseByBit (byte y) {
| output += y & 1
| }
""".stripMargin
){m =>
m.readByte(0xc000) should equal(1)
}
}
}