JVM_IR simplify null check on trivially initialized vals only

This commit is contained in:
Dmitry Petrov
2021-10-01 11:17:16 +03:00
committed by TeamCityServer
parent ae1288948a
commit aea2db97c5
17 changed files with 73 additions and 10 deletions
@@ -39842,6 +39842,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@Test
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@Test
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isTrivial
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
@@ -83,6 +84,7 @@ class JvmSafeCallChainFoldingLowering(val context: JvmBackendContext) : FileLowe
// c
// }
// which can be further simplified depending on the nullability of subexpressions in 'a?.foo() ?: b?.bar()?.qux() ?: c'.
// We should perform such simplification carefully, since a value of a non-null type can be uninitialized at runtime.
// In bytecode this produces a chain of temporary STORE-LOAD and IFNULL checks that can be optimized to a compact sequence
// of stack operations and IFNULL checks.
@@ -119,7 +121,7 @@ class JvmSafeCallChainFoldingLowering(val context: JvmBackendContext) : FileLowe
IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, false)
private fun irValNotNull(startOffset: Int, endOffset: Int, irVariable: IrVariable): IrExpression =
if (irVariable.type.isJvmNullable())
if (irVariable.type.isJvmNullable() || irVariable.initializer?.isTrivial() != true)
IrGetValueImpl(startOffset, endOffset, irVariable.symbol).irEqEqNull().irNot()
else
irTrue(startOffset, endOffset)
@@ -0,0 +1,18 @@
abstract class Base() {
init {
foo()
}
abstract fun foo()
}
class Derived(val x: String) : Base() {
override fun foo() {
x?.length
}
}
fun box(): String {
Derived("")
return "OK"
}
@@ -14,5 +14,5 @@ class A(val x: String) {
// JVM_IR_TEMPLATES
// 4 IFNULL
// 0 IFNONNULL
// 2 IFNONNULL
// 0 ACONST_NULL
@@ -6,8 +6,8 @@ fun test(na: A?) =
na?.b?.c?.s
// JVM_IR_TEMPLATES
// 1 DUP
// 1 IFNULL
// 3 DUP
// 3 IFNULL
// 0 IFNONNULL
// 1 ACONST_NULL
@@ -6,6 +6,6 @@ fun test(an: A?) = an?.b?.c?.s
// JVM_IR_TEMPLATES
// 0 ASTORE
// 1 IFNULL
// 3 IFNULL
// 0 IFNONNULL
// 1 ACONST_NULL
@@ -13,5 +13,5 @@ object Host {
// JVM_IR_TEMPLATES
// 0 ASTORE
// 1 ACONST_NULL
// 1 IFNULL
// 3 IFNULL
// 0 IFNONNULL
@@ -17,5 +17,5 @@ fun test(an: A?) = an?.b?.c?.s
// JVM_IR_TEMPLATES
// 0 ASTORE
// 1 ACONST_NULL
// 1 IFNULL
// 3 IFNULL
// 0 IFNONNULL
@@ -3,7 +3,7 @@ fun test(a: Any?, b: Any?, c: String) =
// JVM_IR_TEMPLATES
// 2 IFNULL
// 0 IFNONNULL
// 1 IFNONNULL
// 0 ACONST_NULL
// JVM_TEMPLATES
@@ -9,8 +9,8 @@ fun test(a: Any?) =
// 0 valueOf
// JVM_IR_TEMPLATES
// 1 DUP
// 1 IFNULL
// 2 DUP
// 2 IFNULL
// 0 ACONST_NULL
// 0 IFNONNULL
@@ -39686,6 +39686,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@Test
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@Test
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
@@ -39842,6 +39842,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@Test
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@Test
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
@@ -31768,6 +31768,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallNotEqPrimitive.kt");
@@ -26918,6 +26918,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallNotEqPrimitive.kt");
@@ -26324,6 +26324,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallNotEqPrimitive.kt");
@@ -26249,6 +26249,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallNotEqPrimitive.kt");
@@ -15618,6 +15618,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/safeCall/safeCallEqPrimitive.kt");
}
@TestMetadata("safeCallIOnUninitializedNonNullValue.kt")
public void testSafeCallIOnUninitializedNonNullValue() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallIOnUninitializedNonNullValue.kt");
}
@TestMetadata("safeCallNotEqPrimitive.kt")
public void testSafeCallNotEqPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/safeCall/safeCallNotEqPrimitive.kt");