Don't transform irBranch if tableswitch can't be generated #KT-34466 Fixed
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 8f560a2..56892b4 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java
@@ -48741,6 +48741,18 @@ } @Test + @TestMetadata("notAllConditionsAreEqEqExceptElse.kt") + public void testNotAllConditionsAreEqEqExceptElse() throws Exception { + runTest("compiler/testData/codegen/box/when/enumOptimization/notAllConditionsAreEqEqExceptElse.kt"); + } + + @Test + @TestMetadata("notAllEntriesAreConstants.kt") + public void testNotAllEntriesAreConstants() throws Exception { + runTest("compiler/testData/codegen/box/when/enumOptimization/notAllEntriesAreConstants.kt"); + } + + @Test @TestMetadata("nullIsTheFirstEntry.kt") public void testNullIsTheFirstEntry() throws Exception { runTest("compiler/testData/codegen/box/when/enumOptimization/nullIsTheFirstEntry.kt");
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt index 01cbd42..f432b8f 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt
@@ -73,12 +73,39 @@ } } } - - transformBranches(irWhen, subject, subjectOrdinalProvider) - + if (possibleToGenerateJumpTable(irWhen, subject)) { + transformBranches(irWhen, subject, subjectOrdinalProvider) + } return expression } + private fun possibleToGenerateJumpTable(irWhen: IrWhen, subject: IrVariable): Boolean { + for (irBranch in irWhen.branches) { + val condition = irBranch.condition as? IrCall ?: continue + if (condition.symbol != context.irBuiltIns.eqeqSymbol) + return false + + val lhs = condition.getValueArgument(0)!! + val rhs = condition.getValueArgument(1)!! + val other = getOther(lhs, rhs, subject) + if (other is IrCall) { + return false + } + } + return true + } + + private fun getOther(lhs: IrExpression, rhs: IrExpression, subject: IrVariable): IrExpression? { + return when { + lhs is IrGetValue && lhs.symbol.owner == subject -> + rhs + rhs is IrGetValue && rhs.symbol.owner == subject -> + lhs + else -> + return null + } + } + private fun transformBranches( irWhen: IrWhen, subject: IrVariable, @@ -125,14 +152,7 @@ } val lhs = expression.getValueArgument(0)!! val rhs = expression.getValueArgument(1)!! - val other = when { - lhs is IrGetValue && lhs.symbol.owner == subject -> - rhs - rhs is IrGetValue && rhs.symbol.owner == subject -> - lhs - else -> - return expression - } + val other = getOther(lhs, rhs, subject) ?: return expression val entryOrdinal = when { other is IrGetEnumValue && subject.type.classifierOrNull?.owner == other.symbol.owner.parent -> mapConstEnumEntry(other.symbol.owner)
diff --git a/compiler/testData/codegen/box/when/enumOptimization/notAllConditionsAreEqEqExceptElse.kt b/compiler/testData/codegen/box/when/enumOptimization/notAllConditionsAreEqEqExceptElse.kt new file mode 100644 index 0000000..7976ed6 --- /dev/null +++ b/compiler/testData/codegen/box/when/enumOptimization/notAllConditionsAreEqEqExceptElse.kt
@@ -0,0 +1,25 @@ +// TARGET_BACKEND: JVM_IR +// WITH_STDLIB + +enum class E { + A, B, C, D; +} + +val abc = setOf(E.A, E.B, E.C) + +fun bar(): E = E.A + +fun foo(e: E): String { + val c = when (e) { + E.B -> "B" + in abc -> "OK" + else -> "else" + } + return c +} + +fun box() = foo(bar()) + +// CHECK_BYTECODE_TEXT +// 0 WhenMappings +// 0 TABLESWITCH \ No newline at end of file
diff --git a/compiler/testData/codegen/box/when/enumOptimization/notAllEntriesAreConstants.kt b/compiler/testData/codegen/box/when/enumOptimization/notAllEntriesAreConstants.kt new file mode 100644 index 0000000..ab28ac6 --- /dev/null +++ b/compiler/testData/codegen/box/when/enumOptimization/notAllEntriesAreConstants.kt
@@ -0,0 +1,22 @@ +// TARGET_BACKEND: JVM_IR + +enum class E { + A, B; +} + +fun bar(): E = E.A + +fun foo(e: E): String { + val c = when (e) { + E.B -> "B" + bar() -> "OK" + else -> "else" + } + return c +} + +fun box() = foo(bar()) + +// CHECK_BYTECODE_TEXT +// 0 WhenMappings +// 0 TABLESWITCH \ No newline at end of file
diff --git a/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt b/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt index bfce330..7707e79 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt
@@ -17,3 +17,7 @@ fun box(): String { return test(null) } + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 TABLESWITCH
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 183fc99..a5a0eae 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
@@ -48741,6 +48741,18 @@ } @Test + @TestMetadata("notAllConditionsAreEqEqExceptElse.kt") + public void testNotAllConditionsAreEqEqExceptElse() throws Exception { + runTest("compiler/testData/codegen/box/when/enumOptimization/notAllConditionsAreEqEqExceptElse.kt"); + } + + @Test + @TestMetadata("notAllEntriesAreConstants.kt") + public void testNotAllEntriesAreConstants() throws Exception { + runTest("compiler/testData/codegen/box/when/enumOptimization/notAllEntriesAreConstants.kt"); + } + + @Test @TestMetadata("nullIsTheFirstEntry.kt") public void testNullIsTheFirstEntry() throws Exception { runTest("compiler/testData/codegen/box/when/enumOptimization/nullIsTheFirstEntry.kt");