mirror of
https://github.com/irmen/prog8.git
synced 2024-07-10 08:28:57 +00:00
attempt at optimization to register parameter passing
This commit is contained in:
parent
f0a504baec
commit
ae21e03e1d
@ -1647,6 +1647,40 @@ class Subroutine(override val name: String,
|
|||||||
.filter { it is InlineAssembly }
|
.filter { it is InlineAssembly }
|
||||||
.map { (it as InlineAssembly).assembly }
|
.map { (it as InlineAssembly).assembly }
|
||||||
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
.count { " rti" in it || "\trti" in it || " rts" in it || "\trts" in it || " jmp" in it || "\tjmp" in it }
|
||||||
|
|
||||||
|
val canBeAsmSubroutine =false // TODO see below
|
||||||
|
// !isAsmSubroutine
|
||||||
|
// && ((parameters.size == 1 && parameters[0].type in setOf(DataType.BYTE, DataType.UBYTE, DataType.WORD, DataType.UWORD))
|
||||||
|
// || (parameters.size == 2 && parameters.map { it.type }.all { it == DataType.BYTE || it == DataType.UBYTE }))
|
||||||
|
|
||||||
|
fun intoAsmSubroutine(): Subroutine {
|
||||||
|
// TODO turn subroutine into asm calling convention. Requires rethinking of how parameters are handled (conflicts with local vardefs now, see AstIdentifierChecker...)
|
||||||
|
return this // TODO
|
||||||
|
|
||||||
|
// println("TO ASM $this") // TODO
|
||||||
|
// val paramregs = if (parameters.size == 1 && parameters[0].type in setOf(DataType.BYTE, DataType.UBYTE))
|
||||||
|
// listOf(RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
||||||
|
// else if (parameters.size == 1 && parameters[0].type in setOf(DataType.WORD, DataType.UWORD))
|
||||||
|
// listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, null))
|
||||||
|
// else if (parameters.size == 2 && parameters.map { it.type }.all { it == DataType.BYTE || it == DataType.UBYTE })
|
||||||
|
// listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null), RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
||||||
|
// else throw FatalAstException("cannot convert subroutine to asm parameters")
|
||||||
|
//
|
||||||
|
// val asmsub=Subroutine(
|
||||||
|
// name,
|
||||||
|
// parameters,
|
||||||
|
// returntypes,
|
||||||
|
// paramregs,
|
||||||
|
// emptyList(),
|
||||||
|
// emptySet(),
|
||||||
|
// null,
|
||||||
|
// true,
|
||||||
|
// statements,
|
||||||
|
// position
|
||||||
|
// )
|
||||||
|
// asmsub.linkParents(parent)
|
||||||
|
// return asmsub
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,7 +124,8 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
|||||||
// NOTE:
|
// NOTE:
|
||||||
// - numeric types BYTE and WORD and FLOAT are passed by value;
|
// - numeric types BYTE and WORD and FLOAT are passed by value;
|
||||||
// - strings, arrays, matrices are passed by reference (their 16-bit address is passed as an uword parameter)
|
// - strings, arrays, matrices are passed by reference (their 16-bit address is passed as an uword parameter)
|
||||||
if(subroutine.asmAddress==null) {
|
// - do NOT do this is the statement can be transformed into an asm subroutine later!
|
||||||
|
if(subroutine.asmAddress==null && !subroutine.canBeAsmSubroutine) {
|
||||||
if(subroutine.asmParameterRegisters.isEmpty()) {
|
if(subroutine.asmParameterRegisters.isEmpty()) {
|
||||||
subroutine.parameters
|
subroutine.parameters
|
||||||
.filter { it.name !in allDefinedNames }
|
.filter { it.name !in allDefinedNames }
|
||||||
|
@ -165,8 +165,10 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
|||||||
val argConst = arg.first.value.constValue(namespace, heap)
|
val argConst = arg.first.value.constValue(namespace, heap)
|
||||||
if(argConst!=null && argConst.type!=expectedDt) {
|
if(argConst!=null && argConst.type!=expectedDt) {
|
||||||
val convertedValue = argConst.intoDatatype(expectedDt)
|
val convertedValue = argConst.intoDatatype(expectedDt)
|
||||||
if(convertedValue!=null)
|
if(convertedValue!=null) {
|
||||||
functionCall.arglist[arg.first.index] = convertedValue
|
functionCall.arglist[arg.first.index] = convertedValue
|
||||||
|
optimizationsDone++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,18 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
linesToRemove.reversed().forEach{subroutine.statements.removeAt(it)}
|
linesToRemove.reversed().forEach{subroutine.statements.removeAt(it)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(subroutine.canBeAsmSubroutine) {
|
||||||
|
optimizationsDone++
|
||||||
|
return subroutine.intoAsmSubroutine() // TODO this doesn't work yet due to parameter vardecl issue
|
||||||
|
|
||||||
|
// TODO fix parameter passing so this also works:
|
||||||
|
// asmsub aa(byte arg @ Y) -> clobbers() -> () {
|
||||||
|
// byte local = arg ; @todo fix 'undefined symbol arg' by some sort of alias name for the parameter
|
||||||
|
// A=44
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return subroutine
|
return subroutine
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,16 +95,6 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
return linesToRemove
|
return linesToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun returnregisters(subroutine: Subroutine): List<RegisterOrStatusflag> {
|
|
||||||
return when {
|
|
||||||
subroutine.returntypes.isEmpty() -> listOf()
|
|
||||||
subroutine.returntypes.size==1 && subroutine.returntypes[0] in setOf(DataType.BYTE, DataType.UBYTE) -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null))
|
|
||||||
subroutine.returntypes.size==1 && subroutine.returntypes[0] in setOf(DataType.WORD, DataType.UWORD) -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, null))
|
|
||||||
subroutine.returntypes.size==2 && subroutine.returntypes.all { it in setOf(DataType.BYTE, DataType.UBYTE)} -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, null), RegisterOrStatusflag(RegisterOrPair.Y, null, null))
|
|
||||||
else -> throw FatalAstException("can't convert return values to registers")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isNotMemory(target: AssignTarget): Boolean {
|
private fun isNotMemory(target: AssignTarget): Boolean {
|
||||||
if(target.register!=null)
|
if(target.register!=null)
|
||||||
return true
|
return true
|
||||||
|
@ -32,6 +32,8 @@ Add more compiler optimizations to the existing ones.
|
|||||||
- can the parameter passing to subroutines be optimized to avoid copying?
|
- can the parameter passing to subroutines be optimized to avoid copying?
|
||||||
|
|
||||||
- subroutines with 1 or 2 byte args (or 1 word arg) should be converted to asm calling convention with the args in A/Y register
|
- subroutines with 1 or 2 byte args (or 1 word arg) should be converted to asm calling convention with the args in A/Y register
|
||||||
|
this requires rethinking the way parameters are represented, simply injecting vardecls to
|
||||||
|
declare local variables for them is not always correct anymore
|
||||||
|
|
||||||
|
|
||||||
Also some library routines and code patterns could perhaps be optimized further
|
Also some library routines and code patterns could perhaps be optimized further
|
||||||
|
@ -4,23 +4,31 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
myblock2.foo()
|
foo(1)
|
||||||
myblock3.foo()
|
bar(1,2)
|
||||||
|
baz(3333)
|
||||||
|
bzaz(60000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub foo(byte arg) {
|
||||||
|
byte local = arg
|
||||||
|
A=44
|
||||||
|
}
|
||||||
|
|
||||||
|
sub bar(byte arg1, ubyte arg2) {
|
||||||
|
byte local1 = arg1
|
||||||
|
ubyte local2 = arg2
|
||||||
|
A=44
|
||||||
|
}
|
||||||
|
|
||||||
|
sub baz(word arg) {
|
||||||
|
word local=arg
|
||||||
|
A=44
|
||||||
|
}
|
||||||
|
sub bzaz(uword arg) {
|
||||||
|
uword local=arg
|
||||||
|
A=44
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~ myblock2 {
|
|
||||||
|
|
||||||
sub foo() {
|
|
||||||
A=99
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
~ myblock3 {
|
|
||||||
|
|
||||||
sub foo() {
|
|
||||||
A=99
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -17,6 +17,5 @@
|
|||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="Python 3.7 interpreter library" level="application" />
|
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
Loading…
Reference in New Issue
Block a user