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 {
|
fun isSideEffectFree(call: IrCall): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val preferJavaLikeCounterLoop: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -252,6 +252,8 @@ class ProgressionLoopHeader(
|
|||||||
context: CommonBackendContext
|
context: CommonBackendContext
|
||||||
) : NumericForLoopHeader<ProgressionHeaderInfo>(headerInfo, builder, context) {
|
) : NumericForLoopHeader<ProgressionHeaderInfo>(headerInfo, builder, context) {
|
||||||
|
|
||||||
|
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||||
|
|
||||||
// For this loop:
|
// For this loop:
|
||||||
//
|
//
|
||||||
// for (i in first()..last() step step())
|
// for (i in first()..last() step step())
|
||||||
@@ -331,7 +333,7 @@ class ProgressionLoopHeader(
|
|||||||
|
|
||||||
val loopCondition = buildLoopCondition(this@with)
|
val loopCondition = buildLoopCondition(this@with)
|
||||||
LoopReplacement(newLoop, irIfThen(loopCondition, newLoop))
|
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
|
// 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) { ... }`).
|
// (`for (int i = first; i < lastExclusive; ++i) { ... }`).
|
||||||
// Otherwise loop-related optimizations will not kick in, resulting in significant performance degradation.
|
// 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.builders.irInt
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
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.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
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) :
|
internal abstract class IndicesHandler(protected val context: CommonBackendContext) :
|
||||||
ProgressionHandler {
|
ProgressionHandler {
|
||||||
|
|
||||||
|
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||||
|
|
||||||
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
|
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
|
||||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
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: IrExpression
|
||||||
val last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter)
|
val lastInclusive: IrExpression?
|
||||||
.apply { dispatchReceiver = expression.extensionReceiver!! }
|
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(
|
ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = irInt(0),
|
first = irInt(0),
|
||||||
last = last,
|
last = last,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
isLastInclusive = false,
|
isLastInclusive = isLastInclusive,
|
||||||
canOverflow = false,
|
canOverflow = false,
|
||||||
direction = ProgressionDirection.INCREASING,
|
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) :
|
internal class RangeToHandler(private val context: CommonBackendContext) :
|
||||||
ProgressionHandler {
|
ProgressionHandler {
|
||||||
|
|
||||||
|
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
|
||||||
|
|
||||||
private val progressionElementTypes = context.ir.symbols.progressionElementTypes
|
private val progressionElementTypes = context.ir.symbols.progressionElementTypes
|
||||||
|
|
||||||
override val matcher = SimpleCalleeMatcher {
|
override val matcher = SimpleCalleeMatcher {
|
||||||
@@ -39,9 +41,9 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
|
|||||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
||||||
val last = expression.getValueArgument(0)!!
|
val last = expression.getValueArgument(0)!!
|
||||||
|
|
||||||
// Convert range with inclusive upper bound to exclusive upper bound if possible.
|
if (preferJavaLikeCounterLoop && canUseExclusiveUpperBound(last, data)) {
|
||||||
// This affects loop code performance on JVM.
|
// Convert range with inclusive upper bound to exclusive upper bound if possible.
|
||||||
if (canUseExclusiveUpperBound(last, data)) {
|
// This affects loop code performance on JVM.
|
||||||
val lastExclusive = last.convertToExclusiveUpperBound()
|
val lastExclusive = last.convertToExclusiveUpperBound()
|
||||||
if (lastExclusive != null) {
|
if (lastExclusive != null) {
|
||||||
return@with ProgressionHeaderInfo(
|
return@with ProgressionHeaderInfo(
|
||||||
|
|||||||
@@ -212,6 +212,9 @@ class JvmBackendContext(
|
|||||||
super.handleDeepCopy(fileSymbolMap, classSymbolMap, functionSymbolMap)
|
super.handleDeepCopy(fileSymbolMap, classSymbolMap, functionSymbolMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val preferJavaLikeCounterLoop: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
inner class JvmIr(
|
inner class JvmIr(
|
||||||
irModuleFragment: IrModuleFragment,
|
irModuleFragment: IrModuleFragment,
|
||||||
symbolTable: SymbolTable
|
symbolTable: SymbolTable
|
||||||
|
|||||||
Reference in New Issue
Block a user