diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index eb3dddf10d9..f373df8214e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages import org.jetbrains.kotlin.codegen.inline.TypeParameterMappings import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty +import org.jetbrains.kotlin.codegen.intrinsics.Not import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter @@ -638,13 +639,26 @@ class ExpressionCodegen( private fun genIfWithBranches(branch: IrBranch, data: BlockInfo, type: KotlinType, otherBranches: List): StackValue { val elseLabel = Label() - val condition = branch.condition + var condition = branch.condition val thenBranch = branch.result //TODO don't generate condition for else branch - java verifier fails with empty stack val elseBranch = branch is IrElseBranch if (!elseBranch) { - gen(condition, data) - BranchedValue.condJump(StackValue.onStack(condition.asmType), elseLabel, true, mv) + var jumpIfFalse = true + // TODO: there should be only one representation of the 'not' operator. + if (condition is IrCall && ( + condition.symbol == classCodegen.context.irBuiltIns.booleanNotSymbol || + classCodegen.state.intrinsics.getIntrinsic(condition.symbol.descriptor) is Not + ) + ) { + // Instead of materializing a negated value when used for control flow, flip the branch + // targets instead. This significantly cuts down the amount of branches and loads of + // const_0 and const_1 in the generated java bytecode. + condition = condition.dispatchReceiver ?: condition.getValueArgument(0)!! + jumpIfFalse = false + } + gen(condition, data).put(condition.asmType, mv) + BranchedValue.condJump(StackValue.onStack(condition.asmType), elseLabel, jumpIfFalse, mv) } val end = Label() diff --git a/compiler/testData/codegen/bytecodeText/boxingOptimization/maxMinBy.kt b/compiler/testData/codegen/bytecodeText/boxingOptimization/maxMinBy.kt index bf55f7f6d84..3340e899fb4 100644 --- a/compiler/testData/codegen/bytecodeText/boxingOptimization/maxMinBy.kt +++ b/compiler/testData/codegen/bytecodeText/boxingOptimization/maxMinBy.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JVM_IR // FILE: list.kt val intList = listOf(1, 2, 3) diff --git a/compiler/testData/codegen/bytecodeText/lazyCodegen/negateVar.kt b/compiler/testData/codegen/bytecodeText/lazyCodegen/negateVar.kt index e1b23202b82..67b152b2274 100644 --- a/compiler/testData/codegen/bytecodeText/lazyCodegen/negateVar.kt +++ b/compiler/testData/codegen/bytecodeText/lazyCodegen/negateVar.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR val two = 2 fun test2() {