/** * The only change is in the decision to replace a LOAD_LOCAL(l) * in the copy-propagation performed before ClosureElimination. * * In the general case, the local variable 'l' is connected through * an alias chain with other local variables and at the end of the * alias chain there may be a Value, call it 'v'. * * If 'v' is cheaper to access (it is a Deref(This) or Const(_)), then * replace the instruction to load it from the cheaper place. * Otherwise, we use the local variable at the end of the alias chain * instead of 'l'. */ import scala.tools.partest.IcodeComparison object Test extends IcodeComparison { override def printIcodeAfterPhase = "dce" } import scala.util.Random._ /** * The example in the bug report (Issue-5321): an alias chain which store * an Unknown. Should remove local variable 'y'. */ object TestBugReport { def test(x: Int) = { val y = x println(y) } } /** * The code taken from scala.tools.nsc.settings.Settings: * After inlining of the setter is performed, there is an opportunity for * copy-propagation to eliminate some local variables. */ object TestSetterInline { private var _postSetHook: this.type => Unit = (x: this.type) => () def withPostSetHook(f: this.type => Unit): this.type = { _postSetHook = f ; this } } /** * The access of the local variable 'y' should be replaced by the * constant. */ object TestAliasChainConstat { def main(args: Array[String]): Unit = { val x = 2 val y = x println(y) } } /** * At the end of the alias chain we have a reference to 'this'. * The local variables should be all discarded and replace by a * direct reference to this */ class TestAliasChainDerefThis { def main(args: Array[String]): Unit = { val x = this val y = x println(y) } } /** * At the end of the alias chain, there is the value of a field. * The use of variable 'y' should be replaced by 'x', not by an access * to the field 'f' since it is more costly. */ object TestAliasChainDerefField { def f = nextInt def main(args: Array[String]): Unit = { val x = f val y = x println(y) } } /** * The first time 'println' is called, 'x' is replaced by 'y' * and the second time, 'y' is replaced by 'x'. But none of them * can be removed. */ object TestDifferentBindings { def main(args: Array[String]): Unit = { var x = nextInt var y = x println(y) y = nextInt x = y println(x) } }