diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2016-02-03 11:43:48 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-02-03 12:04:49 +0100 |
commit | 5ba1063518f1320b1e920b89c1815406df887467 (patch) | |
tree | 66498d18d1b059898bdd5753b21daeab28b89dab /test | |
parent | bbd890bf907c00f17df39eb4bc656b30d4317b9a (diff) | |
download | scala-5ba1063518f1320b1e920b89c1815406df887467.tar.gz scala-5ba1063518f1320b1e920b89c1815406df887467.tar.bz2 scala-5ba1063518f1320b1e920b89c1815406df887467.zip |
Improve simplifyJumps
Improve simplifyJumps to rewrite
IFEQ L4
L5
GOTO L6
to
IFNE L6
L5
This rewrite is only correct if L5 is not the target of any jump
instruction (otherwise, removing the GOTO would change semantics).
Previously we did not do the rewrite if there was any label between
the conditional jump and the goto (like L5). Now we track which labels
are jump targets.
Diffstat (limited to 'test')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala index a685ae7dd5..99acb318de 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -96,10 +96,22 @@ class SimplifyJumpsTest { instructionsFromMethod(method), List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail ) - // no label allowed between begin and rest. if there's another label, then there could be a - // branch that label. eliminating the GOTO would change the behavior. - val nonOptMethod = genMethod()(begin ::: Label(22) :: rest: _*) - assertFalse(LocalOptImpls.simplifyJumps(nonOptMethod)) + // branch over goto is OK even if there's a label in between, if that label is not a jump target + val withNonJumpTargetLabel = genMethod()(begin ::: Label(22) :: rest: _*) + assertTrue(LocalOptImpls.simplifyJumps(withNonJumpTargetLabel)) + assertSameCode( + instructionsFromMethod(withNonJumpTargetLabel), + List(VarOp(ILOAD, 1), Jump(IFLT, Label(3)), Label(22)) ::: rest.tail ) + + // if the Label(22) between IFGE and GOTO is the target of some jump, we cannot rewrite the IFGE + // and remove the GOTO: removing the GOTO would change semantics. However, the jump that targets + // Label(22) will be re-written (jump-chain collapsing), so in a second round, the IFGE is still + // rewritten to IFLT + val twoRounds = genMethod()(List(VarOp(ILOAD, 1), Jump(IFLE, Label(22))) ::: begin ::: Label(22) :: rest: _*) + assertTrue(LocalOptImpls.simplifyJumps(twoRounds)) + assertSameCode( + instructionsFromMethod(twoRounds), + List(VarOp(ILOAD, 1), Jump(IFLE, Label(3)), VarOp(ILOAD, 1), Jump(IFLT, Label(3)), Label(22)) ::: rest.tail ) } @Test @@ -167,6 +179,9 @@ class SimplifyJumpsTest { VarOp(ILOAD, 1), Jump(IFGE, Label(target)), + VarOp(ILOAD, 1), // some code to prevent rewriting the conditional jump + Op(IRETURN), + Label(4), Jump(GOTO, Label(3)), |