mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-11 12:29:46 +00:00
Optimizations of adding one
This commit is contained in:
parent
1d468e1313
commit
b6e61f16ec
@ -1388,8 +1388,32 @@ object AlwaysGoodOptimizations {
|
|||||||
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasClear(State.D) & DoesntMatterWhatItDoesWith(State.V)) ~~> { code =>
|
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & HasClear(State.D) & DoesntMatterWhatItDoesWith(State.V)) ~~> { code =>
|
||||||
List(code.head, AssemblyLine.implied(ROL))
|
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(ROL) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = ASL))),
|
||||||
(Elidable & HasOpcode(ROR) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = LSR))),
|
(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",
|
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 =>
|
(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
|
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 => {
|
private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => {
|
||||||
|
@ -506,4 +506,38 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
|||||||
m.readByte(0xc000) should equal(0x46)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user