@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.IrWhenUtils
9
9
import org.jetbrains.kotlin.codegen.`when`.SwitchCodegen.Companion.preferLookupOverSwitch
10
10
import org.jetbrains.kotlin.ir.expressions.*
11
11
import org.jetbrains.kotlin.ir.types.*
12
+ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
12
13
import org.jetbrains.kotlin.ir.util.hasAnnotation
13
14
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
14
15
import org.jetbrains.org.objectweb.asm.Label
@@ -62,11 +63,13 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
62
63
63
64
val firstCondition = callToLabels[0 ].call
64
65
if (firstCondition.symbol != context.irBuiltIns.eqeqSymbol) return null
65
- val subject = firstCondition.arguments[0 ]
66
+ val subject = firstCondition.arguments[0 ] ? : return null
66
67
return when {
67
68
subject is IrCall && subject.isCoerceFromUIntToInt() ->
68
69
generateUIntSwitch(subject.arguments[0 ]!! as ? IrGetValue , calls, callToLabels, expressionToLabels, elseExpression)
69
- subject is IrGetValue || subject is IrConst && subject.type.isString() -> // also generate tableswitch for literal string subject
70
+ subject is IrGetValue
71
+ || subject is IrConst && subject.type.isString() // also generate tableswitch for literal string subject
72
+ || subject.isByteOrShortToInt() ->
70
73
generatePrimitiveSwitch(subject, calls, callToLabels, expressionToLabels, elseExpression)
71
74
else ->
72
75
null
@@ -111,6 +114,12 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
111
114
)
112
115
}
113
116
117
+ fun IrExpression.isByteOrShortToInt (): Boolean {
118
+ if (this !is IrCall ) return false
119
+ val fqName = symbol.owner.fqNameWhenAvailable?.asString()
120
+ return fqName == " kotlin.Byte.toInt" || fqName == " kotlin.Short.toInt"
121
+ }
122
+
114
123
private fun generatePrimitiveSwitch (
115
124
subject : IrExpression ,
116
125
conditions : List <IrCall >,
@@ -122,7 +131,7 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
122
131
if (! areConstantComparisons(conditions)) return null
123
132
124
133
return when {
125
- subject is IrGetValue && areConstIntComparisons(conditions) -> {
134
+ ( subject is IrGetValue || subject.isByteOrShortToInt()) && areConstIntComparisons(conditions) -> {
126
135
val cases = extractSwitchCasesAndFilterUnreachableLabels(callToLabels, expressionToLabels)
127
136
IntSwitch (
128
137
subject,
@@ -187,8 +196,17 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
187
196
return lhs.all { it != null && it.value == lhs[0 ]!! .value }
188
197
}
189
198
199
+ fun isValidCallToIntLHS (): Boolean {
200
+ val lhs = conditions.map {
201
+ val call = it.takeIf { it.symbol == context.irBuiltIns.eqeqSymbol }?.arguments[0 ] ? : return false
202
+ if (! call.isByteOrShortToInt()) return false
203
+ (call as IrCall ).arguments[0 ] as ? IrGetValue
204
+ }
205
+ return lhs.all { it != null && it.symbol.owner == lhs[0 ]!! .symbol.owner }
206
+ }
207
+
190
208
// All conditions are equality checks && all LHS refer to the same tmp variable.
191
- if (! isValidIrGetValueTypeLHS() && ! isValidIrConstTypeLHS())
209
+ if (! isValidIrGetValueTypeLHS() && ! isValidIrConstTypeLHS() && ! isValidCallToIntLHS() )
192
210
return false
193
211
194
212
// All RHS are constants
@@ -218,7 +236,7 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
218
236
subjectTypePredicate : (IrType ) -> Boolean ,
219
237
irConstPredicate : (IrConst ) -> Boolean
220
238
): Boolean {
221
- val lhs = conditions.map { it.arguments[0 ] as ? IrGetValue ? : it.arguments[0 ] as IrConst }
239
+ val lhs = conditions.map { it.arguments[0 ] as ? IrGetValue ? : it.arguments[0 ] as ? IrConst ? : it.arguments[ 0 ] as IrCall }
222
240
if (lhs.any { ! subjectTypePredicate(it.type) })
223
241
return false
224
242
@@ -314,7 +332,7 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
314
332
}
315
333
316
334
inner class IntSwitch (
317
- subject : IrGetValue ,
335
+ subject : IrExpression ,
318
336
elseExpression : IrExpression ? ,
319
337
expressionToLabels : ArrayList <ExpressionToLabel >,
320
338
private val cases : List <ValueToLabel >
0 commit comments