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

Optimization fixes (inlining to registers, function inlining, bit operations, DCP opcode)

This commit is contained in:
Karol Stasiak 2018-01-18 22:37:47 +01:00
parent b486436185
commit 64f72c8a1c
7 changed files with 36 additions and 15 deletions

View File

@ -90,7 +90,7 @@ object Main {
if (options.flag(CompilationFlag.EmitCmosOpcodes)) CmosOptimizations.All else LaterOptimizations.Nmos,
if (options.flag(CompilationFlag.DangerousOptimizations)) DangerousOptimizations.All else Nil,
).flatten
val goodCycle = List.fill(optLevel - 1)(OptimizationPresets.Good ++ extras).flatten
val goodCycle = List.fill(optLevel - 1)(OptimizationPresets.Good).flatten
val assemblyOptimizations = if (optLevel <= 0) Nil else if (optLevel >= 9) List(SuperOptimizer) else {
goodCycle ++ OptimizationPresets.AssOpt ++ extras ++ goodCycle
}

View File

@ -153,5 +153,6 @@ object OptimizationPresets {
AlwaysGoodOptimizations.TailCallOptimization,
AlwaysGoodOptimizations.UnusedCodeRemoval,
AlwaysGoodOptimizations.UnusedLabelRemoval,
VariableToRegisterOptimization,
)
}

View File

@ -921,16 +921,23 @@ object AlwaysGoodOptimizations {
},
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.A)) ~
(Linear & DoesNotConcernMemoryAt(0, 1)).* ~
(Linear & DoesNotConcernMemoryAt(0, 1) & DoesntChangeIndexingInAddrMode(0)).* ~
(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 =>
(Linear & DoesNotConcernMemoryAt(0, 1) & DoesntChangeIndexingInAddrMode(0)).* ~
(Elidable & HasOpcode(LSR) & 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 & Not(HasOpcode(LSR)) & DoesNotConcernMemoryAt(0, 1) & DoesntChangeIndexingInAddrMode(0)).* ~
(Elidable & HasOpcode(LSR) & DoesNotConcernMemoryAt(0, 1)) ~
(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
},
)
private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => {

View File

@ -32,5 +32,5 @@ object CmosOptimizations {
(Elidable & HasX(0) & HasAddrMode(IndexedX) & HasOpcodeIn(SupportsZeroPageIndirect)) ~~> (code => code.map(_.copy(addrMode = ZeroPageIndirect))),
)
val All: List[AssemblyOptimization] = List(ZeroStoreAsStz)
val All: List[AssemblyOptimization] = List(OptimizeZeroIndex, ZeroStoreAsStz)
}

View File

@ -259,15 +259,6 @@ object UndocumentedOptimizations {
(Elidable & HasOpcode(DEC) & HasAddrMode(AbsoluteX) & DoesntMatterWhatItDoesWith(State.A, State.Y, State.X, State.C, State.Z, State.N, State.V)) ~~> { code =>
List(code.head.copy(opcode = LDY), code.last.copy(opcode = DCP, addrMode = AbsoluteY))
},
(Elidable & HasOpcode(DEC) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(LDA) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(CMP) & MatchAddrMode(2) & MatchParameter(3) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.A)) ~~> { code =>
List(code(2).copy(opcode = LDA), code(1).copy(opcode = DCP))
},
(Elidable & HasOpcode(DEC) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(LDA) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.A)) ~~> { code =>
List(AssemblyLine.immediate(LDA, 0), code(1).copy(opcode = DCP))
},
)
val UseIsc = new RuleBasedAssemblyOptimization("Using undocumented instruction ISC",

View File

@ -12,7 +12,7 @@ import scala.collection.mutable
*/
object InliningCalculator {
private val sizes = Seq(30, 30, 8, 6, 5, 5, 4)
private val sizes = Seq(64, 64, 8, 6, 5, 5, 4)
def getPotentiallyInlineableFunctions(program: Program): Map[String, Int] = {
val callCount = mutable.Map[String, Int]().withDefaultValue(0)

View File

@ -147,4 +147,26 @@ class BitPackingSuite extends FunSuite with Matchers {
m.readByte(addr) should equal(0x5A)
}
}
test("Reverse word") {
EmuBenchmarkRun("""
| word output_addr @$C000
| void main () {
| byte i
| word input
| word output
| output_addr = output.addr
| input = $5AC1
| output = 0
| for i,0,paralleluntil,16 {
| output <<= 1
| output.lo |= input.lo & 1
| input >>= 1
| }
| }
""".stripMargin){m =>
val addr = m.readWord(0xc000)
m.readWord(addr) should equal(0x835A)
}
}
}