more Rpn optimizations

This commit is contained in:
Irmen de Jong 2023-03-18 18:25:08 +01:00
parent 9b971ad222
commit 52b560e72d
6 changed files with 46 additions and 34 deletions

View File

@ -204,7 +204,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
return false
}
fun maxDepth(): Pair<Map<DataType, Int>, Int> {
fun maxDepth(): Map<DataType, Int> {
val depths = mutableMapOf(
DataType.UBYTE to 0,
DataType.UWORD to 0,
@ -225,7 +225,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
depths[DataType.UBYTE] = depth
maxDepths[DataType.UBYTE] = max(maxDepths.getValue(DataType.UBYTE), depth)
}
in WordDatatypes -> {
in WordDatatypes, in PassByReferenceDatatypes -> {
val depth = depths.getValue(DataType.UWORD) + 1
depths[DataType.UWORD] = depth
maxDepths[DataType.UWORD] = max(maxDepths.getValue(DataType.UWORD), depth)
@ -243,7 +243,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
fun pop(type: DataType) {
when (type) {
in ByteDatatypes -> depths[DataType.UBYTE]=depths.getValue(DataType.UBYTE) - 1
in WordDatatypes -> depths[DataType.UWORD]=depths.getValue(DataType.UWORD) - 1
in WordDatatypes, in PassByReferenceDatatypes -> depths[DataType.UWORD]=depths.getValue(DataType.UWORD) - 1
DataType.FLOAT -> depths[DataType.FLOAT]=depths.getValue(DataType.FLOAT) - 1
else -> throw IllegalArgumentException("invalid dt")
}
@ -260,10 +260,10 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
push((node as PtExpression).type)
}
}
require(numPushes==numPops+1) {
"RPN not balanced, pushes=$numPushes pops=$numPops"
require(numPushes==numPops+1 && numPushes==children.size) {
"RPN not balanced, pushes=$numPushes pops=$numPops childs=${children.size}"
}
return Pair(maxDepths, numPushes)
return maxDepths
}
fun finalOperator() = children.last() as PtRpnOperator

View File

@ -1013,8 +1013,29 @@ $repeatLabel lda $counterVar
when (pointerOffsetExpr) {
is PtRpn -> {
if(pointerOffsetExpr.children.size>3) {
println("TODO: RPN: too complicated pointerViaIndexRegisterPossible") // TODO RPN: split expression?
return null // expression is too complex, we need just a pointer var + index
val rightmostOperator = pointerOffsetExpr.finalOperator()
if(rightmostOperator.operator=="+") {
val rightmostOperand = pointerOffsetExpr.finalRightOperand()
if ((rightmostOperand is PtNumber && rightmostOperand.type in IntegerDatatypes && rightmostOperand.number.toInt() in 0..255)
|| (rightmostOperand is PtExpression && rightmostOperand.type == DataType.UBYTE)
|| (rightmostOperand is PtTypeCast && rightmostOperand.value.type == DataType.UBYTE)
) {
// split up the big expression in 2 parts so that we CAN use ZP,Y indexing after all
pointerOffsetExpr.children.removeLast()
pointerOffsetExpr.children.removeLast()
val tempvar = getTempVarName(DataType.UWORD)
assignExpressionToVariable(pointerOffsetExpr, tempvar, DataType.UWORD, pointerOffsetExpr.definingISub())
val smallExpr = PtRpn(DataType.UWORD, pointerOffsetExpr.position)
smallExpr.addRpnNode(PtIdentifier(tempvar, DataType.UWORD, pointerOffsetExpr.position))
smallExpr.addRpnNode(rightmostOperand)
smallExpr.addRpnNode(rightmostOperator)
smallExpr.parent = pointerOffsetExpr.parent
val result = pointerViaIndexRegisterPossible(smallExpr)
require(result != null)
return result
}
}
return null // expression is too complex
}
val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation()
operator=oper.operator
@ -2910,9 +2931,7 @@ $repeatLabel lda $counterVar
}
is PtRpn -> {
val addrExpr = expr.address as PtRpn
if(addrExpr.children.size>3)
println("TODO: RPN: too complicated translateDirectMemReadExpressionToRegAorStack") // TODO RPN: split expression?
if(addrExpr.children.size==3 && tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex")
} else {

View File

@ -146,9 +146,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
is PtRpn -> {
val addrExpr = value.address as PtRpn
if(addrExpr.children.size>3)
println("TODO: RPN: too complex translateNormalAssignment") // TODO RPN: split expression?
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
assignRegisterByte(assign.target, CpuRegister.A)
} else {
assignViaExprEval(value.address)
@ -926,10 +924,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
is PtRpn -> {
val addrExpr = value.address as PtRpn
if(addrExpr.children.size>3) {
println("TODO: RPN: too complex assignTypeCastedValue") // TODO RPN : split expression?
}
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
asmgen.out(" ldy #0")
assignRegisterpairWord(target, RegisterOrPair.AY)
} else {
@ -2859,9 +2854,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
asmgen.storeAIntoPointerVar(addressExpr)
}
addressExpr is PtRpn -> {
if(addressExpr.children.size>3)
println("TODO: RPN: too complex storeRegisterAInMemoryAddress $memoryAddress") // TODO RPN: split expression?
if(addressExpr.children.size!=3 || !asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true))
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true))
storeViaExprEval()
}
addressExpr is PtBinaryExpression -> {

View File

@ -13,7 +13,7 @@ internal class RpnExpressionAsmGen(
fun attemptAssignOptimizedExpr(assign: AsmAssignment): Boolean {
val value = assign.source.expression as PtRpn
println("TODO: RPN: optimized assignment ${value.position}") // TODO RPN: optimized assignment
println("TODO: RPN: optimized assignment ${value.position} maxdepth=${value.maxDepth()}") // TODO RPN: optimized assignment
// NOTE: don't forgot to evaluate the rest of the RPN expr as well
return false
}

View File

@ -1,9 +1,9 @@
TODO
====
BRANCH: Write some unit tests for the RPN.
BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt
Implement RPN codegen for IR.
BRANCH: Implement RPN codegen for IR.
For next minor release
^^^^^^^^^^^^^^^^^^^^^^

View File

@ -8,17 +8,18 @@
main {
sub start() {
test_stack.test()
uword xx=4000
ubyte a
ubyte b
ubyte c
ubyte d
ubyte a=11
ubyte b=22
ubyte c=33
cx16.r0 = peekw(xx+42)
; TODO cx16.r0 = peekw(a+xx+b+c+d+)
; TODO @(a+xx+b+c+d) = cx16.r0L
; cx16.r0 = peekw(xx+a+b+c)
; cx16.r1 = peekw(xx+a+b+c+42)
; pokew(xx+a+b+c, xx)
; pokew(xx+a+b+c+42, xx)
if a and a & $40 == 0
cx16.r0++
; if cx16.r0L in "derp" {
; xx++
@ -26,7 +27,6 @@ main {
;
; xx = xx+(3*func(xx)+xx*2*cx16.r0L)
; txt.print_uw(xx)
test_stack.test()
}
; sub func(uword value) -> uword {