Skip to content
linker/public
Go to file
Code
This branch is 319 commits ahead, 20365 commits behind lampepfl:master.

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
bin
 
 
 
 
 
 
 
 
out
 
 
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

dotty linker

Join the chat at Join the chat at https://gitter.im/lampepfl/dotty and call for @Darkdimius if you have questions.

This is a modified version of Dotty compiler, that includes optimization phases. Currently included phases are:

  • auto-specialization, enabled by passing -lto:spec or -lto:all flag;
  • rewrite rules, enabled by passing -rewrites.

Rewrite rules

This a mechanism that allows to define custom optimizations alongside with a library. See this illustaration:

import dotty.linker._

@rewrites
object rules{
  // Library authors can define rewrite rules alongside with a library.
  // Rules are applied by a phase that runs after pickler. Thus they do not interact with type checking.
  // Rules can be defined in other compilation units, as they are discovered through TASTY.
  // The following examples are already working in my prototype:

  def isEmpty(x: Seq[Int]) =
    Rewrite(from = x.length == 0,               // linker will look for pattern in `from`, where method arguments are variables to be bound to trees
            to   = x.isEmpty)                   // if the pattern matches, it will rewrite it to `to`, replacing arguments with bound trees

  def twoDropRights(x: List[Int], a: Int, b: Int) =
    Rewrite(from = x.dropRight(a).dropRight(b), // multiple variables can be bound at once
            to   = x.dropRight(a + b))
  
  def bigIntShift(bi: BigInt, a: Int)(implicit evi: Literal[a.type]) =
  Rewrite(from = bi / a,
     to = 
      if (Integer.bitCount(a) == 1) // one of those 2 branches will be eliminated either by Linker or by JIT as dead code
        bi >> java.lang.Integer.numberOfTrailingZeros(a) 
      else bi / a
     )

  def twoFilters(x: List[Int], a: Int => Boolean, b: Int => Boolean)(implicit apure: IsPure[a.type]) =
                                                // implicits can be used to specify additional constraints. 
                                                // my prototype currently supports IsPure and IsLiteral
                                                // IsPure is a tweaked check from tpd.
    Rewrite(from = x.filter(a).filter(b), 
            to   = x.filter(x => a(x) && b(x)))

  def customFancyWarning(x: ParSeq[Int], x: (Int, Int) => Int) =
    Warn(pattern = x.reduceLeft(x)),            // custom warnings are also supported
             msg = “reduceLeft on parallel collection makes no sense”)

  def customFancyError(a: BigInt) =
    Error(pattern = a / 0,                      // custom errors are also supported
              msg =This code is going to fail in runtime“)

  // the following examples are not _yet_ implemented in the prototype.

  def twoFiltersGeneric[T](x: List[T], a: T => Boolean, b: T => Boolean)(implicit apure: IsPure[a.type]) =
                                                // in case method takes type arguments, T becomes a similar type-variable to-be-bound.  
    Rewrite(from = x.filter(a).filter(b), 
            to   = x.filter(x => a(x) && b(x)))

  def metaExample[T](x: List[T])(implicit apure: IsPure[a.type]) =
                                                // in case method takes type arguments, T becomes a similar type-variable to-be-bound.  
    RewriteMeta(from = x.toString, 
            to = meta { /* entry point to interpreted scala-meta macros */})
}

object Test{
  def myPrettyPrint(a: Any): Unit = ()
  def main(args: Array[String]): Unit = {
     List(1,2,3).length == 0                    // will be rewritten to List(1,2,3).isEmpty
     List(1,2,3).drop(1).drop(1)                // will be rewritten to List(1, 2, 3).drop(2)
     List(1,2,3).dropRight(1).dropRight(1)      // will be rewritten to List(1, 2, 3).dropRight(1 + 1)
     List(1,2,3).filter(_ > 2).filter(_ > 1)    // will be rewritten to List(1, 2, 3).filter(x =>  _ > 2 && _ > 1)
     myPrettyPrint(args.length)                 // will be rewritten to println(“args.length” + “ = “ + args.length)
  }
}

Auto specialization

Build a callgraph, sees which specializations are needed and generates only the required ones. Enabled by -lto:spec or -lto:all.

For details, see

Talks:

About

Modified version of dotty suporting language specific and library-specific optimizations

Resources

License

Releases

No releases published

Packages

No packages published
You can’t perform that action at this time.