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

dotty.tools.dotc.transform.localopt.InlineLabelsCalledOnce.scala Maven / Gradle / Ivy

package dotty.tools.dotc
package transform.localopt

import core.Contexts.Context
import core.Symbols._
import core.Flags._
import transform.SymUtils._
import scala.collection.mutable
import config.Printers.simplify

/** Inlines LabelDef which are used exactly once.
 *
 *  @author DarkDimius, OlivierBlanvillain
 */
class InlineLabelsCalledOnce extends Optimisation {
  import ast.tpd._

  val timesUsed = newMutableSymbolMap[Int]
  val defined   = newMutableSymbolMap[DefDef]

  def clear(): Unit = {
    timesUsed.clear()
    defined.clear()
  }

  def visitor(implicit ctx: Context): Tree => Unit = {
    case d: DefDef if d.symbol.is(Label)  =>
      var isRecursive = false
      d.rhs.foreachSubTree { x =>
        if (x.symbol == d.symbol)
          isRecursive = true
      }
      if (!isRecursive)
        defined.update(d.symbol, d)

    case t: Apply if t.symbol.is(Label) =>
      val b4 = timesUsed.getOrElseUpdate(t.symbol, 0)
      timesUsed.update(t.symbol, b4 + 1)

    case _ =>
  }

  def transformer(implicit ctx: Context): Tree => Tree = {
    case a: Apply =>
      defined.get(a.symbol) match {
        case Some(defDef) if usedOnce(a) && a.symbol.info.paramInfoss == List(Nil) =>
          simplify.println(s"Inlining labeldef ${defDef.name}")
          defDef.rhs.changeOwner(defDef.symbol, ctx.owner)

        case Some(defDef) if defDef.rhs.isInstanceOf[Literal] =>
          defDef.rhs

        case _ => a
      }

    case d: DefDef if usedOnce(d) =>
      simplify.println(s"Dropping labeldef (used once) ${d.name} ${timesUsed.get(d.symbol)}")
      defined.update(d.symbol, d)
      EmptyTree

    case d: DefDef if neverUsed(d) =>
      simplify.println(s"Dropping labeldef (never used) ${d.name} ${timesUsed.get(d.symbol)}")
      EmptyTree

    case t => t
  }

  def usedN(t: Tree, n: Int)(implicit ctx: Context): Boolean =
    t.symbol.is(Label)                    &&
    timesUsed.getOrElse(t.symbol, 0) == n &&
    defined.contains(t.symbol)

  def usedOnce(t: Tree)(implicit ctx: Context): Boolean  = usedN(t, 1)
  def neverUsed(t: Tree)(implicit ctx: Context): Boolean = usedN(t, 0)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy