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 = FqName("kotlin.jvm")
|
||||||
private val KOTLIN_JVM_INTERNAL_UNSAFE = FqName("kotlin.jvm.internal.unsafe")
|
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 = (
|
private val intrinsicsMap = (
|
||||||
listOf(
|
listOf(
|
||||||
Key(KOTLIN_JVM, FqName("T"),"<get-javaClass>", emptyList()) to JavaClassProperty,
|
Key(KOTLIN_JVM, FqName("T"),"<get-javaClass>", emptyList()) to JavaClassProperty,
|
||||||
@@ -96,12 +94,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
"clone",
|
"clone",
|
||||||
emptyList()
|
emptyList()
|
||||||
) to Clone,
|
) 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.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),
|
||||||
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
|
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
|
||||||
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE),
|
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.enumValueOfSymbol.toKey()!! to IrEnumValueOf,
|
||||||
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
||||||
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
|
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() +
|
numberConversionMethods() +
|
||||||
unaryFunForPrimitives("plus", UnaryPlus) +
|
unaryFunForPrimitives("plus", UnaryPlus) +
|
||||||
@@ -226,8 +220,4 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
irFunSymbol.toKey()!! to PrimitiveComparison(type, operator)
|
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.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
context.irBuiltIns.booleanType,
|
context.irBuiltIns.booleanType,
|
||||||
context.irIntrinsics.andandSymbol
|
context.irBuiltIns.andandSymbol
|
||||||
).apply {
|
).apply {
|
||||||
dispatchReceiver = expression.branches[0].condition
|
putValueArgument(0, expression.branches[0].condition)
|
||||||
putValueArgument(0, expression.branches[0].result)
|
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
|
// 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 throwNpeSymbol = defineOperator(OperatorNames.THROW_NPE, nothing, listOf())
|
||||||
val throwCceSymbol = defineOperator(OperatorNames.THROW_CCE, nothing, listOf())
|
val throwCceSymbol = defineOperator(OperatorNames.THROW_CCE, nothing, listOf())
|
||||||
val throwIseSymbol = defineOperator(OperatorNames.THROW_ISE, 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 noWhenBranchMatchedExceptionSymbol = defineOperator(OperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothing, listOf())
|
||||||
val illegalArgumentExceptionSymbol = defineOperator(OperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothing, listOf(string))
|
val illegalArgumentExceptionSymbol = defineOperator(OperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothing, listOf(string))
|
||||||
|
|
||||||
@@ -274,5 +276,7 @@ class IrBuiltIns(
|
|||||||
const val THROW_ISE = "THROW_ISE"
|
const val THROW_ISE = "THROW_ISE"
|
||||||
const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException"
|
const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException"
|
||||||
const val ILLEGAL_ARGUMENT_EXCEPTION = "illegalArgumentException"
|
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 a = false
|
||||||
val b = false
|
val b = false
|
||||||
val c = false
|
val c = false
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
val a = false
|
val a = false
|
||||||
val b = false
|
val b = false
|
||||||
val c = false
|
val c = false
|
||||||
|
|||||||
Reference in New Issue
Block a user