JVM_IR: Optimize disjunction condition with intrinsic function call.
This commit is contained in:
committed by
max-kammerer
parent
6d19eb1853
commit
d3cc0e6ce9
+3
-13
@@ -48,8 +48,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
private val KOTLIN_JVM = FqName("kotlin.jvm")
|
||||
private val KOTLIN_JVM_INTERNAL_UNSAFE = FqName("kotlin.jvm.internal.unsafe")
|
||||
|
||||
val andandSymbol = irBuiltIns.run { defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool)) }
|
||||
|
||||
private val intrinsicsMap = (
|
||||
listOf(
|
||||
Key(KOTLIN_JVM, FqName("T"),"<get-javaClass>", emptyList()) to JavaClassProperty,
|
||||
@@ -96,12 +94,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
"clone",
|
||||
emptyList()
|
||||
) to Clone,
|
||||
Key(
|
||||
KOTLIN_INTERNAL_IR,
|
||||
null,
|
||||
OperatorNames.ANDAND,
|
||||
listOf(KotlinBuiltIns.FQ_NAMES._boolean.toSafe(), KotlinBuiltIns.FQ_NAMES._boolean.toSafe())
|
||||
) to AndAnd,
|
||||
irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),
|
||||
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
|
||||
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE),
|
||||
@@ -110,7 +102,9 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
irBuiltIns.enumValueOfSymbol.toKey()!! to IrEnumValueOf,
|
||||
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
||||
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
|
||||
irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE
|
||||
irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE,
|
||||
irBuiltIns.andandSymbol.toKey()!! to AndAnd,
|
||||
irBuiltIns.ororSymbol.toKey()!! to OrOr
|
||||
) +
|
||||
numberConversionMethods() +
|
||||
unaryFunForPrimitives("plus", UnaryPlus) +
|
||||
@@ -226,8 +220,4 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
irFunSymbol.toKey()!! to PrimitiveComparison(type, operator)
|
||||
}
|
||||
}
|
||||
|
||||
private object OperatorNames {
|
||||
const val ANDAND = "ANDAND"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
|
||||
object OrOr : IntrinsicMethod() {
|
||||
|
||||
private class BooleanDisjunction(
|
||||
val arg0: IrExpression, val arg1: IrExpression, val codegen: ExpressionCodegen, val data: BlockInfo) : BooleanValue(codegen.mv) {
|
||||
|
||||
override fun jumpIfFalse(target: Label) {
|
||||
val stayLabel = Label()
|
||||
arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(stayLabel)
|
||||
arg1.accept(codegen, data).coerceToBoolean().jumpIfFalse(target)
|
||||
mv.visitLabel(stayLabel)
|
||||
}
|
||||
|
||||
override fun jumpIfTrue(target: Label) {
|
||||
arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(target)
|
||||
arg1.accept(codegen, data).coerceToBoolean().jumpIfTrue(target)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
|
||||
val (left, right) = expression.receiverAndArgs()
|
||||
return BooleanDisjunction(left, right, codegen, data)
|
||||
}
|
||||
}
|
||||
+23
-3
@@ -114,10 +114,30 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
context.irBuiltIns.booleanType,
|
||||
context.irIntrinsics.andandSymbol
|
||||
context.irBuiltIns.andandSymbol
|
||||
).apply {
|
||||
dispatchReceiver = expression.branches[0].condition
|
||||
putValueArgument(0, expression.branches[0].result)
|
||||
putValueArgument(0, expression.branches[0].condition)
|
||||
putValueArgument(1, expression.branches[0].result)
|
||||
}
|
||||
}
|
||||
if (expression.origin == IrStatementOrigin.OROR) {
|
||||
assert(
|
||||
expression.type.isBoolean()
|
||||
&& expression.branches.size == 2
|
||||
&& expression.branches[0].result.isTrueConst()
|
||||
&& expression.branches[1].condition.isTrueConst()) {
|
||||
"OROR condition should have an 'if a then true' body on its first branch, " +
|
||||
"and an 'if true then b' body on its second branch. " +
|
||||
"Failing expression: ${expression.dump()}"
|
||||
}
|
||||
return IrCallImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
context.irBuiltIns.booleanType,
|
||||
context.irBuiltIns.ororSymbol
|
||||
).apply {
|
||||
putValueArgument(0, expression.branches[0].condition)
|
||||
putValueArgument(1, expression.branches[1].result)
|
||||
}
|
||||
}
|
||||
// If the only condition that is left has a constant true condition remove the
|
||||
|
||||
@@ -216,6 +216,8 @@ class IrBuiltIns(
|
||||
val throwNpeSymbol = defineOperator(OperatorNames.THROW_NPE, nothing, listOf())
|
||||
val throwCceSymbol = defineOperator(OperatorNames.THROW_CCE, nothing, listOf())
|
||||
val throwIseSymbol = defineOperator(OperatorNames.THROW_ISE, nothing, listOf())
|
||||
val andandSymbol = defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool))
|
||||
val ororSymbol = defineOperator(OperatorNames.OROR, bool, listOf(bool, bool))
|
||||
val noWhenBranchMatchedExceptionSymbol = defineOperator(OperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothing, listOf())
|
||||
val illegalArgumentExceptionSymbol = defineOperator(OperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothing, listOf(string))
|
||||
|
||||
@@ -274,5 +276,7 @@ class IrBuiltIns(
|
||||
const val THROW_ISE = "THROW_ISE"
|
||||
const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException"
|
||||
const val ILLEGAL_ARGUMENT_EXCEPTION = "illegalArgumentException"
|
||||
const val ANDAND = "ANDAND"
|
||||
const val OROR = "OROR"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
val a = false
|
||||
val b = false
|
||||
val c = false
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
val a = false
|
||||
val b = false
|
||||
val c = false
|
||||
|
||||
Reference in New Issue
Block a user