mirror of
https://github.com/KarolS/millfork.git
synced 2025-02-13 01:30:27 +00:00
Optimization fixes (inlining to registers, function inlining, bit operations, DCP opcode)
This commit is contained in:
parent
b486436185
commit
64f72c8a1c
@ -90,7 +90,7 @@ object Main {
|
|||||||
if (options.flag(CompilationFlag.EmitCmosOpcodes)) CmosOptimizations.All else LaterOptimizations.Nmos,
|
if (options.flag(CompilationFlag.EmitCmosOpcodes)) CmosOptimizations.All else LaterOptimizations.Nmos,
|
||||||
if (options.flag(CompilationFlag.DangerousOptimizations)) DangerousOptimizations.All else Nil,
|
if (options.flag(CompilationFlag.DangerousOptimizations)) DangerousOptimizations.All else Nil,
|
||||||
).flatten
|
).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 {
|
val assemblyOptimizations = if (optLevel <= 0) Nil else if (optLevel >= 9) List(SuperOptimizer) else {
|
||||||
goodCycle ++ OptimizationPresets.AssOpt ++ extras ++ goodCycle
|
goodCycle ++ OptimizationPresets.AssOpt ++ extras ++ goodCycle
|
||||||
}
|
}
|
||||||
|
@ -153,5 +153,6 @@ object OptimizationPresets {
|
|||||||
AlwaysGoodOptimizations.TailCallOptimization,
|
AlwaysGoodOptimizations.TailCallOptimization,
|
||||||
AlwaysGoodOptimizations.UnusedCodeRemoval,
|
AlwaysGoodOptimizations.UnusedCodeRemoval,
|
||||||
AlwaysGoodOptimizations.UnusedLabelRemoval,
|
AlwaysGoodOptimizations.UnusedLabelRemoval,
|
||||||
|
VariableToRegisterOptimization,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -921,16 +921,23 @@ object AlwaysGoodOptimizations {
|
|||||||
},
|
},
|
||||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||||
(Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.A)) ~
|
(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 =>
|
(Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code =>
|
||||||
code.last :: code.drop(2).init
|
code.last :: code.drop(2).init
|
||||||
},
|
},
|
||||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||||
(Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.A)) ~
|
(Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.A)) ~
|
||||||
(Linear & DoesNotConcernMemoryAt(0, 1)).* ~
|
(Linear & DoesNotConcernMemoryAt(0, 1) & DoesntChangeIndexingInAddrMode(0)).* ~
|
||||||
(Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code =>
|
(Elidable & HasOpcode(LSR) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code =>
|
||||||
code.last :: code.drop(2).init
|
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 => {
|
private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => {
|
||||||
|
@ -32,5 +32,5 @@ object CmosOptimizations {
|
|||||||
(Elidable & HasX(0) & HasAddrMode(IndexedX) & HasOpcodeIn(SupportsZeroPageIndirect)) ~~> (code => code.map(_.copy(addrMode = ZeroPageIndirect))),
|
(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)
|
||||||
}
|
}
|
||||||
|
@ -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 =>
|
(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))
|
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",
|
val UseIsc = new RuleBasedAssemblyOptimization("Using undocumented instruction ISC",
|
||||||
|
@ -12,7 +12,7 @@ import scala.collection.mutable
|
|||||||
*/
|
*/
|
||||||
object InliningCalculator {
|
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] = {
|
def getPotentiallyInlineableFunctions(program: Program): Map[String, Int] = {
|
||||||
val callCount = mutable.Map[String, Int]().withDefaultValue(0)
|
val callCount = mutable.Map[String, Int]().withDefaultValue(0)
|
||||||
|
@ -147,4 +147,26 @@ class BitPackingSuite extends FunSuite with Matchers {
|
|||||||
m.readByte(addr) should equal(0x5A)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user