1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-25 19:29:49 +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
*/
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)
@ -19,35 +28,36 @@ case class FlowInfo(statusBefore: CpuStatus, importanceAfter: CpuImportance, lab
def labelUseCount(label: String): Int = labelUseCountMap.map(_.getOrElse(label, 0)).getOrElse(-1)
}
object FlowInfo {
val Default = FlowInfo(CpuStatus(), CpuImportance(), None)
}
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)] = {
val forwardFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow =>
if (options.flag(CompilationFlag.DetailedFlowAnalysis)) {
QuantumFlowAnalyzer.analyze(f, code).map(_.collapse)
() => QuantumFlowAnalyzer.analyze(f, code).map(_.collapse)
} else {
CoarseFlowAnalyzer.analyze(f, code)
() => CoarseFlowAnalyzer.analyze(f, code)
}
case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
List.fill(code.size)(CpuStatus())
() => List.fill(code.size)(EmptyCpuStatus)
}
val reverseFlow = req match {
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.BackwardFlow =>
ReverseFlowAnalyzer.analyze(f, code)
() => ReverseFlowAnalyzer.analyze(f, code)
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 _ => Some(code.flatMap {
case AssemblyLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l)
case _ => None
}.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}
}
}