[IR] Split const folding into necessary one and for optimizations only
In this commit we have a lot of change in test data. This was caused by the way where we evaluate constants. We split constant evaluation into two distinct parts: only necessary evaluations for `fir2ir` (like const val and annotations) and optimizations for lowering. Now we don't do all constant evaluation on `fir2ir`, but IR dump is executed after this phase, so test data changed. #KT-58923
This commit is contained in:
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.transformer
|
||||
|
||||
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
import org.jetbrains.kotlin.ir.interpreter.createGetField
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
internal class IrConstAllTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
inlineConstTracker: InlineConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstExpressionTransformer(
|
||||
interpreter, irFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
+3
-5
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.ir.interpreter.createGetField
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
internal class IrConstExpressionTransformer(
|
||||
internal abstract class IrConstExpressionTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
@@ -32,7 +32,7 @@ internal class IrConstExpressionTransformer(
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstTransformer(interpreter, irFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions) {
|
||||
private var inAnnotation: Boolean = false
|
||||
protected var inAnnotation: Boolean = false
|
||||
|
||||
private inline fun <T> visitAnnotationClass(crossinline block: () -> T): T {
|
||||
val oldInAnnotation = inAnnotation
|
||||
@@ -67,10 +67,8 @@ internal class IrConstExpressionTransformer(
|
||||
override fun visitField(declaration: IrField, data: Nothing?): IrStatement {
|
||||
val initializer = declaration.initializer
|
||||
val expression = initializer?.expression ?: return declaration
|
||||
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
|
||||
if (!isConst) return super.visitField(declaration, data)
|
||||
|
||||
val getField = declaration.createGetField()
|
||||
|
||||
if (getField.canBeInterpreted()) {
|
||||
initializer.expression = expression.interpret(failAsError = true)
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.transformer
|
||||
|
||||
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
|
||||
import org.jetbrains.kotlin.incremental.components.InlineConstTracker
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||
|
||||
/**
|
||||
* This transformer will visit all expressions and will evaluate only those that are necessary. By "necessary" we mean expressions
|
||||
* that are used in `const val` and inside annotations.
|
||||
*/
|
||||
internal class IrConstOnlyNecessaryTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
irFile: IrFile,
|
||||
mode: EvaluationMode,
|
||||
checker: IrInterpreterChecker,
|
||||
evaluatedConstTracker: EvaluatedConstTracker?,
|
||||
inlineConstTracker: InlineConstTracker?,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit,
|
||||
suppressExceptions: Boolean,
|
||||
) : IrConstExpressionTransformer(
|
||||
interpreter, irFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
) {
|
||||
override fun visitCall(expression: IrCall, data: Nothing?): IrElement {
|
||||
val isConstGetter = (expression.symbol.owner as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isConst == true
|
||||
if (!inAnnotation && !isConstGetter) {
|
||||
expression.transformChildren(this, null)
|
||||
return expression
|
||||
}
|
||||
return super.visitCall(expression, data)
|
||||
}
|
||||
|
||||
override fun visitGetField(expression: IrGetField, data: Nothing?): IrExpression {
|
||||
val isConst = expression.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true
|
||||
if (!inAnnotation && !isConst) return expression
|
||||
return super.visitGetField(expression, data)
|
||||
}
|
||||
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): IrExpression {
|
||||
if (!inAnnotation) {
|
||||
expression.transformChildren(this, null)
|
||||
return expression
|
||||
}
|
||||
return super.visitStringConcatenation(expression, data)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField, data: Nothing?): IrStatement {
|
||||
val isConst = declaration.correspondingPropertySymbol?.owner?.isConst == true
|
||||
if (!isConst) {
|
||||
declaration.transformChildren(this, null)
|
||||
return declaration
|
||||
}
|
||||
|
||||
return super.visitField(declaration, data)
|
||||
}
|
||||
}
|
||||
+41
-14
@@ -33,24 +33,51 @@ fun IrFile.transformConst(
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
||||
suppressExceptions: Boolean = false,
|
||||
) {
|
||||
val preprocessedFile = this.preprocessForConstTransformer(interpreter, mode)
|
||||
|
||||
val checker = IrInterpreterCommonChecker()
|
||||
val irConstExpressionTransformer = IrConstOnlyNecessaryTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||
}
|
||||
|
||||
fun IrFile.runConstOptimizations(
|
||||
interpreter: IrInterpreter,
|
||||
mode: EvaluationMode,
|
||||
evaluatedConstTracker: EvaluatedConstTracker? = null,
|
||||
inlineConstTracker: InlineConstTracker? = null,
|
||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
||||
suppressExceptions: Boolean = false,
|
||||
) {
|
||||
val preprocessedFile = this.preprocessForConstTransformer(interpreter, mode)
|
||||
val checker = IrInterpreterCommonChecker()
|
||||
val irConstExpressionTransformer = IrConstAllTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||
}
|
||||
|
||||
fun IrFile.preprocessForConstTransformer(
|
||||
interpreter: IrInterpreter,
|
||||
mode: EvaluationMode,
|
||||
): IrFile {
|
||||
val preprocessors = setOf(IrInterpreterKCallableNamePreprocessor())
|
||||
val preprocessedFile = preprocessors.fold(this) { file, preprocessor ->
|
||||
preprocessor.preprocess(file, IrInterpreterPreprocessorData(mode, interpreter.irBuiltIns))
|
||||
}
|
||||
|
||||
val checker = IrInterpreterCommonChecker()
|
||||
val irConstExpressionTransformer = IrConstExpressionTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstDeclarationAnnotationTransformer = IrConstDeclarationAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
val irConstTypeAnnotationTransformer = IrConstTypeAnnotationTransformer(
|
||||
interpreter, preprocessedFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
||||
)
|
||||
preprocessedFile.transform(irConstExpressionTransformer, null)
|
||||
preprocessedFile.transform(irConstDeclarationAnnotationTransformer, null)
|
||||
preprocessedFile.transform(irConstTypeAnnotationTransformer, null)
|
||||
return preprocessedFile
|
||||
}
|
||||
|
||||
// Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid`
|
||||
|
||||
Reference in New Issue
Block a user