[IR] canHaveSideEffects more robust

By default copyable (IrExpressionWithCopy) declarations is considered as side-effects.

^KT-45655 fixed

[IR] isTrivial more robust

By default copyable (IrExpressionWithCopy) declarations is considered as trivials.

[IR] Use one source of truth for triviality of IrExpression
This commit is contained in:
Ilya Goncharov
2021-03-24 16:00:24 +03:00
committed by TeamCityServer
parent 47f1a8a0bb
commit 7046f9badd
3 changed files with 26 additions and 7 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
@@ -695,3 +696,9 @@ fun IrExpression?.isPure(
return false return false
} }
fun IrExpression.isTrivial() =
this is IrConst<*> ||
this is IrGetValue ||
this is IrGetObjectValue ||
this is IrErrorExpressionImpl
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isTrivial
import org.jetbrains.kotlin.backend.common.lower.loops.canHaveSideEffects
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irBlock import org.jetbrains.kotlin.ir.builders.irBlock
@@ -14,11 +16,13 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irIfNull import org.jetbrains.kotlin.ir.builders.irIfNull
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.util.fileOrNull import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -189,11 +193,13 @@ class IfNullExpressionsFusionLowering(val context: CommonBackendContext) : FileL
null null
} }
private fun IrExpression.isTrivial() =
this is IrExpressionWithCopy
private fun IrExpression.copyIfTrivial() = private fun IrExpression.copyIfTrivial() =
if (this is IrExpressionWithCopy) copy() else this if (isTrivial()) {
require(this is IrExpressionWithCopy) {
"Not a copyable expression: ${render()}"
}
copy()
} else this
private fun IrExpression.remap(from: IrVariable, to: Lazy<IrVariable>): IrExpression = private fun IrExpression.remap(from: IrVariable, to: Lazy<IrVariable>): IrExpression =
copyIfTrivial().transform(object : AbstractVariableRemapper() { copyIfTrivial().transform(object : AbstractVariableRemapper() {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.lower.loops package org.jetbrains.kotlin.backend.common.lower.loops
import org.jetbrains.kotlin.backend.common.ir.isTrivial
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irGet
@@ -13,11 +14,13 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -70,7 +73,7 @@ internal fun IrExpression.decrement(): IrExpression {
} }
internal val IrExpression.canHaveSideEffects: Boolean internal val IrExpression.canHaveSideEffects: Boolean
get() = this !is IrExpressionWithCopy get() = !isTrivial()
private fun Any?.toLong(): Long? = private fun Any?.toLong(): Long? =
when (this) { when (this) {
@@ -95,9 +98,12 @@ internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary(
expression: IrExpression, nameHint: String? = null, expression: IrExpression, nameHint: String? = null,
irType: IrType? = null, isMutable: Boolean = false irType: IrType? = null, isMutable: Boolean = false
): Pair<IrVariable?, IrExpressionWithCopy> = ): Pair<IrVariable?, IrExpressionWithCopy> =
if (expression !is IrExpressionWithCopy) { if (expression.canHaveSideEffects) {
scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) } scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) }
} else { } else {
require(expression is IrExpressionWithCopy) {
"Not a copyable expression: ${expression.render()}"
}
Pair(null, expression) Pair(null, expression)
} }