JVM_IR: fold constant string concatenations

This commit is contained in:
pyos
2019-04-15 14:25:35 +02:00
committed by max-kammerer
parent 1bc4a2eff9
commit 5b595b58b2
12 changed files with 81 additions and 8 deletions
@@ -105,8 +105,8 @@ val jvmPhases = namedIrFilePhase(
tailrecPhase then
toArrayPhase then
jvmTypeOperatorLoweringPhase then
foldConstantLoweringPhase then
flattenStringConcatenationPhase then
foldConstantLoweringPhase then
jvmBuiltinOptimizationLoweringPhase then
additionalClassAnnotationPhase then
@@ -10,10 +10,9 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrExpression
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.types.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -176,6 +175,26 @@ class FoldConstantLowering(private val context: JvmBackendContext) : IrElementTr
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
View File
@@ -1,5 +1,4 @@
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
// IGNORE_BACKEND: JVM_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: NATIVE
+1 -1
View File
@@ -1,5 +1,5 @@
// !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
// 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 = ""
val test1 = ""
@@ -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"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
const val y = "cde"
fun foo(x : String) : String {
@@ -1,4 +1,5 @@
// !LANGUAGE: -InlineConstVals
// IGNORE_BACKEND: JVM_IR
const val y = "cde"
@@ -3422,6 +3422,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
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")
public void testDoNotAppendEmptyString() throws Exception {
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");
}
@TestMetadata("partiallyConstConcat.kt")
public void testPartiallyConstConcat() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt");
}
@TestMetadata("plusAssign.kt")
public void testPlusAssign() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");
@@ -3432,6 +3432,16 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
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")
public void testDoNotAppendEmptyString() throws Exception {
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");
}
@TestMetadata("partiallyConstConcat.kt")
public void testPartiallyConstConcat() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt");
}
@TestMetadata("plusAssign.kt")
public void testPlusAssign() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/plusAssign.kt");