From 5b595b58b24f1112a876b8ffec82e77d85f6ba9c Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 15 Apr 2019 14:25:35 +0200 Subject: [PATCH] JVM_IR: fold constant string concatenations --- .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 2 +- .../backend/jvm/lower/FoldConstantLowering.kt | 25 ++++++++++++++++--- .../testData/codegen/box/constants/kt9532.kt | 1 - .../codegen/box/constants/kt9532_lv10.kt | 2 +- .../stringOperations/constConcat.kt | 5 ++++ .../stringOperations/constValConcat.kt | 12 +++++++++ .../bytecodeText/stringOperations/kt19037.kt | 1 - .../stringOperations/partiallyConstConcat.kt | 9 +++++++ .../inlineStringConstInsideWhen.kt | 1 - .../whenStringOptimization/nonInlinedConst.kt | 1 + .../codegen/BytecodeTextTestGenerated.java | 15 +++++++++++ .../ir/IrBytecodeTextTestGenerated.java | 15 +++++++++++ 12 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt create mode 100644 compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt create mode 100644 compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index ee546a0de4a..1bbf435b5c9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -105,8 +105,8 @@ val jvmPhases = namedIrFilePhase( tailrecPhase then toArrayPhase then jvmTypeOperatorLoweringPhase then - foldConstantLoweringPhase then flattenStringConcatenationPhase then + foldConstantLoweringPhase then jvmBuiltinOptimizationLoweringPhase then additionalClassAnnotationPhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FoldConstantLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FoldConstantLowering.kt index 4f72c4d1c3b..3c1b8a8779e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FoldConstantLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FoldConstantLowering.kt @@ -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() + 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) + } }) } } \ No newline at end of file diff --git a/compiler/testData/codegen/box/constants/kt9532.kt b/compiler/testData/codegen/box/constants/kt9532.kt index e74fd2d5b9e..92ea89584ab 100644 --- a/compiler/testData/codegen/box/constants/kt9532.kt +++ b/compiler/testData/codegen/box/constants/kt9532.kt @@ -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 diff --git a/compiler/testData/codegen/box/constants/kt9532_lv10.kt b/compiler/testData/codegen/box/constants/kt9532_lv10.kt index b78cc1db13f..4f322ab65a2 100644 --- a/compiler/testData/codegen/box/constants/kt9532_lv10.kt +++ b/compiler/testData/codegen/box/constants/kt9532_lv10.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt b/compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt new file mode 100644 index 00000000000..8a8ef458bb9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/stringOperations/constConcat.kt @@ -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" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt b/compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt new file mode 100644 index 00000000000..507a3ac616f --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/stringOperations/constValConcat.kt @@ -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" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/stringOperations/kt19037.kt b/compiler/testData/codegen/bytecodeText/stringOperations/kt19037.kt index f6b3ff545e0..76b370bdc93 100644 --- a/compiler/testData/codegen/bytecodeText/stringOperations/kt19037.kt +++ b/compiler/testData/codegen/bytecodeText/stringOperations/kt19037.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR const val empty = "" val test1 = "" diff --git a/compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt b/compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt new file mode 100644 index 00000000000..ba802cadd5b --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/stringOperations/partiallyConstConcat.kt @@ -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" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/whenStringOptimization/inlineStringConstInsideWhen.kt b/compiler/testData/codegen/bytecodeText/whenStringOptimization/inlineStringConstInsideWhen.kt index 1d05bbbc590..8563b273642 100644 --- a/compiler/testData/codegen/bytecodeText/whenStringOptimization/inlineStringConstInsideWhen.kt +++ b/compiler/testData/codegen/bytecodeText/whenStringOptimization/inlineStringConstInsideWhen.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR const val y = "cde" fun foo(x : String) : String { diff --git a/compiler/testData/codegen/bytecodeText/whenStringOptimization/nonInlinedConst.kt b/compiler/testData/codegen/bytecodeText/whenStringOptimization/nonInlinedConst.kt index e44503c1d45..5011f63ad1c 100644 --- a/compiler/testData/codegen/bytecodeText/whenStringOptimization/nonInlinedConst.kt +++ b/compiler/testData/codegen/bytecodeText/whenStringOptimization/nonInlinedConst.kt @@ -1,4 +1,5 @@ // !LANGUAGE: -InlineConstVals +// IGNORE_BACKEND: JVM_IR const val y = "cde" diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 8c43a02b7fa..06ba06d99b2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 5b43136197a..d855c3911ec 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -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");