Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local optimisations round two #2647

Merged
merged 16 commits into from
Jun 14, 2017
Merged

Conversation

OlivierBlanvillain
Copy link
Contributor

Follow up PR of #2513

Objective: bootstrap Dotty with -optimise!


/** Every pure statement preceding a ??? can be removed.
*
* This optimisation makes it rather tricky meaningful examples since the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence seems to be missing some words.

def visitor: Tree => Unit

/** Does the actual Tree => Tree transformation, possibly using a different
* context from the one using in Optimisation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give more explanations on what contexts are used when? Also typo: using -> used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got addressed in this PR, we always use the correct, most local context!

def localOptimizations(classNode: ClassNode): Unit = {
// BackendStats.timed(BackendStats.methodOptTimer)(localOpt.methodOptimizations(classNode))
def localOptimisations(classNode: ClassNode): Unit = {
// BackendStats.timed(BackendStats.methodOptTimer)(localOpt.methodOptimisations(classNode))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose not to rename the method here. This is how method is actually called in the backend.

@DarkDimius
Copy link
Contributor

@OlivierBlanvillain, If you don't mind, I propose to wait with getting this PR in.
I've done quite some changes to Simplify to enable more optimizations and add more documentation.
Would you mind if I take your changes and apply them by hand on my branch?(after my branch passes the tests)

@DarkDimius
Copy link
Contributor

DarkDimius commented Jun 2, 2017

For curiosity I've just checked: Oxford English Dictionary, prefers the -ize. But I don't really care. I'm fine with the change.
More details for curious ones: https://www.quora.com/Is-there-any-difference-between-optimization-and-optimisation/answer/Bob-Crowl

@OlivierBlanvillain
Copy link
Contributor Author

OlivierBlanvillain commented Jun 2, 2017

@DarkDimius How large is your diff? I would be surprise if git manages to rebase either diffs on top of the other, and if it doesn't, it's probably easier to hand apply your changes on top of this rather than the other way around... (Happy to help if you point me to a branch)

I really don't have a preference between -ise and -ize, as long has it's not half/half 😄

@OlivierBlanvillain
Copy link
Contributor Author

@DarkDimius Found the issue with DropNoEffects, if you want to have a look a the last commits. It's currently not tested by the CI, but this is what I use locally:

$ sbt ';project dotty-compiler-bootstrapped ;clean ;set scalacOptions ++= Seq("-optimise", "-Yopt-phases:DropNoEffects") ;test'

@DarkDimius
Copy link
Contributor

@OlivierBlanvillain, nice find! Did tests pass on your machine after the change?

@OlivierBlanvillain
Copy link
Contributor Author

The above, i.e. bootstrapped Dotty tests with -optimise -Yopt-phases:DropNoEffects does. That's a tiny step but I'm confident we can make it work will all optimisations enabled!

@@ -447,6 +448,8 @@ class Definitions {
def Long_* = Long_mulR.symbol
lazy val Long_divR = LongClass.requiredMethodRef(nme.DIV, List(LongType))
def Long_/ = Long_divR.symbol
val CommutativePrimitiveOperations = new PerRun[collection.Set[Symbol]](implicit ctx =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't put stuff inside Definitions, unless its frequently used by multiple phases.

Same applies for SeqFactoryType.

a.symbol.extendedOverriddenSymbols.isEmpty &&
(isPureExpr(a.fun) || a.fun.symbol.is(Synthetic)) =>

def reciever(t: Tree): Type = t match {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: reciever -> receiver

Block(recv :: Nil, res)
}

// To run this optimisation after erasure one would need to specialize it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this comment to the top of the class?

case Some(_) =>
a
}
case a: DefDef if (a.symbol.is(Label) && timesUsed.getOrElse(a.symbol, 0) == 1 && defined.contains(a.symbol)) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This same if expression is repeated below, factor it out in a def?

@DarkDimius
Copy link
Contributor

DarkDimius commented Jun 11, 2017

@OlivierBlanvillain, i've pushed a merge of our changes. I've quite substantially changed the structure of the split, because the original split introduced 70% slowdown(even after removing fuel)
Now, there is only 20% slowdown. I'm still not sure if this split is worth this slowdown. I'd prefer to keep this phase fast, as it has to run multiple times during the pipeline and it should "pay for itself" by speeding up other phases. If this phase becomes 70% slower, it's harder for it to pay for itself.

@smarter
Copy link
Member

smarter commented Jun 11, 2017

What changes in the split cause a slowdown?

@DarkDimius
Copy link
Contributor

50% that I've removed - substantially more allocations. More maps, sets & etc were allocated, unlike before. More lambdas were coined. More calls were non-local and cold. E.g. there were two contexts being used interchangeably.

In general: abstractions in Scala are anything but free. What brings the remaining 20% slowdown - I haven't checked yet and I don't think I'll have opportunity to do it in coming months.

@OlivierBlanvillain
Copy link
Contributor Author

@DarkDimius Interesting, what measure did you use?

@OlivierBlanvillain
Copy link
Contributor Author

OlivierBlanvillain commented Jun 12, 2017

@DarkDimius I just force pushed to restore history, I authored 4 commits under you name, you can check that nothing got lost using git diff a386f63 f8cf56f.

I isolated the CI failure, it looks like compileStdLib compiles forever with -optimise -Yopt-phases:Devalify starting from commit 93e1b6d (Collapse ctx and localCtx together). I guess Devalify really need to run using the context from the overall DefDef tree instead of the local one. Note that before the split, the ctx used by every Visitor/Transformer pair is fixed in the in outer loop, here (which corresponds to the class parameter you instantiated), the localCtx was almost never used before that commit, maybe we should try getting ride of this one instead.

@DarkDimius I think you have mesured the wrong with this 20% slowdown. By not
sharing instances Optimistion instead of allocating new ones you where also
sharing the mutable.Hashmap instances. The failure on compileStdLib is
actaully a proper timeout: keeping these Hashmaps around when compiling all of
stdlib prevented GC from doing it job, and (I'm guessing) spent a lot of time
reshufuling the Hashmap.

I also removed your `private val useFuel = false` back to a simple runtime
setting check. I moved the debuging code in a `printIfDifferent` which only
adds 3 extra bytecode instructions to the body of the TreeMap.transform (going
from 70 to 73).
@OlivierBlanvillain OlivierBlanvillain changed the title [WIP] Local optimisations round two Local optimisations round two Jun 14, 2017
@DarkDimius
Copy link
Contributor

Let's get this in. The followup discussions can be held separately, but this PR in any case is an improvement.

@DarkDimius
Copy link
Contributor

LGTM. Glad to have it in.

@DarkDimius DarkDimius merged commit 2520992 into scala:master Jun 14, 2017
@allanrenucci allanrenucci deleted the localopt-continued branch December 14, 2017 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants