JVM_IR generate range loops as counter loops when possible
This commit is contained in:
committed by
teamcityserver
parent
d0f207071c
commit
38d6c8ded0
+35
-16
@@ -80,7 +80,8 @@ class ProgressionHeaderInfo(
|
|||||||
isReversed: Boolean = false,
|
isReversed: Boolean = false,
|
||||||
canOverflow: Boolean? = null,
|
canOverflow: Boolean? = null,
|
||||||
direction: ProgressionDirection,
|
direction: ProgressionDirection,
|
||||||
val additionalStatements: List<IrStatement> = listOf()
|
val additionalStatements: List<IrStatement> = listOf(),
|
||||||
|
val originalLastInclusive: IrExpression? = null
|
||||||
) : NumericHeaderInfo(
|
) : NumericHeaderInfo(
|
||||||
progressionType, first, last, step, isLastInclusive,
|
progressionType, first, last, step, isLastInclusive,
|
||||||
canCacheLast = true,
|
canCacheLast = true,
|
||||||
@@ -88,6 +89,22 @@ class ProgressionHeaderInfo(
|
|||||||
direction = direction
|
direction = direction
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
fun revertToLastInclusive(): ProgressionHeaderInfo? =
|
||||||
|
originalLastInclusive?.let {
|
||||||
|
ProgressionHeaderInfo(
|
||||||
|
progressionType = progressionType,
|
||||||
|
first = first,
|
||||||
|
last = originalLastInclusive,
|
||||||
|
step = step,
|
||||||
|
isLastInclusive = true,
|
||||||
|
isReversed = isReversed,
|
||||||
|
canOverflow = canOverflow,
|
||||||
|
direction = direction,
|
||||||
|
additionalStatements = additionalStatements,
|
||||||
|
originalLastInclusive = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val canOverflow: Boolean by lazy {
|
val canOverflow: Boolean by lazy {
|
||||||
if (canOverflow != null) return@lazy canOverflow
|
if (canOverflow != null) return@lazy canOverflow
|
||||||
|
|
||||||
@@ -148,21 +165,23 @@ class ProgressionHeaderInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asReversed() = if (isLastInclusive) {
|
override fun asReversed(): HeaderInfo? =
|
||||||
ProgressionHeaderInfo(
|
if (isLastInclusive) {
|
||||||
progressionType = progressionType,
|
ProgressionHeaderInfo(
|
||||||
first = last,
|
progressionType = progressionType,
|
||||||
last = first,
|
first = last,
|
||||||
step = step.negate(),
|
last = first,
|
||||||
isReversed = !isReversed,
|
step = step.negate(),
|
||||||
direction = direction.asReversed(),
|
isReversed = !isReversed,
|
||||||
additionalStatements = additionalStatements
|
direction = direction.asReversed(),
|
||||||
)
|
additionalStatements = additionalStatements
|
||||||
} else {
|
)
|
||||||
// If reversed, we would have a "first-exclusive" loop. We are currently not supporting this since it would add more complexity
|
} else {
|
||||||
// due to possible overflow when pre-incrementing the loop variable (see KT-42533).
|
// If reversed, we would have a "first-exclusive" loop. We are currently not supporting this since it would add more complexity
|
||||||
null
|
// due to possible overflow when pre-incrementing the loop variable (see KT-42533).
|
||||||
}
|
revertToLastInclusive()?.asReversed()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+28
-9
@@ -304,7 +304,7 @@ class ProgressionLoopHeader(
|
|||||||
|
|
||||||
override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) =
|
override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) =
|
||||||
with(builder) {
|
with(builder) {
|
||||||
val newLoop = if (headerInfo.canOverflow) {
|
if (headerInfo.canOverflow) {
|
||||||
// If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like:
|
// If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like:
|
||||||
//
|
//
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
@@ -315,7 +315,7 @@ class ProgressionLoopHeader(
|
|||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (loopVar != last)
|
// } while (loopVar != last)
|
||||||
// }
|
// }
|
||||||
IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
|
val newLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
|
||||||
val loopVariableExpression = irGet(loopVariable!!).let {
|
val loopVariableExpression = irGet(loopVariable!!).let {
|
||||||
headerInfo.progressionType.run {
|
headerInfo.progressionType.run {
|
||||||
if (this is UnsignedProgressionType) {
|
if (this is UnsignedProgressionType) {
|
||||||
@@ -328,8 +328,30 @@ class ProgressionLoopHeader(
|
|||||||
condition = irNotEquals(loopVariableExpression, lastExpression)
|
condition = irNotEquals(loopVariableExpression, lastExpression)
|
||||||
body = newBody
|
body = newBody
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val loopCondition = buildLoopCondition(this@with)
|
||||||
|
LoopReplacement(newLoop, irIfThen(loopCondition, newLoop))
|
||||||
|
} else if (!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.
|
||||||
|
//
|
||||||
|
// Use a simple while loop:
|
||||||
|
//
|
||||||
|
// while (inductionVar < last) {
|
||||||
|
// val loopVar = inductionVar
|
||||||
|
// inductionVar += step
|
||||||
|
// // Loop body
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
val newLoop = IrWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
|
||||||
|
label = oldLoop.label
|
||||||
|
condition = buildLoopCondition(this@with)
|
||||||
|
body = newBody
|
||||||
|
}
|
||||||
|
LoopReplacement(newLoop, newLoop)
|
||||||
} else {
|
} else {
|
||||||
// If the induction variable can NOT overflow, use a do-while loop. Loop is lowered into something like:
|
// Use an if-guarded do-while loop (note the difference in loop condition):
|
||||||
//
|
//
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// do {
|
// do {
|
||||||
@@ -339,17 +361,14 @@ class ProgressionLoopHeader(
|
|||||||
// } while (inductionVar <= last)
|
// } while (inductionVar <= last)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Even though this can be simplified into a simpler while loop, using if + do-while (i.e., doing a loop inversion)
|
val newLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
|
||||||
// performs better in benchmarks. In cases where `last` is a constant, the `if` may be optimized away.
|
|
||||||
IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
|
|
||||||
label = oldLoop.label
|
label = oldLoop.label
|
||||||
condition = buildLoopCondition(this@with)
|
condition = buildLoopCondition(this@with)
|
||||||
body = newBody
|
body = newBody
|
||||||
}
|
}
|
||||||
|
val loopCondition = buildLoopCondition(this@with)
|
||||||
|
LoopReplacement(newLoop, irIfThen(loopCondition, newLoop))
|
||||||
}
|
}
|
||||||
|
|
||||||
val loopCondition = buildLoopCondition(this@with)
|
|
||||||
LoopReplacement(newLoop, irIfThen(loopCondition, newLoop))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -26,17 +26,18 @@ internal abstract class IndicesHandler(protected val context: CommonBackendConte
|
|||||||
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)`.
|
// `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 {
|
val last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter)
|
||||||
dispatchReceiver = expression.extensionReceiver!!
|
.apply { dispatchReceiver = expression.extensionReceiver!! }
|
||||||
}.decrement()
|
|
||||||
|
|
||||||
ProgressionHeaderInfo(
|
ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = irInt(0),
|
first = irInt(0),
|
||||||
last = last,
|
last = last,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
|
isLastInclusive = false,
|
||||||
canOverflow = false,
|
canOverflow = false,
|
||||||
direction = ProgressionDirection.INCREASING
|
direction = ProgressionDirection.INCREASING,
|
||||||
|
originalLastInclusive = last.decrement()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
-2
@@ -15,8 +15,11 @@ import org.jetbrains.kotlin.backend.common.lower.loops.ProgressionType
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
||||||
import org.jetbrains.kotlin.ir.builders.irInt
|
import org.jetbrains.kotlin.ir.builders.irInt
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
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.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
|
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
|
||||||
@@ -34,12 +37,61 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
|
|||||||
|
|
||||||
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) =
|
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) =
|
||||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
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)) {
|
||||||
|
val lastExclusive = last.convertToExclusiveUpperBound()
|
||||||
|
if (lastExclusive != null) {
|
||||||
|
return@with ProgressionHeaderInfo(
|
||||||
|
data,
|
||||||
|
first = expression.dispatchReceiver!!,
|
||||||
|
last = lastExclusive,
|
||||||
|
step = irInt(1),
|
||||||
|
direction = ProgressionDirection.INCREASING,
|
||||||
|
isLastInclusive = false,
|
||||||
|
originalLastInclusive = last
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProgressionHeaderInfo(
|
ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = expression.dispatchReceiver!!,
|
first = expression.dispatchReceiver!!,
|
||||||
last = expression.getValueArgument(0)!!,
|
last = last,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
direction = ProgressionDirection.INCREASING
|
direction = ProgressionDirection.INCREASING
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun canUseExclusiveUpperBound(last: IrExpression, progressionType: ProgressionType): Boolean {
|
||||||
|
val lastLongValue = last.constLongValue
|
||||||
|
?: return false
|
||||||
|
return if (progressionType is UnsignedProgressionType) {
|
||||||
|
lastLongValue != -1L
|
||||||
|
} else {
|
||||||
|
lastLongValue != progressionType.maxValueAsLong
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrExpression.convertToExclusiveUpperBound(): IrConstImpl<out Any>? {
|
||||||
|
val irConst = this as? IrConst<*> ?: return null
|
||||||
|
return when (irConst.kind) {
|
||||||
|
IrConstKind.Char ->
|
||||||
|
IrConstImpl.char(startOffset, endOffset, type, IrConstKind.Char.valueOf(irConst).inc())
|
||||||
|
IrConstKind.Byte ->
|
||||||
|
IrConstImpl.byte(startOffset, endOffset, type, IrConstKind.Byte.valueOf(irConst).inc())
|
||||||
|
IrConstKind.Short ->
|
||||||
|
IrConstImpl.short(startOffset, endOffset, type, IrConstKind.Short.valueOf(irConst).inc())
|
||||||
|
IrConstKind.Int ->
|
||||||
|
IrConstImpl.int(startOffset, endOffset, type, IrConstKind.Int.valueOf(irConst).inc())
|
||||||
|
IrConstKind.Long ->
|
||||||
|
IrConstImpl.long(startOffset, endOffset, type, IrConstKind.Long.valueOf(irConst).inc())
|
||||||
|
else ->
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+3
-2
@@ -43,7 +43,7 @@ internal class StepHandler(
|
|||||||
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)) {
|
||||||
// Retrieve the HeaderInfo from the underlying progression (if any).
|
// Retrieve the HeaderInfo from the underlying progression (if any).
|
||||||
val nestedInfo = expression.extensionReceiver!!.accept(visitor, null) as? ProgressionHeaderInfo
|
var nestedInfo = expression.extensionReceiver!!.accept(visitor, null) as? ProgressionHeaderInfo
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
if (!nestedInfo.isLastInclusive) {
|
if (!nestedInfo.isLastInclusive) {
|
||||||
@@ -51,7 +51,8 @@ internal class StepHandler(
|
|||||||
// underlying progression is last-exclusive, we must decrement the nested "last" by the step. However, this can cause
|
// underlying progression is last-exclusive, we must decrement the nested "last" by the step. However, this can cause
|
||||||
// underflow if "last" is MIN_VALUE. We will not support fully optimizing this scenario (e.g., `for (i in A until B step C`)
|
// underflow if "last" is MIN_VALUE. We will not support fully optimizing this scenario (e.g., `for (i in A until B step C`)
|
||||||
// for now. It will be partly optimized via DefaultProgressionHandler.
|
// for now. It will be partly optimized via DefaultProgressionHandler.
|
||||||
return null
|
nestedInfo = nestedInfo.revertToLastInclusive()
|
||||||
|
?: return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val stepArg = expression.getValueArgument(0)!!
|
val stepArg = expression.getValueArgument(0)!!
|
||||||
|
|||||||
+1
-8
@@ -6,22 +6,15 @@ fun test(s: CharSequence): Int {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 0 IF_ICMPGT
|
// 0 IF_ICMPGT
|
||||||
// 0 IF_ICMPEQ
|
// 0 IF_ICMPEQ
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceTypeParameterIndices.kt
Vendored
+1
-9
@@ -6,9 +6,6 @@ fun <T : CharSequence> test(s: T): Int {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -16,13 +13,8 @@ fun <T : CharSequence> test(s: T): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 1 INVOKEINTERFACE java/lang/CharSequence\.length \(\)I
|
// 1 INVOKEINTERFACE java/lang/CharSequence\.length \(\)I
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 0 IF_ICMPGT
|
// 0 IF_ICMPGT
|
||||||
// 0 IF_ICMPEQ
|
// 0 IF_ICMPEQ
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
+2
-9
@@ -12,14 +12,7 @@ fun Collection<Int>.sumIndices(): Int {
|
|||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPGT
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
+2
-9
@@ -11,14 +11,7 @@ fun test() {
|
|||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPGT
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
Vendored
+2
-9
@@ -12,14 +12,7 @@ fun <T : Collection<*>> test(c: T) {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 1 INVOKEINTERFACE java/util/Collection\.size \(\)I
|
// 1 INVOKEINTERFACE java/util/Collection\.size \(\)I
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPGT
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
+2
-9
@@ -5,20 +5,13 @@ fun test() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPGT
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
+2
-9
@@ -5,20 +5,13 @@ fun test() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPGT
|
||||||
|
// 0 IF_ICMPLE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGT
|
|
||||||
// 1 IF_ICMPLE
|
|
||||||
// 2 IF
|
|
||||||
@@ -8,19 +8,17 @@ fun test(): Int {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
// 1 IF
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPGE
|
||||||
|
// 1 IF
|
||||||
@@ -8,19 +8,17 @@ fun test(): Int {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
// 1 IF
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPGE
|
||||||
|
// 1 IF
|
||||||
@@ -8,24 +8,22 @@ fun test(): Long {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
// 1 IFGT
|
|
||||||
// 0 L2I
|
// 0 L2I
|
||||||
// 0 I2L
|
// 0 I2L
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
|
// 1 IFGT
|
||||||
// 1 LCMP
|
// 1 LCMP
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 2 LCMP
|
// 1 LCMP
|
||||||
// 1 IFLE
|
// 1 IFGE
|
||||||
// 2 IF
|
// 1 IF
|
||||||
+3
-5
@@ -11,19 +11,17 @@ fun test(): Int {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
// 1 IF
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPGE
|
||||||
|
// 1 IF
|
||||||
-3
@@ -11,9 +11,6 @@ fun box(): String {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 reversed
|
// 0 reversed
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
|
|||||||
Vendored
-3
@@ -11,9 +11,6 @@ fun box(): String {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 reversed
|
// 0 reversed
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
|
|||||||
Vendored
-3
@@ -11,9 +11,6 @@ fun box(): String {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 reversed
|
// 0 reversed
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
|
|||||||
-3
@@ -22,9 +22,6 @@ fun box(): String {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
|
|
||||||
|
|
||||||
// 0 reversed
|
// 0 reversed
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
|
|||||||
-3
@@ -22,9 +22,6 @@ fun box(): String {
|
|||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
|
|
||||||
|
|
||||||
// 0 reversed
|
// 0 reversed
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
|
|||||||
+1
-9
@@ -6,9 +6,6 @@ fun test(a: Char, b: Char): String {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -16,11 +13,6 @@ fun test(a: Char, b: Char): String {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPLT
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
|
||||||
// 1 IF_ICMPLT
|
|
||||||
// 2 IF
|
|
||||||
+1
-9
@@ -8,9 +8,6 @@ fun f(a: Char): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -18,11 +15,6 @@ fun f(a: Char): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
|
// 0 IF_ICMPLT
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
|
||||||
// 1 IF_ICMPLT
|
|
||||||
// 2 IF
|
|
||||||
+2
-8
@@ -8,9 +8,6 @@ fun f(a: Char): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -18,8 +15,5 @@ fun f(a: Char): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// 1 IFGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 2 IF
|
|
||||||
@@ -6,9 +6,6 @@ fun test(a: Int, b: Int): Int {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -16,11 +13,5 @@ fun test(a: Int, b: Int): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
|
||||||
// 1 IF_ICMPLT
|
|
||||||
// 2 IF
|
|
||||||
-9
@@ -8,9 +8,6 @@ fun f(a: Int): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -18,11 +15,5 @@ fun f(a: Int): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
// 1 IF_ICMPGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 1 IF_ICMPGE
|
|
||||||
// 1 IF_ICMPLT
|
|
||||||
// 2 IF
|
|
||||||
+1
-4
@@ -18,8 +18,5 @@ fun f(a: Int): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// 1 IF_ICMPGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ fun test(a: Long, b: Long): Long {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -16,13 +13,6 @@ fun test(a: Long, b: Long): Long {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 LCMP
|
// 1 LCMP
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 2 LCMP
|
|
||||||
// 1 IFGE
|
|
||||||
// 1 IFLT
|
|
||||||
// 2 IF
|
|
||||||
-10
@@ -8,9 +8,6 @@ fun f(a: Long): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -18,13 +15,6 @@ fun f(a: Long): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 1 LCMP
|
// 1 LCMP
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 2 LCMP
|
|
||||||
// 1 IFGE
|
|
||||||
// 1 IFLT
|
|
||||||
// 2 IF
|
|
||||||
+1
-7
@@ -8,9 +8,6 @@ fun f(a: Long): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -18,8 +15,5 @@ fun f(a: Long): Int {
|
|||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// 1 IFGE
|
||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
|
||||||
// 2 IF
|
|
||||||
|
|||||||
@@ -3,19 +3,18 @@ fun f() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
// 0 getFirst
|
// 0 getFirst
|
||||||
// 0 getLast
|
// 0 getLast
|
||||||
// 0 getStep
|
// 0 getStep
|
||||||
// 1 IF
|
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPGE
|
||||||
|
// 1 IF
|
||||||
|
|||||||
+2
-6
@@ -9,9 +9,6 @@ fun f(a: UInt): Int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM non-IR uses while.
|
|
||||||
// JVM IR uses if + do-while.
|
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
@@ -27,7 +24,6 @@ fun f(a: UInt): Int {
|
|||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 1 IFLT
|
// 1 IF
|
||||||
// 2 IF
|
|
||||||
+1
-1
@@ -25,4 +25,4 @@ fun f(a: UInt): Int {
|
|||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 2 IF
|
// 1 IF
|
||||||
|
|||||||
+2
-3
@@ -27,7 +27,6 @@ fun f(a: ULong): Int {
|
|||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 2 INVOKESTATIC kotlin/UnsignedKt.ulongCompare
|
// 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 1 IFLT
|
// 1 IF
|
||||||
// 2 IF
|
|
||||||
+1
-1
@@ -25,4 +25,4 @@ fun f(a: ULong): Int {
|
|||||||
// 1 IF
|
// 1 IF
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 2 IF
|
// 1 IF
|
||||||
|
|||||||
Reference in New Issue
Block a user