optimization and fixes

This commit is contained in:
Irmen de Jong 2019-01-12 16:13:40 +01:00
parent f3c9be4e06
commit 23afb1ccc2
7 changed files with 99 additions and 94 deletions

View File

@ -812,7 +812,7 @@ asmsub print (str text @ AY) -> clobbers(A,Y) -> () {
; ---- print null terminated string from A/Y ; ---- print null terminated string from A/Y
; note: the compiler contains an optimization that will replace ; note: the compiler contains an optimization that will replace
; a call to this subroutine with a string argument of just one char, ; a call to this subroutine with a string argument of just one char,
; by just one call to c64.CHROUT of that single char. @todo do this ; by just one call to c64.CHROUT of that single char.
%asm {{ %asm {{
sta c64.SCRATCH_ZPB1 sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG sty c64.SCRATCH_ZPREG

View File

@ -102,7 +102,7 @@ private fun compileMain(args: Array<String>) {
} }
//println(" time1: $time1") //println(" time1: $time1")
val time2 = measureTimeMillis { val time2 = measureTimeMillis {
// @todo this is slow! // @todo this call below is relatively slow
moduleAst.constantFold(namespace, heap) moduleAst.constantFold(namespace, heap)
} }
//println(" time2: $time2") //println(" time2: $time2")
@ -111,7 +111,7 @@ private fun compileMain(args: Array<String>) {
} }
//println(" time3: $time3") //println(" time3: $time3")
val time4 = measureTimeMillis { val time4 = measureTimeMillis {
// @todo this is slow! // @todo this call below is relatively slow
moduleAst.checkValid(namespace, compilerOptions, heap) // check if tree is valid moduleAst.checkValid(namespace, compilerOptions, heap) // check if tree is valid
} }
//println(" time4: $time4") //println(" time4: $time4")

View File

@ -1429,6 +1429,11 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
} }
override fun isIterable(namespace: INameScope, heap: HeapValues): Boolean = resultingDatatype(namespace, heap) in IterableDatatypes override fun isIterable(namespace: INameScope, heap: HeapValues): Boolean = resultingDatatype(namespace, heap) in IterableDatatypes
fun heapId(namespace: INameScope): Int {
val node = namespace.lookup(nameInSource, this) ?: throw UndefinedSymbolError(this)
return ((node as? VarDecl)?.value as? LiteralValue)?.heapId ?: throw FatalAstException("identifier is not on the heap")
}
} }

View File

@ -21,11 +21,15 @@ fun Module.checkIdentifiers(heap: HeapValues): MutableMap<String, IStatement> {
val parent = variable.first.parent val parent = variable.first.parent
when { when {
parent is Assignment && parent.value === variable.first -> { parent is Assignment && parent.value === variable.first -> {
parent.value = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position) val idref = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.value = idref
} }
parent is IFunctionCall -> { parent is IFunctionCall -> {
val parameterPos = parent.arglist.indexOf(variable.first) val parameterPos = parent.arglist.indexOf(variable.first)
parent.arglist[parameterPos] = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position) val idref = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.arglist[parameterPos] = idref
} }
else -> TODO("replace literalvalue by identifierref: $variable (in $parent)") else -> TODO("replace literalvalue by identifierref: $variable (in $parent)")
} }

View File

@ -99,6 +99,8 @@ class HeapValues {
fun get(heapId: Int): HeapValue = heap[heapId] fun get(heapId: Int): HeapValue = heap[heapId]
// TODO remove function
fun allEntries() = heap.withIndex().toList() fun allEntries() = heap.withIndex().toList()
} }
@ -2049,37 +2051,34 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
// todo deal with target.arrayindexed? // todo deal with target.arrayindexed?
fun createLoopCode(step: Int) {
if(step!=1 && step !=-1)
TODO("can't generate code for step other than 1 or -1 right now")
// LV++ / LV--
val postIncr = PostIncrDecr(lvTarget, if(step==1) "++" else "--", range.position)
postIncr.linkParents(body)
translate(postIncr)
if(lvTarget.register!=null)
prog.instr(Opcode.PUSH_VAR_BYTE, callLabel =lvTarget.register.toString())
else {
val opcode = opcodePushvar(targetStatement!!.datatype)
prog.instr(opcode, callLabel = targetStatement.scopedname)
}
val branch = BranchStatement(
BranchCondition.NZ,
AnonymousScope(mutableListOf(Jump(null, null, loopLabel, range.position)), range.position),
AnonymousScope(mutableListOf(), range.position),
range.position)
branch.linkParents(body)
translate(branch)
}
when (literalStepValue) { when (literalStepValue) {
1 -> { 1 -> createLoopCode(1)
// LV++ -1 -> createLoopCode(-1)
val postIncr = PostIncrDecr(lvTarget, "++", range.position) null -> TODO("variable range forloop non-literal-const step increment, At: ${range.position}")
postIncr.linkParents(body) else -> TODO("variable range forloop step increment not 1 or -1, At: ${range.position}")
translate(postIncr)
if(lvTarget.register!=null)
prog.instr(Opcode.PUSH_VAR_BYTE, callLabel =lvTarget.register.toString())
else {
val opcode = opcodePushvar(targetStatement!!.datatype)
prog.instr(opcode, callLabel = targetStatement.scopedname)
}
val branch = BranchStatement(
BranchCondition.NZ,
AnonymousScope(mutableListOf(Jump(null, null, loopLabel, range.position)), range.position),
AnonymousScope(mutableListOf(), range.position),
range.position)
branch.linkParents(body)
translate(branch)
}
-1 -> {
// LV--
val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
postIncr.linkParents(body)
translate(postIncr)
TODO("signed numbers and/or special condition are needed for decreasing for loop. Try an increasing loop and/or constant loop values instead? At: ${range.position}") // fix with signed numbers
}
else -> {
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")
}
} }
prog.label(breakLabel) prog.label(breakLabel)

View File

@ -2,6 +2,7 @@ package prog8.optimizing
import prog8.ast.* import prog8.ast.*
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.target.c64.Petscii
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions
import kotlin.math.floor import kotlin.math.floor
@ -37,6 +38,37 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
if (functionName in pureBuiltinFunctions) { if (functionName in pureBuiltinFunctions) {
printWarning("statement has no effect (function return value is discarded)", functionCall.position) printWarning("statement has no effect (function return value is discarded)", functionCall.position)
statementsToRemove.add(functionCall) statementsToRemove.add(functionCall)
return functionCall
}
}
if(functionCall.target.nameInSource==listOf("c64scr", "print") ||
functionCall.target.nameInSource==listOf("c64scr", "print_p")) {
// printing a literal string of just 2 or 1 characters is replaced by directly outputting those characters
if(functionCall.arglist.single() is LiteralValue)
throw AstException("string argument should be on heap already")
val stringVar = functionCall.arglist.single() as? IdentifierReference
if(stringVar!=null) {
val heapId = stringVar.heapId(namespace)
val string = heap.get(heapId).str!!
// TODO heap.remove(heapId)
if(string.length==1) {
val petscii = Petscii.encodePetscii(string, true)[0]
functionCall.arglist.clear()
functionCall.arglist.add(LiteralValue.optimalInteger(petscii, functionCall.position))
functionCall.target = IdentifierReference(listOf("c64", "CHROUT"), functionCall.target.position)
optimizationsDone++
return functionCall
} else if(string.length==2) {
val petscii = Petscii.encodePetscii(string, true)
val scope = AnonymousScope(mutableListOf(), functionCall.position)
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCall.target.position),
mutableListOf(LiteralValue.optimalInteger(petscii[0], functionCall.position)), functionCall.position))
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCall.target.position),
mutableListOf(LiteralValue.optimalInteger(petscii[1], functionCall.position)), functionCall.position))
optimizationsDone++
return scope
}
} }
} }

View File

@ -1,48 +1,13 @@
%import c64utils %import c64utils
%import c64flt
~ main { ~ main {
sub start() { sub start() {
uword[4] uwa = 5 c64scr.print("hoi")
ubyte[4] uba = 5 c64scr.print("ho") ; @todo 2x CHROUT
word[4] wa = 5 c64scr.print("h") ; @todo 1x CHROUT
byte[4] ba = 5 c64scr.print("h") ; @todo 1x CHROUT
float[4] fa = 5.123 c64scr.print("\n") ; @todo 1x CHROUT
str naam = "irmen"
float ff = 3.4444
uword addr
addr = naam
addr = uwa
addr = fa
pairAX(naam)
pairAX("hello")
pairAX("hello2")
pairAX("hello2")
pairAX("hello2")
pairAY("hello2")
pairAY("hello2")
pairXY("hello2")
pairXY("hello2")
pairAX(uwa)
pairAX(fa)
pairAY(naam)
pairAY(uwa)
pairAY(fa)
pairXY(naam)
pairXY(uwa)
pairXY(fa)
}
asmsub pairAX(uword address @ AX) -> clobbers() -> () {
}
asmsub pairAY(uword address @ AY) -> clobbers() -> () {
}
asmsub pairXY(uword address @ XY) -> clobbers() -> () {
} }
} }