JVM_IR generate less bytecode for for-loops if possible(KT-22334).

This commit is contained in:
Xin Wang
2021-12-28 10:54:01 +08:00
committed by Dmitry Petrov
parent 3b928e1780
commit 9ae452e489
27 changed files with 830 additions and 12 deletions
@@ -10,12 +10,10 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.*
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
import org.jetbrains.kotlin.ir.builders.irInt
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.util.OperatorNameConventions
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
@@ -67,7 +65,46 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
if (preferJavaLikeCounterLoop || this.constLongValue == -1L) return null
}
val irConst = this as? IrConst<*> ?: return null
return when (this) {
is IrConst<*> -> convertIrConst(this)
is IrCall -> convertIrCall(this)
else -> null
}
}
private val allowedMethods = listOf(
"kotlin.ByteArray.<get-size>",
"kotlin.CharArray.<get-size>",
"kotlin.String.<get-length>",
"kotlin.ShortArray.<get-size>",
"kotlin.IntArray.<get-size>",
"kotlin.LongArray.<get-size>",
"kotlin.FloatArray.<get-size>",
"kotlin.DoubleArray.<get-size>",
"kotlin.BooleanArray.<get-size>",
"kotlin.collections.List.<get-size>",
"kotlin.collections.MutableList.<get-size>",
"kotlin.CharSequence.<get-length>",
"kotlin.collections.Set.<get-size>",
"kotlin.collections.MutableSet.<get-size>",
"kotlin.collections.Map.<get-size>",
"kotlin.collections.MutableMap.<get-size>",
)
private fun convertIrCall(irCall: IrCall): IrExpression? {
fun IrCall.dispatchReceiverName() = (dispatchReceiver as? IrCall)?.symbol?.owner?.fqNameWhenAvailable.toString()
return if (irCall.origin == IrStatementOrigin.MINUS
&& (irCall.getValueArgument(0) as? IrConst<*>)?.value == 1
&& irCall.dispatchReceiverName() in allowedMethods // to avoid possible underflow
) irCall.dispatchReceiver
else null
}
private fun convertIrConst(irConst: IrConst<*>): IrExpression? {
val startOffset = irConst.startOffset
val endOffset = irConst.endOffset
val type = irConst.type
return when (irConst.kind) {
IrConstKind.Char -> {
val charValue = IrConstKind.Char.valueOf(irConst)
@@ -108,6 +145,4 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
null
}
}
}