mirror of https://github.com/KarolS/millfork.git
76 lines
2.6 KiB
Scala
76 lines
2.6 KiB
Scala
package millfork.assembly.opt
|
|
|
|
import millfork.{CompilationFlag, CompilationOptions, OptimizationPresets}
|
|
import millfork.assembly.{AddrMode, AssemblyLine, Opcode}
|
|
import millfork.env.NormalFunction
|
|
import millfork.error.ErrorReporting
|
|
|
|
import scala.collection.mutable
|
|
|
|
/**
|
|
* @author Karol Stasiak
|
|
*/
|
|
object SuperOptimizer extends AssemblyOptimization {
|
|
|
|
def optimize(m: NormalFunction, code: List[AssemblyLine], options: CompilationOptions): List[AssemblyLine] = {
|
|
val oldVerbosity = ErrorReporting.verbosity
|
|
ErrorReporting.verbosity = -1
|
|
var allOptimizers = OptimizationPresets.Good ++ LaterOptimizations.All
|
|
if (options.flag(CompilationFlag.EmitIllegals)) {
|
|
allOptimizers ++= UndocumentedOptimizations.All
|
|
}
|
|
if (options.flag(CompilationFlag.EmitCmosOpcodes)) {
|
|
allOptimizers ++= CmosOptimizations.All
|
|
}
|
|
allOptimizers ++= List(
|
|
VariableToRegisterOptimization,
|
|
ChangeIndexRegisterOptimizationPreferringX2Y,
|
|
ChangeIndexRegisterOptimizationPreferringY2X,
|
|
UnusedLabelRemoval)
|
|
val seenSoFar = mutable.Set[CodeView]()
|
|
val queue = mutable.Queue[(List[AssemblyOptimization], List[AssemblyLine])]()
|
|
val leaves = mutable.ListBuffer[(List[AssemblyOptimization], List[AssemblyLine])]()
|
|
seenSoFar += viewCode(code)
|
|
queue.enqueue(Nil -> code)
|
|
while(queue.nonEmpty) {
|
|
val (optsSoFar, codeSoFar) = queue.dequeue()
|
|
var isLeaf = true
|
|
allOptimizers.par.foreach { o =>
|
|
val optimized = o.optimize(m, codeSoFar, options)
|
|
val view = viewCode(optimized)
|
|
seenSoFar.synchronized{
|
|
if (!seenSoFar(view)) {
|
|
isLeaf = false
|
|
seenSoFar += view
|
|
queue.enqueue((o :: optsSoFar) -> optimized)
|
|
}
|
|
}
|
|
}
|
|
if (isLeaf) {
|
|
// println(codeSoFar.map(_.sizeInBytes).sum + " B: " + optsSoFar.reverse.map(_.name).mkString(" -> "))
|
|
leaves += optsSoFar -> codeSoFar
|
|
}
|
|
}
|
|
|
|
val result = leaves.minBy(_._2.map(_.cost).sum)
|
|
ErrorReporting.verbosity = oldVerbosity
|
|
ErrorReporting.debug(s"Visited ${leaves.size} leaves")
|
|
ErrorReporting.debug(s"${code.map(_.sizeInBytes).sum} B -> ${result._2.map(_.sizeInBytes).sum} B: ${result._1.reverse.map(_.name).mkString(" -> ")}")
|
|
result._1.reverse.foldLeft(code){(c, opt) =>
|
|
val n = opt.optimize(m, c, options)
|
|
// println(c.mkString("","",""))
|
|
// println(n.mkString("","",""))
|
|
n
|
|
}
|
|
result._2
|
|
}
|
|
|
|
override val name = "Superoptimizer"
|
|
|
|
def viewCode(code: List[AssemblyLine]): CodeView = {
|
|
CodeView(code.map(l => l.opcode -> l.addrMode))
|
|
}
|
|
}
|
|
|
|
case class CodeView(content: List[(Opcode.Value, AddrMode.Value)])
|