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

Loop compilation/optimization fixes/improvements

This commit is contained in:
Karol Stasiak 2018-06-18 17:54:45 +02:00
parent 24a3943501
commit ca14e417dd
2 changed files with 12 additions and 15 deletions

View File

@ -3,7 +3,7 @@ package millfork.assembly.mos.opt
import java.util.concurrent.atomic.AtomicInteger
import millfork.{CompilationFlag, CompilationOptions}
import millfork.assembly.mos.AssemblyLine
import millfork.assembly.mos.{AssemblyLine, State}
import millfork.assembly.mos.OpcodeClasses._
import millfork.assembly.mos.Opcode._
import millfork.assembly.mos.AddrMode._
@ -37,13 +37,10 @@ object LoopUnrolling {
val bodyCode = ctx.get[List[AssemblyLine]](Body)
val start = ctx.get[Int](Start)
val end = ctx.getOrDefault[Int](End, 0)
if (start == end) return true
if (start == end) return false // 256 iterations, don't inline ever
val increasing = isIncreasing(ctx)
if (increasing != (start < end)) return false // overflow not supported
val count = Math.abs(start - end)
if (count > 32) return false
if (count > 8 && !ctx.compilationOptions.flag(CompilationFlag.OptimizeForSonicSpeed)) return false
if (count > 3 && !ctx.compilationOptions.flag(CompilationFlag.OptimizeForSpeed)) return false
val onlyUsedForArrayIndexing = index match {
case Unrolling.Var => false
case Unrolling.X => bodyCode.forall(line => !ConcernsX(line) || line.addrMode == AbsoluteX)
@ -69,7 +66,7 @@ object LoopUnrolling {
private def isIncreasing(ctx: AssemblyMatchingContext) = {
val opcode = ctx.get[List[AssemblyLine]](Step).head.opcode
opcode == INX || opcode == INY || opcode == INC || opcode == ISC
opcode == INX || opcode == INY || opcode == INZ || opcode == INC || opcode == ISC
}
private def fixLabels(code: List[AssemblyLine]) = {
@ -86,15 +83,15 @@ object LoopUnrolling {
}
val LoopUnrolling = new RuleBasedAssemblyOptimization("Loop unrolling",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(Elidable & HasOpcode(LDX) & MatchNumericImmediate(Start)).capture(Initialization) ~
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(Elidable & HasOpcode(LDX) & MatchNumericImmediate(Start) & Not(HasImmediate(0))).capture(Initialization) ~
(Elidable & HasOpcode(BEQ) & MatchParameter(Skip)) ~
(Elidable & HasOpcode(LABEL) & MatchParameter(Back)) ~
((Elidable & Not(HasOpcodeIn(Set(RTS, JSR, RTI, RTL))) & Not(ChangesX)).*.capture(Body) ~
(Elidable & HasOpcodeIn(Set(DEX, INX))).capture(Step)
).capture(BodyWithStep) ~
(Elidable & HasOpcode(CPX) & MatchNumericImmediate(End)).? ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z)) ~
(Elidable & HasOpcode(LABEL) & MatchParameter(Skip)) ~
Where(ctx => isFeasible(ctx, 4, Unrolling.X)) ~~> { (code, ctx) =>
val start = ctx.get[Int](Start)
@ -108,7 +105,7 @@ object LoopUnrolling {
(Elidable & HasOpcodeIn(Set(DEX, INX))).capture(Step)
).capture(BodyWithStep) ~
(Elidable & HasOpcode(CPX) & MatchNumericImmediate(End)).? ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z)) ~
Where(ctx => isFeasible(ctx, 2, Unrolling.X)) ~~> { (code, ctx) =>
val start = ctx.get[Int](Start)
val end = ctx.getOrDefault[Int](End, 0)
@ -128,14 +125,14 @@ object LoopUnrolling {
val increasing = isIncreasing(ctx)
ctx.get[List[AssemblyLine]](Initialization) ++ (0 until Math.abs(start - end)).flatMap(_ => fixLabels(ctx.get[List[AssemblyLine]](BodyWithStep)))
},
(Elidable & HasOpcode(LDY) & MatchNumericImmediate(Start)).capture(Initialization) ~
(Elidable & HasOpcode(LDY) & MatchNumericImmediate(Start) & Not(HasImmediate(0))).capture(Initialization) ~
(Elidable & HasOpcode(BEQ) & MatchParameter(Skip)) ~
(Elidable & HasOpcode(LABEL) & MatchParameter(Back)) ~
((Elidable & Not(HasOpcodeIn(Set(RTS, JSR, RTI, RTL))) & Not(ChangesY)).*.capture(Body) ~
(Elidable & HasOpcodeIn(Set(DEY, INY))).capture(Step)
).capture(BodyWithStep) ~
(Elidable & HasOpcode(CPY) & MatchNumericImmediate(End)).? ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z)) ~
(Elidable & HasOpcode(LABEL) & MatchParameter(Skip)) ~
Where(ctx => isFeasible(ctx, 4, Unrolling.Y)) ~~> { (code, ctx) =>
val start = ctx.get[Int](Start)
@ -149,7 +146,7 @@ object LoopUnrolling {
(Elidable & HasOpcodeIn(Set(DEY, INY))).capture(Step)
).capture(BodyWithStep) ~
(Elidable & HasOpcode(CPY) & MatchNumericImmediate(End)).? ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z)) ~
Where(ctx => isFeasible(ctx, 2, Unrolling.Y)) ~~> { (code, ctx) =>
val start = ctx.get[Int](Start)
val end = ctx.getOrDefault[Int](End, 0)
@ -162,7 +159,7 @@ object LoopUnrolling {
(Elidable & Not(HasOpcodeIn(Set(RTS, JSR, RTI, RTL, BNE, CPY, TYA))) & Not(ChangesY)).*.capture(Body)
).capture(BodyWithStep) ~
(Elidable & HasOpcode(CPY) & MatchNumericImmediate(End) | Elidable & HasOpcode(TYA)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back)) ~
(Elidable & HasOpcode(BNE) & MatchParameter(Back) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z)) ~
Where(ctx => isFeasible(ctx, 2, Unrolling.Y)) ~~> { (code, ctx) =>
val start = ctx.get[Int](Start)
val end = ctx.getOrDefault[Int](End, 0)

View File

@ -21,7 +21,7 @@ object MosStatementCompiler extends AbstractStatementCompiler[AssemblyLine] {
def branchChunk(opcode: BranchingOpcodeMapping, labelName: String) = List(AssemblyLine.relative(opcode.mosOpcode, Label(labelName)))
def areBlocksLarge(blocks: List[AssemblyLine]*): Boolean = blocks.map(_.map(_.sizeInBytes).sum).sum > 100
def areBlocksLarge(blocks: List[AssemblyLine]*): Boolean = blocks.map(_.map(_.sizeInBytes).sum).sum > 170
def compileExpressionForBranching(ctx: CompilationContext, expr: Expression, branching: BranchSpec): List[AssemblyLine] = {
val b = ctx.env.get[Type]("byte")