Optimize constant conditions

Using basic constant propagation (only integer constants, no arithmetic
calculations), rewrite conditional jump instructions with constant
arguments.

This covers problem description in KT-17007.
Note that it also works transparently with inline functions.
Partial evaluation is required to cover more "advanced" cases.

As a side effect, this also covers KT-3098:
rewrite IF_ICMP<cmp_op>(x, 0) to IF<cmp0_op>(x).
This commit is contained in:
Dmitry Petrov
2017-05-12 15:22:52 +03:00
parent 495fba43c0
commit 2051355d6a
8 changed files with 372 additions and 6 deletions
@@ -0,0 +1,25 @@
// FILE: util.kt
inline fun ieq(x: Int, y: Int) = x == y
inline fun ine(x: Int, y: Int) = x != y
inline fun ilt(x: Int, y: Int) = x < y
inline fun ile(x: Int, y: Int) = x <= y
inline fun igt(x: Int, y: Int) = x > y
inline fun ige(x: Int, y: Int) = x >= y
// FILE: test.kt
fun testeq(x: Int) = ieq(x, 0)
fun testne(x: Int) = ine(x, 0)
fun testlt(x: Int) = ilt(x, 0)
fun testle(x: Int) = ile(x, 0)
fun testgt(x: Int) = igt(x, 0)
fun testge(x: Int) = ige(x, 0)
// @TestKt.class:
// 0 IF_ICMPEQ
// 0 IF_ICMPNE
// 0 IF_ICMPGE
// 0 IF_ICMPGT
// 0 IF_ICMPLE
// 0 IF_ICMPLT
@@ -0,0 +1,35 @@
// FILE: util.kt
const val FLAG = true
const val OTHER_FLAG = false
fun doStuff1() {}
fun doStuff2() {}
fun doStuff3() {}
inline fun doStuff1IfTrue(flag: Boolean) {
if (flag) doStuff1()
}
inline fun doStuff2IfFalse(flag: Boolean) {
if (!flag) doStuff2()
}
inline fun doStuff3IfComplex(flag: Boolean) {
if (flag && !OTHER_FLAG) doStuff3()
}
// FILE: test.kt
fun test() {
doStuff1IfTrue(FLAG)
doStuff2IfFalse(FLAG)
doStuff3IfComplex(FLAG)
}
// @TestKt.class:
// 0 FLAG
// 1 INVOKESTATIC UtilKt.doStuff1
// 0 INVOKESTATIC UtilKt.doStuff2
// 1 INVOKESTATIC UtilKt.doStuff3
// 0 ILOAD 0
// 0 IFEQ
// 0 IFNE
@@ -0,0 +1,58 @@
// FILE: util.kt
const val MAGIC = 42
fun doStuffEq() {}
fun doStuffNotEq() {}
fun doStuffLt() {}
fun doStuffLe() {}
fun doStuffGt() {}
fun doStuffGe() {}
inline fun doStuffIfEq(i: Int) {
if (i == MAGIC) doStuffEq()
}
inline fun doStuffIfNotEq(i: Int) {
if (i != MAGIC) doStuffNotEq()
}
inline fun doStuffIfLt(i: Int) {
if (i < MAGIC) doStuffLt()
}
inline fun doStuffIfLe(i: Int) {
if (i <= MAGIC) doStuffLe()
}
inline fun doStuffIfGt(i: Int) {
if (i > MAGIC) doStuffGt()
}
inline fun doStuffIfGe(i: Int) {
if (i >= MAGIC) doStuffGe()
}
// FILE: test.kt
fun test() {
doStuffIfEq(100)
doStuffIfNotEq(100)
doStuffIfLt(100)
doStuffIfLe(100)
doStuffIfGt(100)
doStuffIfGe(100)
}
// @TestKt.class:
// 0 INVOKESTATIC UtilKt.doStuffEq
// 1 INVOKESTATIC UtilKt.doStuffNotEq
// 0 INVOKESTATIC UtilKt.doStuffLt
// 0 INVOKESTATIC UtilKt.doStuffLe
// 1 INVOKESTATIC UtilKt.doStuffGt
// 1 INVOKESTATIC UtilKt.doStuffGe
// 0 ILOAD 0
// 0 IFEQ
// 0 IFNE
// 0 IFLT
// 0 IFLE
// 0 IFGE
// 0 IFGT
@@ -0,0 +1,9 @@
fun testLt(x: String, y: String) = x < y
fun testLe(x: String, y: String) = x <= y
fun testGt(x: String, y: String) = x > y
fun testGe(x: String, y: String) = x >= y
// 0 IF_ICMPGE
// 0 IF_ICMPGT
// 0 IF_ICMPLE
// 0 IF_ICMPLT