diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt index 59745b8c601..70ba88a8864 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt @@ -310,8 +310,7 @@ internal class HeaderProcessor( progressionType.elementCastFunctionName ), nameHint = "inductionVariable", - isMutable = true, - origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE + isMutable = true ) // Due to features of PSI2IR we can obtain nullable arguments here while actually @@ -325,8 +324,7 @@ internal class HeaderProcessor( progressionType.elementCastFunctionName ) ), - nameHint = "last", - origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE + nameHint = "last" ) val stepValue = scope.createTemporaryVariable( @@ -336,8 +334,7 @@ internal class HeaderProcessor( progressionType.stepCastFunctionName ) ), - nameHint = "step", - origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE + nameHint = "step" ) return when (headerInfo) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt index 8985adfa6db..cea4d82992e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt @@ -351,8 +351,7 @@ internal abstract class IndexedGetIterationHandler(protected val context: Common // This also ensures that the semantics of re-assignment of array variables used in the loop is consistent with the semantics // proposed in https://youtrack.jetbrains.com/issue/KT-21354. val arrayReference = scope.createTemporaryVariable( - expression, nameHint = "indexedObject", - origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE + expression, nameHint = "indexedObject" ) val last = irCall(expression.type.sizePropertyGetter).apply { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 8fd450be82c..faea2725cc2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -262,8 +262,7 @@ class ExpressionCodegen( info.variables.forEach { when (it.declaration.origin) { IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, - IrDeclarationOrigin.FOR_LOOP_ITERATOR, - IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE -> { + IrDeclarationOrigin.FOR_LOOP_ITERATOR -> { // Ignore implicitly created variables } else -> { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt index 3536ff743d9..0e0d74f0b0d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt @@ -178,8 +178,7 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower statement.initializer is IrConst<*> } - override fun visitBlock(expression: IrBlock): IrExpression { - expression.transformChildrenVoid(this) + private fun removeUnnecessaryTemporaryVariables(statements: MutableList) { // Remove declarations of immutable temporary variables with constant values. // IrGetValue operations for such temporary variables are replaced // by the initializer IrConst. This makes sure that we do not load and @@ -208,9 +207,10 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower // // which allows the equality check to be simplified away and we end up with // just a const string load. - expression.statements.removeIf { + statements.removeIf { isImmutableTemporaryVariableWithConstantValue(it) } + // Remove a block that contains only two statements: the declaration of a temporary // variable and a load of the value of that temporary variable with just the initializer // for the temporary variable. We only perform this transformation for compiler generated @@ -242,18 +242,28 @@ class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLower // 42.toLong() // // Doing so we avoid local loads and stores. - if (expression.statements.size == 2) { - val first = expression.statements[0] - val second = expression.statements[1] + if (statements.size == 2) { + val first = statements[0] + val second = statements[1] if (first is IrVariable && first.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE && second is IrGetValue - && first.symbol == second.symbol - ) { - expression.statements.clear() - first.initializer?.let { expression.statements.add(it) } + && first.symbol == second.symbol) { + statements.clear() + first.initializer?.let { statements.add(it) } } } + } + + override fun visitBlockBody(body: IrBlockBody): IrBody { + body.transformChildrenVoid(this) + removeUnnecessaryTemporaryVariables(body.statements) + return body + } + + override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { + expression.transformChildrenVoid(this) + removeUnnecessaryTemporaryVariables(expression.statements) return expression } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt index 7b0b40669d2..ad6b251682e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt @@ -197,7 +197,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen irNextCall ) } else { - scope.createTemporaryVariable(irNextCall, "loop_parameter", origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE) + scope.createTemporaryVariable(irNextCall, "loop_parameter") } irInnerBody.statements.add(irLoopParameter) diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt index c882c798ce9..d3eb41c5ee5 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt @@ -9,5 +9,5 @@ fun test() { // 0 hasNext // 0 nextChar // 0 INVOKEINTERFACE -// 1 ISTORE 4 -// 1 ILOAD 4 +// 1 charAt \(I\)C +// 1 length \(\)I diff --git a/compiler/testData/ir/irText/expressions/for.txt b/compiler/testData/ir/irText/expressions/for.txt index e6cf725a0f1..2af2f411122 100644 --- a/compiler/testData/ir/irText/expressions/for.txt +++ b/compiler/testData/ir/irText/expressions/for.txt @@ -41,7 +41,7 @@ FILE fqName: fileName:/for.kt condition: CALL 'public abstract fun hasNext (): kotlin.Boolean declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=FOR_LOOP_HAS_NEXT $this: GET_VAR 'val tmp0_iterator: kotlin.collections.Iterator> [val] declared in .testDestructuring' type=kotlin.collections.Iterator> origin=null body: BLOCK type=kotlin.Unit origin=FOR_LOOP_INNER_WHILE - VAR FOR_LOOP_IMPLICIT_VARIABLE name:tmp1_loop_parameter type:kotlin.Pair [val] + VAR IR_TEMPORARY_VARIABLE name:tmp1_loop_parameter type:kotlin.Pair [val] CALL 'public abstract fun next (): T of kotlin.collections.Iterator declared in kotlin.collections.Iterator' type=kotlin.Pair origin=FOR_LOOP_NEXT $this: GET_VAR 'val tmp0_iterator: kotlin.collections.Iterator> [val] declared in .testDestructuring' type=kotlin.collections.Iterator> origin=null VAR name:i type:kotlin.Int [val]