[KT-79276] fix(irValNotNull): prevent null check compiler crashes
diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt
index ab3196d..efa5c70 100644
--- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt
+++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSafeCallChainFoldingLowering.kt
@@ -118,10 +118,8 @@
         IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, false)
 
     private fun irValNotNull(startOffset: Int, endOffset: Int, irVariable: IrVariable): IrExpression =
-        if (irVariable.type.isJvmNullable() || irVariable.initializer?.isConstantLike != true)
-            IrGetValueImpl(startOffset, endOffset, irVariable.symbol).irEqEqNull().irNot()
-        else
-            irTrue(startOffset, endOffset)
+        // Always generate a null check for safe calls to ensure bytecode is verifiable by D8/R8
+        IrGetValueImpl(startOffset, endOffset, irVariable.symbol).irEqEqNull().irNot()
 
     private fun IrType.isJvmNullable(): Boolean =
         isNullable() || hasAnnotation(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION)
diff --git a/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt b/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt
new file mode 100644
index 0000000..340e80a
--- /dev/null
+++ b/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt
@@ -0,0 +1,44 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+
+class Container {
+    val d: String = "OK"
+}
+
+class Wrapper {
+    var container: Container? = null
+}
+
+fun getWrapper(flag: Boolean): Wrapper? {
+    return if (flag) Wrapper() else null
+}
+
+fun box(): String {
+    // Create a potentially null wrapper
+    val wrapper = getWrapper(true)
+    
+    // Access container which is initially null
+    val container = wrapper?.container
+    
+    // Try to access field 'd' on the null container
+    // This should be safe in Kotlin due to null safety, but might generate problematic bytecode
+    val result = container?.d
+    
+    // Use a more complex pattern with lambdas and control flow
+    val complexResult = wrapper?.let { w ->
+        w.container?.let { c ->
+            c.d
+        }
+    }
+    
+    // Try with nested null checks and assignments
+    if (wrapper != null) {
+        wrapper.container = Container()
+        val c = wrapper.container
+        if (c != null) {
+            return c.d
+        }
+    }
+    
+    return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/d8/nullCheckIssue.kt b/compiler/testData/codegen/box/d8/nullCheckIssue.kt
new file mode 100644
index 0000000..eeca241
--- /dev/null
+++ b/compiler/testData/codegen/box/d8/nullCheckIssue.kt
@@ -0,0 +1,50 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+
+class Container {
+    val d: String = "OK"
+}
+
+// This function returns a nullable Container, but its return type is not explicitly marked as nullable
+// This might cause isJvmNullable() to return false for the return type
+fun getContainer(): Container {
+    return if (System.currentTimeMillis() > 0) Container() else null as Container
+}
+
+// This function returns a constant-like expression that might be null
+// This might cause isConstantLike to return true for an expression that can be null
+fun getConstantLikeContainer(): Container? {
+    val x: Any? = null
+    return x as? Container
+}
+
+fun box(): String {
+    // Test case 1: Safe call on a value that might be null but whose type is not explicitly marked as nullable
+    val container1 = getContainer()
+    val result1 = try {
+        container1?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    // Test case 2: Safe call on a constant-like expression that might be null
+    val container2 = getConstantLikeContainer()
+    val result2 = try {
+        container2?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    // Test case 3: Chained safe calls with a mix of nullable and non-nullable types
+    val container3: Container? = if (System.currentTimeMillis() > 0) null else Container()
+    val wrapper = object {
+        val container: Container? = container3
+    }
+    val result3 = try {
+        wrapper?.container?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/d8/nullFieldAccess.kt b/compiler/testData/codegen/box/d8/nullFieldAccess.kt
new file mode 100644
index 0000000..e5c5978
--- /dev/null
+++ b/compiler/testData/codegen/box/d8/nullFieldAccess.kt
@@ -0,0 +1,23 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+
+class Container {
+    val d: String = "OK"
+}
+
+fun getContainer(flag: Boolean): Container? {
+    return if (flag) Container() else null
+}
+
+fun box(): String {
+    // This should trigger a null check before accessing field 'd'
+    val container = getContainer(false)
+    
+    // Try to access field 'd' on potentially null container
+    // This should be safe in Kotlin due to null safety, but might generate problematic bytecode
+    return try {
+        container?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+}
\ No newline at end of file
diff --git a/proj/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt b/proj/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt
new file mode 100644
index 0000000..340e80a
--- /dev/null
+++ b/proj/compiler/testData/codegen/box/d8/complexNullFieldAccess.kt
@@ -0,0 +1,44 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+
+class Container {
+    val d: String = "OK"
+}
+
+class Wrapper {
+    var container: Container? = null
+}
+
+fun getWrapper(flag: Boolean): Wrapper? {
+    return if (flag) Wrapper() else null
+}
+
+fun box(): String {
+    // Create a potentially null wrapper
+    val wrapper = getWrapper(true)
+    
+    // Access container which is initially null
+    val container = wrapper?.container
+    
+    // Try to access field 'd' on the null container
+    // This should be safe in Kotlin due to null safety, but might generate problematic bytecode
+    val result = container?.d
+    
+    // Use a more complex pattern with lambdas and control flow
+    val complexResult = wrapper?.let { w ->
+        w.container?.let { c ->
+            c.d
+        }
+    }
+    
+    // Try with nested null checks and assignments
+    if (wrapper != null) {
+        wrapper.container = Container()
+        val c = wrapper.container
+        if (c != null) {
+            return c.d
+        }
+    }
+    
+    return "OK"
+}
\ No newline at end of file
diff --git a/proj/compiler/testData/codegen/box/d8/nullCheckIssue.kt b/proj/compiler/testData/codegen/box/d8/nullCheckIssue.kt
new file mode 100644
index 0000000..eeca241
--- /dev/null
+++ b/proj/compiler/testData/codegen/box/d8/nullCheckIssue.kt
@@ -0,0 +1,50 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+
+class Container {
+    val d: String = "OK"
+}
+
+// This function returns a nullable Container, but its return type is not explicitly marked as nullable
+// This might cause isJvmNullable() to return false for the return type
+fun getContainer(): Container {
+    return if (System.currentTimeMillis() > 0) Container() else null as Container
+}
+
+// This function returns a constant-like expression that might be null
+// This might cause isConstantLike to return true for an expression that can be null
+fun getConstantLikeContainer(): Container? {
+    val x: Any? = null
+    return x as? Container
+}
+
+fun box(): String {
+    // Test case 1: Safe call on a value that might be null but whose type is not explicitly marked as nullable
+    val container1 = getContainer()
+    val result1 = try {
+        container1?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    // Test case 2: Safe call on a constant-like expression that might be null
+    val container2 = getConstantLikeContainer()
+    val result2 = try {
+        container2?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    // Test case 3: Chained safe calls with a mix of nullable and non-nullable types
+    val container3: Container? = if (System.currentTimeMillis() > 0) null else Container()
+    val wrapper = object {
+        val container: Container? = container3
+    }
+    val result3 = try {
+        wrapper?.container?.d ?: "OK"
+    } catch (e: Exception) {
+        e.toString()
+    }
+    
+    return "OK"
+}
\ No newline at end of file