when: emit lookupswitch/tableswitch if possible

A lookupswitch or tableswitch can be used if all conditions are equality
checks to constants. To be more specific, it can be done if:
  1. All conditions are CALL 'EQEQ(Any?, Any?)': Boolean
  2. All types of variables involved in comparison are in the same group
     of Char/Byte/Short/Int, String or enum.
  3. All arg0 refer to the same value.
  4. All arg1 are IrConst<*>.

Change-Id: Ifd7cb618395f6c5cc64601018b446f0bb7f5891c
This commit is contained in:
Ting-Yuan Huang
2019-02-18 01:48:54 -08:00
committed by max-kammerer
parent f5d0a38629
commit c1d721a15f
10 changed files with 249 additions and 11 deletions
@@ -186,12 +186,7 @@ abstract class SwitchCodegen(
val minValue = keys.first()
val rangeLength = maxValue.toLong() - minValue.toLong() + 1L
// In modern JVM implementations it shouldn't matter very much for runtime performance
// whether to choose lookupswitch or tableswitch.
// The only metric that really matters is bytecode size and here we can estimate:
// - lookupswitch: ~ 2 * labelsNumber
// - tableswitch: ~ rangeLength
if (rangeLength > 2L * labelsNumber || rangeLength > Int.MAX_VALUE) {
if (preferLookupOverSwitch(labelsNumber, rangeLength)) {
val labels = transitionsTable.values.toTypedArray()
v.lookupswitch(defaultLabel, keys, labels)
return
@@ -219,4 +214,13 @@ abstract class SwitchCodegen(
}
}
}
companion object {
// In modern JVM implementations it shouldn't matter very much for runtime performance
// whether to choose lookupswitch or tableswitch.
// The only metric that really matters is bytecode size and here we can estimate:
// - lookupswitch: ~ 2 * labelsNumber
// - tableswitch: ~ rangeLength
fun preferLookupOverSwitch(labelsNumber: Int, rangeLength: Long) = rangeLength > 2L * labelsNumber || rangeLength > Int.MAX_VALUE
}
}