1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-09-10 11:54:30 +00:00

Lazy flow analysis

This commit is contained in:
Karol Stasiak 2018-02-26 17:12:12 +01:00
parent b9eb59ad51
commit a2b6a392a5

View File

@ -8,7 +8,16 @@ import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
* @author Karol Stasiak * @author Karol Stasiak
*/ */
case class FlowInfo(statusBefore: CpuStatus, importanceAfter: CpuImportance, labelUseCountMap: Option[Map[String, Int]]) { class FlowHolder(_statusBefore: () => List[CpuStatus], _importanceAfter: () => List[CpuImportance]) {
lazy val statusBefore: List[CpuStatus] = _statusBefore()
lazy val importanceAfter: List[CpuImportance] = _importanceAfter()
}
case class FlowInfo(holder: FlowHolder, index: Int, _labelUseCountMap: () => Option[Map[String, Int]]) {
lazy val statusBefore: CpuStatus = holder.statusBefore(index)
lazy val importanceAfter = holder.importanceAfter(index)
lazy val labelUseCountMap: Option[Map[String, Int]] = _labelUseCountMap()
def hasClear(state: State.Value): Boolean = statusBefore.hasClear(state) def hasClear(state: State.Value): Boolean = statusBefore.hasClear(state)
@ -19,35 +28,36 @@ case class FlowInfo(statusBefore: CpuStatus, importanceAfter: CpuImportance, lab
def labelUseCount(label: String): Int = labelUseCountMap.map(_.getOrElse(label, 0)).getOrElse(-1) def labelUseCount(label: String): Int = labelUseCountMap.map(_.getOrElse(label, 0)).getOrElse(-1)
} }
object FlowInfo {
val Default = FlowInfo(CpuStatus(), CpuImportance(), None)
}
object FlowAnalyzer { object FlowAnalyzer {
private val EmptyCpuStatus = CpuStatus()
private val EmptyCpuImportance = CpuImportance()
def analyze(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions, req: FlowInfoRequirement.Value): List[(FlowInfo, AssemblyLine)] = { def analyze(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions, req: FlowInfoRequirement.Value): List[(FlowInfo, AssemblyLine)] = {
val forwardFlow = req match { val forwardFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow => case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow =>
if (options.flag(CompilationFlag.DetailedFlowAnalysis)) { if (options.flag(CompilationFlag.DetailedFlowAnalysis)) {
QuantumFlowAnalyzer.analyze(f, code).map(_.collapse) () => QuantumFlowAnalyzer.analyze(f, code).map(_.collapse)
} else { } else {
CoarseFlowAnalyzer.analyze(f, code) () => CoarseFlowAnalyzer.analyze(f, code)
} }
case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement => case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
List.fill(code.size)(CpuStatus()) () => List.fill(code.size)(EmptyCpuStatus)
} }
val reverseFlow = req match { val reverseFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.BackwardFlow => case FlowInfoRequirement.BothFlows | FlowInfoRequirement.BackwardFlow =>
ReverseFlowAnalyzer.analyze(f, code) () => ReverseFlowAnalyzer.analyze(f, code)
case FlowInfoRequirement.ForwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement => case FlowInfoRequirement.ForwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
List.fill(code.size)(CpuImportance()) () => List.fill(code.size)(EmptyCpuImportance)
} }
val labelMap = req match { val labelMap: (() => Option[Map[String, Int]]) = () => req match {
case FlowInfoRequirement.NoRequirement => None case FlowInfoRequirement.NoRequirement => None
case _ => Some(code.flatMap { case _ => Some(code.flatMap {
case AssemblyLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l) case AssemblyLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l)
case _ => None case _ => None
}.groupBy(identity).mapValues(_.size)) }.groupBy(identity).mapValues(_.size))
} }
forwardFlow.zip(reverseFlow).map { case (s, i) => FlowInfo(s, i, labelMap) }.zip(code) val holder = new FlowHolder(forwardFlow, reverseFlow)
code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line}
} }
} }