All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalanative.optimizer.pass.GlobalBoxingElimination.scala Maven / Gradle / Ivy

The newest version!
package scala.scalanative
package optimizer
package pass

import scala.collection.mutable
import nir._, Inst.Let
import analysis.ClassHierarchy.Top
import analysis.DominatorTree
import analysis.ControlFlow

/** Eliminates redundant box/unbox operations within
 *  a single method definition. This is quite simplistic approach
 *  but we need this to remove boxing around pointer operations
 *  that happen to have generic signatures.
 */
class GlobalBoxingElimination extends Pass {
  import GlobalBoxingElimination._

  override def onInsts(insts: Seq[Inst]): Seq[Inst] = {
    val records = mutable.UnrolledBuffer.empty[Record]

    // Setup the dominator tree checks
    val cfg             = ControlFlow.Graph(insts)
    val blockDomination = DominatorTree.build(cfg)

    val localToBlock =
      cfg.all.flatMap { block =>
        val params = block.params.map { local =>
          (local.name, block)
        }
        val insts = block.insts.collect {
          case Let(name, _) => (name, block)
        }
        params ++ insts
      }.toMap

    def isDominatedBy(dominated: Local, dominating: Local): Boolean = {
      val dominatedBlock  = localToBlock(dominated)
      val dominatingBlock = localToBlock(dominating)
      blockDomination(dominatedBlock).contains(dominatingBlock)
    }

    def canReuse(target: Local, reusedVal: Val): Boolean = {
      reusedVal match {
        case Val.Local(reusedLocal, _) => isDominatedBy(target, reusedLocal)
        case _                         => false
      }
    }

    // Original box elimination code
    insts.map {
      case inst @ Let(to, op @ Op.Box(ty, from)) =>
        records
          .collectFirst {
            // if a box for given value already exists, re-use the box
            case Box(rty, rfrom, rto)
                if rty == ty && from == rfrom && canReuse(to, rto) =>
              Let(to, Op.Copy(rto))

            // if we re-box previously unboxed value, re-use the original box
            case Unbox(rty, rfrom, rto)
                if rty == ty && from == rto && canReuse(to, rfrom) =>
              Let(to, Op.Copy(rfrom))
          }
          .getOrElse {
            // otherwise do actual boxing
            records += Box(ty, from, Val.Local(to, op.resty))
            inst
          }

      case inst @ Let(to, op @ Op.Unbox(ty, from)) =>
        records
          .collectFirst {
            // if we unbox previously boxed value, return original value
            case Box(rty, rfrom, rto)
                if rty == ty && from == rto && canReuse(to, rfrom) =>
              Let(to, Op.Copy(rfrom))

            // if an unbox for this value already exists, re-use unbox
            case Unbox(rty, rfrom, rto)
                if rty == ty && from == rfrom && canReuse(to, rto) =>
              Let(to, Op.Copy(rto))
          }
          .getOrElse {
            // otherwise do actual unboxing
            records += Unbox(ty, from, Val.Local(to, op.resty))
            inst
          }

      case inst =>
        inst
    }
  }
}

object GlobalBoxingElimination extends PassCompanion {
  private sealed abstract class Record
  private final case class Box(ty: Type, from: nir.Val, to: nir.Val)
      extends Record
  private final case class Unbox(ty: Type, from: nir.Val, to: nir.Val)
      extends Record

  override def apply(config: tools.Config, top: Top) =
    new GlobalBoxingElimination
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy