JVM remove dead code during constant condition elimination

This avoids an extra call to 'analyze', which is rather costly.

Update debugger testData: Constant condition
elimination now performs DCE more consistently.
This commit is contained in:
Dmitry Petrov
2021-06-01 17:16:27 +03:00
committed by TeamCityServer
parent 1fd94d1bc2
commit 7a43c2de79
18 changed files with 357 additions and 13 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -31,12 +32,10 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
private val deadCodeElimination = DeadCodeEliminationMethodTransformer()
override fun transform(internalClassName: String, methodNode: MethodNode) {
do {
val changes = ConstantConditionsOptimization(internalClassName, methodNode).run()
if (changes) deadCodeElimination.transform(internalClassName, methodNode)
} while (changes)
}
@@ -49,11 +48,21 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
private fun collectRewriteActions(): List<() -> Unit> =
arrayListOf<() -> Unit>().also { actions ->
val deadCode = ArrayList<AbstractInsnNode>()
val frames = analyze(internalClassName, methodNode, ConstantPropagationInterpreter())
val insns = methodNode.instructions.toArray()
for (i in frames.indices) {
val frame = frames[i] ?: continue
val insn = insns[i] as? JumpInsnNode ?: continue
val insn = insns[i]
val frame = frames[i]
if (frame == null && insn !is LabelNode) {
deadCode.add(insn)
continue
}
if (insn !is JumpInsnNode) continue
when (insn.opcode) {
in Opcodes.IFEQ..Opcodes.IFLE ->
tryRewriteComparisonWithZero(insn, frame, actions)
@@ -61,6 +70,12 @@ class ConstantConditionEliminationMethodTransformer : MethodTransformer() {
tryRewriteBinaryComparison(insn, frame, actions)
}
}
if (deadCode.isNotEmpty()) {
actions.add {
methodNode.instructions.removeAll(deadCode)
}
}
}
private fun tryRewriteComparisonWithZero(insn: JumpInsnNode, frame: Frame<BasicValue>, actions: ArrayList<() -> Unit>) {
@@ -8028,12 +8028,30 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@Test
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@Test
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@Test
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@Test
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@Test
@TestMetadata("tryFinallyGeneric.kt")
public void testTryFinallyGeneric() throws Exception {
@@ -0,0 +1,68 @@
// IGNORE_BACKEND: WASM
var log = ""
fun foo() {
try {
log += "1"
mightThrow()
log += "2"
} catch (e: Throwable) {
log += "3"
return
}
val t = try {
log += "4"
mightThrow2()
log += "5"
} catch (e: Throwable) {
log += "6"
return
}
val x = try {
log += "7"
mightThrow3()
log += "8"
} catch (e: Throwable) {
log += "9"
return
}
}
var throw1 = false
var throw2 = false
var throw3 = false
fun mightThrow() {
if (throw1) throw Exception()
}
fun mightThrow2() {
if (throw2) throw Exception()
}
fun mightThrow3(): Int {
if (throw3) throw Exception()
return 42
}
fun box(): String {
log += "a"
foo()
throw3 = true
log += " b"
foo()
throw2 = true
log += " c"
foo()
throw1 = true
log += " d"
foo()
if (log != "a124578 b124579 c1246 d13")
return "Failed: $log"
return "OK"
}
@@ -0,0 +1,54 @@
// IGNORE_BACKEND: WASM
var log = ""
fun foo() {
try {
log += "1"
mightThrow()
log += "2"
} catch (e: Throwable) {
log += "3"
"OK"
} finally {
log += "4"
"FINALLY"
}
val t = try {
log += "5"
mightThrow2()
log += "6"
} catch (e: Throwable) {
log += "7"
"OK2"
} finally {
log += "8"
"FINALLY2"
}
}
var throw1 = false
var throw2 = false
fun mightThrow() {
if (throw1) throw Exception()
}
fun mightThrow2() {
if (throw2) throw Exception()
}
fun box(): String {
log += "a"
foo()
throw2 = true
log += " b"
foo()
throw1 = true
log += " c"
foo()
if (log != "a124568 b124578 c134578")
return "Failed: $log"
return "OK"
}
@@ -0,0 +1,56 @@
// IGNORE_BACKEND: WASM
var log = ""
fun foo() {
try {
log += "1"
mightThrow()
log += "2"
} finally {
log += "3"
"FINALLY"
}
val t = try {
log += "4"
mightThrow2()
log += "5"
} finally {
log += "6"
"FINALLY2"
}
}
var throw1 = false
var throw2 = false
fun mightThrow() {
if (throw1) throw Exception()
}
fun mightThrow2() {
if (throw2) throw Exception()
}
fun test() {
log += "a"
foo()
throw2 = true
log += " b"
foo()
// Never gets here.
throw1 = true
log += " c"
foo()
}
fun box(): String {
try {
test()
} catch (e: Exception) {}
if (log != "a123456 b12346")
return "Failed: $log"
return "OK"
}
+1 -2
View File
@@ -16,7 +16,7 @@ fun box(): String {
}
} finally {
return "OK"
} // TODO: why do we go to this line before going to the line above for the finally block.
}
return "FAIL"
}
@@ -33,5 +33,4 @@ fun box(): String {
// test.kt:10 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException
// test.kt:11 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException, y:java.lang.String="y":java.lang.String
// test.kt:14 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException
// test.kt:19 box:
// test.kt:18 box:
+1 -2
View File
@@ -16,7 +16,7 @@ fun box(): String {
}
} finally {
return "OK"
} // TODO: why stop here before the line above for the finally block?
}
return "FAIL"
}
@@ -33,6 +33,5 @@ fun box(): String {
// test.kt:10 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException
// test.kt:11 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException, y:java.lang.String="y":java.lang.String
// test.kt:14 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException
// test.kt:19 box:
// test.kt:18 box:
+12
View File
@@ -59,13 +59,21 @@ fun box() {
// test.kt:32 mightThrow2
// test.kt:33 mightThrow2
// test.kt:11 foo
// LINENUMBERS JVM_IR
// test.kt:10 foo
// LINENUMBERS JVM
// test.kt:13 foo
// LINENUMBERS
// test.kt:16 foo
// test.kt:17 foo
// test.kt:36 mightThrow3
// test.kt:37 mightThrow3
// test.kt:17 foo
// LINENUMBERS JVM_IR
// test.kt:16 foo
// LINENUMBERS JVM
// test.kt:19 foo
// LINENUMBERS
// test.kt:21 foo
// test.kt:42 box
// test.kt:43 box
@@ -79,7 +87,11 @@ fun box() {
// test.kt:32 mightThrow2
// test.kt:33 mightThrow2
// test.kt:11 foo
// LINENUMBERS JVM
// test.kt:13 foo
// LINENUMBERS JVM_IR
// test.kt:10 foo
// LINENUMBERS
// test.kt:16 foo
// test.kt:17 foo
// test.kt:36 mightThrow3
+13 -1
View File
@@ -52,7 +52,11 @@ fun box() {
// test.kt:13 foo
// test.kt:17 foo
// test.kt:18 foo
// LINENUMBERS JVM
// test.kt:17 foo
// LINENUMBERS JVM_IR
// test.kt:12 foo
// LINENUMBERS
// test.kt:19 foo
// test.kt:34 box
// test.kt:35 box
@@ -69,7 +73,11 @@ fun box() {
// test.kt:15 foo
// test.kt:17 foo
// test.kt:18 foo
// LINENUMBERS JVM
// test.kt:17 foo
// LINENUMBERS JVM_IR
// test.kt:12 foo
// LINENUMBERS
// test.kt:19 foo
// test.kt:36 box
// test.kt:37 box
@@ -87,6 +95,10 @@ fun box() {
// test.kt:15 foo
// test.kt:17 foo
// test.kt:18 foo
// LINENUMBERS JVM
// test.kt:17 foo
// LINENUMBERS JVM_IR
// test.kt:12 foo
// LINENUMBERS
// test.kt:19 foo
// test.kt:38 box
// test.kt:38 box
+4
View File
@@ -56,7 +56,11 @@ fun box() {
// LINENUMBERS
// test.kt:13 foo
// test.kt:14 foo
// LINENUMBERS JVM
// test.kt:13 foo
// LINENUMBERS JVM_IR
// test.kt:10 foo
// LINENUMBERS
// test.kt:15 foo
// test.kt:30 box
// test.kt:31 box
@@ -8028,12 +8028,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@Test
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@Test
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@Test
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@Test
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@Test
@TestMetadata("tryFinallyGeneric.kt")
public void testTryFinallyGeneric() throws Exception {
@@ -8028,12 +8028,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@Test
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@Test
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@Test
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@Test
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@Test
@TestMetadata("tryFinallyGeneric.kt")
public void testTryFinallyGeneric() throws Exception {
@@ -6152,11 +6152,26 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@TestMetadata("tryFinallyGeneric.kt")
public void testTryFinallyGeneric() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinallyGeneric.kt");
@@ -5,12 +5,10 @@ stepOverWhenWithInline.kt:5
stepOverWhenWithInline.kt:7
stepOverWhenWithInline.kt:8
stepOverWhenWithInline.kt:9
stepOverWhenWithInline.kt:7
stepOverWhenWithInline.kt:13
stepOverWhenWithInline.kt:14
stepOverWhenWithInline.kt:17
stepOverWhenWithInline.kt:18
stepOverWhenWithInline.kt:13
stepOverWhenWithInline.kt:25
stepOverWhenWithInline.kt:26
stepOverWhenWithInline.kt:27
@@ -26,11 +24,9 @@ stepOverWhenWithInline.kt:52
stepOverWhenWithInline.kt:51
stepOverWhenWithInline.kt:57
stepOverWhenWithInline.kt:58
stepOverWhenWithInline.kt:57
stepOverWhenWithInline.kt:63
stepOverWhenWithInline.kt:64
stepOverWhenWithInline.kt:65
stepOverWhenWithInline.kt:63
stepOverWhenWithInline.kt:75
stepOverWhenWithInline.kt:76
stepOverWhenWithInline.kt:75
@@ -5426,11 +5426,26 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -4832,11 +4832,26 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -4832,11 +4832,26 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@TestMetadata("tryCatchFinallyChain.kt")
public void testTryCatchFinallyChain() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinallyChain.kt");
}
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -3410,6 +3410,21 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
}
@TestMetadata("tryCatchExpression.kt")
public void testTryCatchExpression() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchExpression.kt");
}
@TestMetadata("tryCatchFinally.kt")
public void testTryCatchFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryCatchFinally.kt");
}
@TestMetadata("tryFinally.kt")
public void testTryFinally() throws Exception {
runTest("compiler/testData/codegen/box/controlStructures/tryFinally.kt");
}
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)