JVM_IR: fold constant string concatenations
This commit is contained in:
@@ -105,8 +105,8 @@ val jvmPhases = namedIrFilePhase(
|
|||||||
tailrecPhase then
|
tailrecPhase then
|
||||||
toArrayPhase then
|
toArrayPhase then
|
||||||
jvmTypeOperatorLoweringPhase then
|
jvmTypeOperatorLoweringPhase then
|
||||||
foldConstantLoweringPhase then
|
|
||||||
flattenStringConcatenationPhase then
|
flattenStringConcatenationPhase then
|
||||||
|
foldConstantLoweringPhase then
|
||||||
jvmBuiltinOptimizationLoweringPhase then
|
jvmBuiltinOptimizationLoweringPhase then
|
||||||
additionalClassAnnotationPhase then
|
additionalClassAnnotationPhase then
|
||||||
|
|
||||||
|
|||||||
+22
-3
@@ -10,10 +10,9 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
@@ -176,6 +175,26 @@ class FoldConstantLowering(private val context: JvmBackendContext) : IrElementTr
|
|||||||
else -> expression
|
else -> expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
val folded = mutableListOf<IrExpression>()
|
||||||
|
for (next in expression.arguments) {
|
||||||
|
val last = folded.lastOrNull()
|
||||||
|
when {
|
||||||
|
next !is IrConst<*> -> folded += next
|
||||||
|
last !is IrConst<*> -> folded += IrConstImpl.string(
|
||||||
|
next.startOffset, next.endOffset, context.irBuiltIns.stringType, next.value.toString()
|
||||||
|
)
|
||||||
|
else -> folded[folded.size - 1] = IrConstImpl.string(
|
||||||
|
last.startOffset, next.endOffset, context.irBuiltIns.stringType,
|
||||||
|
last.value.toString() + next.value.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return folded.singleOrNull() as? IrConst<*>
|
||||||
|
?: IrStringConcatenationImpl(expression.startOffset, expression.endOffset, expression.type, folded)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
|
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// !LANGUAGE: -InlineConstVals
|
// !LANGUAGE: -InlineConstVals
|
||||||
// IGNORE_BACKEND: JS_IR, NATIVE
|
// IGNORE_BACKEND: JVM_IR, JS_IR, NATIVE
|
||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
val s = "1" + "2" + 3 + 4L + 5.0 + 6F + '7'
|
||||||
|
val c = "${"1"}2${3}${4L}${5.0}${6F}${'7'}"
|
||||||
|
|
||||||
|
// 0 NEW java/lang/StringBuilder
|
||||||
|
// 2 LDC "12345.06.07"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
const val string = "2"
|
||||||
|
const val int = 3
|
||||||
|
const val long = 4L
|
||||||
|
const val double = 5.0
|
||||||
|
const val float = 6F
|
||||||
|
const val char = '7'
|
||||||
|
|
||||||
|
val s = "1" + string + int + long + double + float + char
|
||||||
|
val c = "1$string$int$long$double$float$char"
|
||||||
|
|
||||||
|
// 0 NEW java/lang/StringBuilder
|
||||||
|
// 2 LDC "12345.06.07"
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
const val empty = ""
|
const val empty = ""
|
||||||
|
|
||||||
val test1 = ""
|
val test1 = ""
|
||||||
|
|||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// IGNORE_BACKEND: JVM
|
||||||
|
fun foo(a: String, b: String) {
|
||||||
|
val s = a + "1" + "2" + 3 + 4L + b + 5.0 + 6F + '7'
|
||||||
|
val c = "$a${"1"}2${3}${4L}$b${5.0}${6F}${'7'}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 NEW java/lang/StringBuilder
|
||||||
|
// 2 LDC "1234"
|
||||||
|
// 2 LDC "5.06.07"
|
||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
const val y = "cde"
|
const val y = "cde"
|
||||||
|
|
||||||
fun foo(x : String) : String {
|
fun foo(x : String) : String {
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// !LANGUAGE: -InlineConstVals
|
// !LANGUAGE: -InlineConstVals
|
||||||
|
// IGNORE_BACKEND: JVM_IR
|
||||||
|
|
||||||
const val y = "cde"
|
const val y = "cde"
|
||||||
|
|
||||||
|
|||||||
@@ -3422,6 +3422,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concat.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concat.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constConcat.kt")
|
||||||
|
public void testConstConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constValConcat.kt")
|
||||||
|
public void testConstValConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doNotAppendEmptyString.kt")
|
@TestMetadata("doNotAppendEmptyString.kt")
|
||||||
public void testDoNotAppendEmptyString() throws Exception {
|
public void testDoNotAppendEmptyString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/doNotAppendEmptyString.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/doNotAppendEmptyString.kt");
|
||||||
@@ -3462,6 +3472,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/nullableStringPlus.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/nullableStringPlus.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("partiallyConstConcat.kt")
|
||||||
|
public void testPartiallyConstConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("plusAssign.kt")
|
@TestMetadata("plusAssign.kt")
|
||||||
public void testPlusAssign() throws Exception {
|
public void testPlusAssign() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");
|
||||||
|
|||||||
+15
@@ -3432,6 +3432,16 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concat.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concat.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constConcat.kt")
|
||||||
|
public void testConstConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constValConcat.kt")
|
||||||
|
public void testConstValConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doNotAppendEmptyString.kt")
|
@TestMetadata("doNotAppendEmptyString.kt")
|
||||||
public void testDoNotAppendEmptyString() throws Exception {
|
public void testDoNotAppendEmptyString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/doNotAppendEmptyString.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/doNotAppendEmptyString.kt");
|
||||||
@@ -3472,6 +3482,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/nullableStringPlus.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/nullableStringPlus.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("partiallyConstConcat.kt")
|
||||||
|
public void testPartiallyConstConcat() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("plusAssign.kt")
|
@TestMetadata("plusAssign.kt")
|
||||||
public void testPlusAssign() throws Exception {
|
public void testPlusAssign() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");
|
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user