1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 22:29:33 +00:00
millfork/src/main/scala/millfork/assembly/mos/opt/FlowAnalyzer.scala

65 lines
2.7 KiB
Scala
Raw Normal View History

package millfork.assembly.mos.opt
2017-12-06 23:23:30 +00:00
import millfork.assembly.OptimizationContext
import millfork.assembly.mos.{AssemblyLine, AssemblyLine0, Opcode, State}
2019-11-24 00:30:30 +00:00
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, StructureConstant}
2017-12-06 23:23:30 +00:00
/**
* @author Karol Stasiak
*/
2018-02-26 16:12:12 +00:00
class FlowHolder(_statusBefore: () => List[CpuStatus], _importanceAfter: () => List[CpuImportance]) {
lazy val statusBefore: List[CpuStatus] = _statusBefore()
lazy val importanceAfter: List[CpuImportance] = _importanceAfter()
def toString(index: Int): String = statusBefore(index).toString ++ " -> " ++ importanceAfter(index).toString
2018-02-26 16:12:12 +00:00
}
case class FlowInfo(holder: FlowHolder, index: Int, _labelUseCountMap: () => Option[Map[String, Int]]) {
lazy val statusBefore: CpuStatus = holder.statusBefore(index)
2019-06-12 20:55:34 +00:00
lazy val importanceAfter: CpuImportance = holder.importanceAfter(index)
2018-02-26 16:12:12 +00:00
lazy val labelUseCountMap: Option[Map[String, Int]] = _labelUseCountMap()
2017-12-06 23:23:30 +00:00
2023-02-03 13:45:47 +00:00
@inline
2017-12-06 23:23:30 +00:00
def hasClear(state: State.Value): Boolean = statusBefore.hasClear(state)
2023-02-03 13:45:47 +00:00
@inline
2017-12-06 23:23:30 +00:00
def hasSet(state: State.Value): Boolean = statusBefore.hasSet(state)
2023-02-03 13:45:47 +00:00
@inline
2017-12-06 23:23:30 +00:00
def isUnimportant(state: State.Value): Boolean = importanceAfter.isUnimportant(state)
2023-02-03 13:45:47 +00:00
@inline
def labelUseCount(label: String): Int = labelUseCountMap.map(_.getOrElse(label, 0)).getOrElse(-1)
override def toString: String = holder.toString(index)
2017-12-06 23:23:30 +00:00
}
object FlowAnalyzer {
2018-02-26 16:12:12 +00:00
private val EmptyCpuStatus = CpuStatus()
private val EmptyCpuImportance = CpuImportance()
def analyze(f: NormalFunction, code: List[AssemblyLine], optimizationContext: OptimizationContext, req: FlowInfoRequirement.Value): List[(FlowInfo, AssemblyLine)] = {
val forwardFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow =>
() => CoarseFlowAnalyzer.analyze(f, code, optimizationContext)
case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
2018-02-26 16:12:12 +00:00
() => List.fill(code.size)(EmptyCpuStatus)
}
val reverseFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.BackwardFlow =>
() => ReverseFlowAnalyzer.analyze(f, code, optimizationContext)
case FlowInfoRequirement.ForwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
2018-02-26 16:12:12 +00:00
() => List.fill(code.size)(EmptyCpuImportance)
}
val labelMap: () => Option[Map[String, Int]] = () => req match {
case FlowInfoRequirement.NoRequirement => None
2021-04-23 23:16:16 +00:00
case _ => Some(code.filter(m => m.opcode != Opcode.LABEL).flatMap(_.parameter.extractLabels).groupBy(identity).mapValues(_.size).view.force)
2017-12-06 23:23:30 +00:00
}
2018-02-26 16:12:12 +00:00
val holder = new FlowHolder(forwardFlow, reverseFlow)
code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line}
2017-12-06 23:23:30 +00:00
}
}