printing 2-letter strings is now only optimized into direct CHROUT if it's a const string literal

This commit is contained in:
Irmen de Jong 2021-05-16 15:00:40 +02:00
parent 68d7b4649e
commit ca61248861
6 changed files with 25 additions and 17 deletions

View File

@ -48,6 +48,7 @@ internal class StatementOptimizer(private val program: Program,
}
// printing a literal string of just 2 or 1 characters is replaced by directly outputting those characters
// only do this optimization if the arg is a known-constant string literal instead of a user defined variable.
if(functionCallStatement.target.nameInSource==listOf("txt", "print")) {
val arg = functionCallStatement.args.single()
val stringVar: IdentifierReference? = if(arg is AddressOf) {
@ -55,10 +56,7 @@ internal class StatementOptimizer(private val program: Program,
} else {
arg as? IdentifierReference
}
if(stringVar!=null) {
// TODO: only do this optimization if the arg is a known-constant string literal instead of a user defined variable. We can't see the difference here yet.
if(stringVar!=null && stringVar.wasStringLiteral(program)) {
val string = stringVar.targetVarDecl(program)?.value as? StringLiteralValue
if(string!=null) {
val pos = functionCallStatement.position

View File

@ -1,9 +1,6 @@
package prog8.optimizer
import prog8.ast.INameScope
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.*
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.FunctionCall
@ -65,7 +62,7 @@ internal class UnusedCodeRemover(private val program: Program,
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
if("force_output" !in block.options()) {
if (block.containsNoCodeNorVars()) {
if(block.name != program.internedStringsModuleName)
if(block.name != internedStringsModuleName)
errors.warn("removing unused block '${block.name}'", block.position)
return listOf(IAstModification.Remove(block, parent as INameScope))
}

View File

@ -8,6 +8,8 @@ import prog8.ast.walk.IAstVisitor
import java.nio.file.Path
import kotlin.math.abs
const val internedStringsModuleName = "prog8_interned_strings"
interface IStringEncoding {
fun encodeString(str: String, altEncoding: Boolean): List<Short>
fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
@ -257,7 +259,6 @@ class Program(val name: String,
var actualLoadAddress: Int = 0
private val internedStringsUnique = mutableMapOf<Pair<String, Boolean>, List<String>>()
val internedStringsModuleName = "prog8_interned_strings"
init {
// insert a container module for all interned strings later

View File

@ -788,6 +788,15 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
else -> InferredTypes.InferredType.unknown()
}
}
fun wasStringLiteral(program: Program): Boolean {
val decl = targetVarDecl(program)
if(decl == null || !decl.autogeneratedDontRemove)
return false
val scope=decl.definingModule()
return scope.name==internedStringsModuleName
}
}
class FunctionCall(override var target: IdentifierReference,

View File

@ -4,8 +4,9 @@ TODO
- possible idea: option to mark vardecls 'shared' to indicate they should not be optimized away because they're shared with assembly code?
However: who even needs variables declared in prog8 code that are only used by assembly???
- github issue about strings and their immutability:
StatementOptimizer line 60: only optimize when it's a known constant literal
Can we make deduplication the default again? (only string literals are considered...) remove cli option for it again?
IMPROVE DOCUMENTATION ABOUT STRINGS AND DEDUP and (NON)IMMUTABILITY.
- test all examples (including imgviewer, assembler and petaxian) before release of the new version

View File

@ -1,24 +1,26 @@
%import textio ; txt.*
%zeropage basicsafe
main {
sub start() {
str string1 = "stringvalue"
str string2 = "stringvalue"
str string3 = "stringvalue"
str string1 = "stringvalue\n"
str string2 = "stringvalue\n"
str string3 = "stringvalue\n"
str string4 = "a"
str string5 = "bb"
txt.print("a")
txt.print("a")
txt.print(string4)
txt.print("bb")
txt.print("bb")
txt.print(string5)
txt.print("\n")
txt.print("\n\n")
txt.print(string1)
txt.nl()
txt.print(string2)
txt.nl()
txt.print(string3)
txt.nl()
txt.print("hello\n")
txt.print("hello\n")
txt.print("hello\n")