-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Copy propagation, remove unused values (closures!) and local variables #4837
Conversation
This allows using an AliasingAnalyzer for copy propagation (subsequent commit).
Review by @retronym |
Community build running here: https://scala-ci.typesafe.com/job/scala-2.12.x-integrate-community-build/205/parameters/ |
The community build found some issues, will look at those next week:
also akka and twitter-util failed, the rest passed. |
(the twitter-util failure is unrelated to your changes) |
Previously the VarInstruction extractor did not include IINCs. Also give rename the isVarInstruction predicate to isLoadStoreOrRet, as it doesn't include IINC. Also fixes a bug in removeJumpAndAdjustStack, it checked the wrong opcode range before.
When running DCE, directly remove eliminated callsites from the call graph (instead delegating this task to the callees).
By convention (for performance), `aliasingFrame.aliases(slot) == null` means that the value at `slot` has no aliases, so this is isomorphic to having a singleton `AliasSet(slot)`. When merging an AliasingFrame `other` into `this`, at every value slot we have to keep the intersection of the two alias sets. In other words we have to remove from `this.aliases(slot)` those values that are not in `other.aliases(slot)`. This was wrong for the cases where `other.aliases == null` - we did not treat this case as a singleton set.
Copy propagation uses an AliasingAnalyzer: it replaces a `LOAD n` instruction by `LOAD m` where m is the smallest alias of n. This leads to stale STORE instructions. Stale STOREs are identified using a ProdCons analyzer and replaced by POPs. Values that are pushed on the stack by a side-effect free instruction and consumed by a POP are then removed by `eliminatePushPop`. This includes elimination of unused closure allocations and unused boxes and tuple allocations (*). A final cleanup eliminates `STORE x; LOADx` pairs where the stored value is not otherwise used. Fixes - scala/scala-dev#25 - scala/scala-dev#7 - scala/scala-dev#14 - scala/scala-dev#12 (*) We don't yet rewrite reads of boxes and tuples yet. For example, `val x = (1, 2); x._1` remains a method invocation and the tuple cannot be eliminated (scala/scala-dev#11). Inspired in many ways by Miguel's work!
community build (with the optimizer enabled) succeeded: https://scala-ci.typesafe.com/view/scala-2.12.x/job/scala-2.12.x-integrate-community-build/213/ |
I'll take another pass over this tomorrow. |
closing in favor of #4858 |
See individual commit messages.