[JVM_IR] Extend when to switch translation to deal with nested ors.
FIR translates:
```
when (x) {
1, 2, 3 -> action
else -> other_action
}
```
to an IR structure with nested ors:
```
if ((x == 1 || x == 2) || (x == 3)) action
else other_action
```
This change allows that to turn into switch instructions in the
JVM backend.
This commit is contained in:
committed by
Alexander Udalov
parent
91581d6c1a
commit
05ff2b1292
+6
@@ -5574,6 +5574,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenOr.kt")
|
||||||
|
public void testWhenOr() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/whenOr.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("withoutElse.kt")
|
@TestMetadata("withoutElse.kt")
|
||||||
public void testWithoutElse() throws Exception {
|
public void testWithoutElse() throws Exception {
|
||||||
|
|||||||
+14
-3
@@ -237,11 +237,13 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
|
|||||||
// action
|
// action
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// fir2ir lowers the same to an or sequence:
|
||||||
|
//
|
||||||
|
// if (((subject == a) || (subject == b)) || (subject = c)) action
|
||||||
|
//
|
||||||
// @return true if the conditions are equality checks of constants.
|
// @return true if the conditions are equality checks of constants.
|
||||||
private fun matchConditions(condition: IrExpression): ArrayList<IrCall>? {
|
private fun matchConditions(condition: IrExpression): ArrayList<IrCall>? {
|
||||||
if (condition is IrCall) {
|
if (condition is IrWhen && condition.origin == IrStatementOrigin.WHEN_COMMA) {
|
||||||
return arrayListOf(condition)
|
|
||||||
} else if (condition is IrWhen && condition.origin == IrStatementOrigin.WHEN_COMMA) {
|
|
||||||
assert(condition.type.isBoolean()) { "WHEN_COMMA should always be a Boolean: ${condition.dump()}" }
|
assert(condition.type.isBoolean()) { "WHEN_COMMA should always be a Boolean: ${condition.dump()}" }
|
||||||
|
|
||||||
val candidates = ArrayList<IrCall>()
|
val candidates = ArrayList<IrCall>()
|
||||||
@@ -268,6 +270,15 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (candidates.isNotEmpty()) candidates else return null
|
return if (candidates.isNotEmpty()) candidates else return null
|
||||||
|
} else if (condition is IrCall && condition.symbol == codegen.context.irBuiltIns.ororSymbol) {
|
||||||
|
val candidates = ArrayList<IrCall>()
|
||||||
|
for (i in 0 until condition.valueArgumentsCount) {
|
||||||
|
val argument = condition.getValueArgument(i)!!
|
||||||
|
candidates += matchConditions(argument) ?: return null
|
||||||
|
}
|
||||||
|
return if (candidates.isNotEmpty()) candidates else return null
|
||||||
|
} else if (condition is IrCall) {
|
||||||
|
return arrayListOf(condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun foo(x: Int): Int {
|
fun foo(x: Int): Int {
|
||||||
return when (x) {
|
return when (x) {
|
||||||
1, 1, 2 -> 1001
|
1, 1, 2 -> 1001
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
enum class BigEnum {
|
enum class BigEnum {
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
enum class Season {
|
enum class Season {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
enum class Season {
|
enum class Season {
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
package abc.foo
|
package abc.foo
|
||||||
|
|
||||||
enum class Season {
|
enum class Season {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class Season {
|
enum class Season {
|
||||||
WINTER,
|
WINTER,
|
||||||
SPRING,
|
SPRING,
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// IGNORE_BACKEND: JVM
|
||||||
|
|
||||||
|
fun test(x: Int): String {
|
||||||
|
when {
|
||||||
|
x == 1 || x == 3 || x == 5 -> "135"
|
||||||
|
x == 2 || x == 4 || x == 6 -> "246"
|
||||||
|
else -> "other"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 TABLESWITCH
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
enum class Season {
|
enum class Season {
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
fun foo(x : String) : String {
|
fun foo(x : String) : String {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun foo(x : String) : String {
|
fun foo(x : String) : String {
|
||||||
return when (x) {
|
return when (x) {
|
||||||
"abc", "cde" -> "abc_cde"
|
"abc", "cde" -> "abc_cde"
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
const val y = "cde"
|
const val y = "cde"
|
||||||
|
|
||||||
fun foo(x : String) : String {
|
fun foo(x : String) : String {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun foo1(x : String?) : String {
|
fun foo1(x : String?) : String {
|
||||||
when (x) {
|
when (x) {
|
||||||
"abc", "cde" -> return "abc_cde"
|
"abc", "cde" -> return "abc_cde"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun foo(x : String) : String {
|
fun foo(x : String) : String {
|
||||||
assert("abz]".hashCode() == "aby|".hashCode())
|
assert("abz]".hashCode() == "aby|".hashCode())
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun foo1(x : String) : String {
|
fun foo1(x : String) : String {
|
||||||
when (x) {
|
when (x) {
|
||||||
"abc", "cde" -> return "abc_cde"
|
"abc", "cde" -> return "abc_cde"
|
||||||
|
|||||||
+6
@@ -5442,6 +5442,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenOr.kt")
|
||||||
|
public void testWhenOr() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/whenOr.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("withoutElse.kt")
|
@TestMetadata("withoutElse.kt")
|
||||||
public void testWithoutElse() throws Exception {
|
public void testWithoutElse() throws Exception {
|
||||||
|
|||||||
+6
@@ -5574,6 +5574,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("whenOr.kt")
|
||||||
|
public void testWhenOr() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/whenOr.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("withoutElse.kt")
|
@TestMetadata("withoutElse.kt")
|
||||||
public void testWithoutElse() throws Exception {
|
public void testWithoutElse() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user