JVM_IR: Optimize disjunction condition with intrinsic function call.

This commit is contained in:
Jiaxiang Chen
2019-05-23 13:42:27 -07:00
committed by max-kammerer
parent 6d19eb1853
commit d3cc0e6ce9
6 changed files with 65 additions and 18 deletions
@@ -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)
}
}
@@ -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