JVM_IR configure loop shape in the backend context
This commit is contained in:
committed by
teamcityserver
parent
38d6c8ded0
commit
b93dff003f
+3
@@ -50,4 +50,7 @@ interface CommonBackendContext : BackendContext, LoggingContext {
|
||||
fun isSideEffectFree(call: IrCall): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
val preferJavaLikeCounterLoop: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
+3
-1
@@ -252,6 +252,8 @@ class ProgressionLoopHeader(
|
||||
context: CommonBackendContext
|
||||
) : NumericForLoopHeader<ProgressionHeaderInfo>(headerInfo, builder, context) {
|
||||
|
||||
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||
|
||||
// For this loop:
|
||||
//
|
||||
// for (i in first()..last() step step())
|
||||
@@ -331,7 +333,7 @@ class ProgressionLoopHeader(
|
||||
|
||||
val loopCondition = buildLoopCondition(this@with)
|
||||
LoopReplacement(newLoop, irIfThen(loopCondition, newLoop))
|
||||
} else if (!headerInfo.isLastInclusive) {
|
||||
} else if (preferJavaLikeCounterLoop && !headerInfo.isLastInclusive) {
|
||||
// It is critically important for loop code performance on JVM to "look like" a simple counter loop in Java when possible
|
||||
// (`for (int i = first; i < lastExclusive; ++i) { ... }`).
|
||||
// Otherwise loop-related optimizations will not kick in, resulting in significant performance degradation.
|
||||
|
||||
+23
-5
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irInt
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
@@ -23,21 +24,38 @@ import org.jetbrains.kotlin.name.FqName
|
||||
internal abstract class IndicesHandler(protected val context: CommonBackendContext) :
|
||||
ProgressionHandler {
|
||||
|
||||
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||
|
||||
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
|
||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
||||
// `last = array.size - 1` (last is inclusive) for the loop `for (i in array.indices)`.
|
||||
val last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter)
|
||||
.apply { dispatchReceiver = expression.extensionReceiver!! }
|
||||
val last: IrExpression
|
||||
val lastInclusive: IrExpression?
|
||||
val isLastInclusive: Boolean
|
||||
|
||||
if (preferJavaLikeCounterLoop) {
|
||||
// Convert range with inclusive upper bound to exclusive upper bound if possible.
|
||||
// This affects loop code performance on JVM.
|
||||
last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter)
|
||||
.apply { dispatchReceiver = expression.extensionReceiver!! }
|
||||
lastInclusive = last.decrement()
|
||||
isLastInclusive = false
|
||||
} else {
|
||||
last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter)
|
||||
.apply { dispatchReceiver = expression.extensionReceiver!! }
|
||||
.decrement()
|
||||
lastInclusive = null
|
||||
isLastInclusive = true
|
||||
}
|
||||
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
first = irInt(0),
|
||||
last = last,
|
||||
step = irInt(1),
|
||||
isLastInclusive = false,
|
||||
isLastInclusive = isLastInclusive,
|
||||
canOverflow = false,
|
||||
direction = ProgressionDirection.INCREASING,
|
||||
originalLastInclusive = last.decrement()
|
||||
originalLastInclusive = lastInclusive
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
internal class RangeToHandler(private val context: CommonBackendContext) :
|
||||
ProgressionHandler {
|
||||
|
||||
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||
|
||||
private val progressionElementTypes = context.ir.symbols.progressionElementTypes
|
||||
|
||||
override val matcher = SimpleCalleeMatcher {
|
||||
@@ -39,9 +41,9 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
|
||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
||||
val last = expression.getValueArgument(0)!!
|
||||
|
||||
// Convert range with inclusive upper bound to exclusive upper bound if possible.
|
||||
// This affects loop code performance on JVM.
|
||||
if (canUseExclusiveUpperBound(last, data)) {
|
||||
if (preferJavaLikeCounterLoop && canUseExclusiveUpperBound(last, data)) {
|
||||
// Convert range with inclusive upper bound to exclusive upper bound if possible.
|
||||
// This affects loop code performance on JVM.
|
||||
val lastExclusive = last.convertToExclusiveUpperBound()
|
||||
if (lastExclusive != null) {
|
||||
return@with ProgressionHeaderInfo(
|
||||
|
||||
@@ -212,6 +212,9 @@ class JvmBackendContext(
|
||||
super.handleDeepCopy(fileSymbolMap, classSymbolMap, functionSymbolMap)
|
||||
}
|
||||
|
||||
override val preferJavaLikeCounterLoop: Boolean
|
||||
get() = true
|
||||
|
||||
inner class JvmIr(
|
||||
irModuleFragment: IrModuleFragment,
|
||||
symbolTable: SymbolTable
|
||||
|
||||
Reference in New Issue
Block a user