implementing Rpn optimizations 2

This commit is contained in:
Irmen de Jong 2023-03-18 11:04:51 +01:00
parent e8bebe5a75
commit 94c06e13f4
7 changed files with 38 additions and 13 deletions

View File

@ -74,6 +74,9 @@ class PtProgram(
fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn { fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn {
fun makeRpn(expr: PtExpression): PtRpn { fun makeRpn(expr: PtExpression): PtRpn {
val rpn = PtRpn(expr.type, expr.position) val rpn = PtRpn(expr.type, expr.position)
if(expr is PtBinaryExpression)
rpn.addRpnNode(transformToRPN(expr))
else
rpn.addRpnNode(expr) rpn.addRpnNode(expr)
return rpn return rpn
} }

View File

@ -175,6 +175,7 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
} }
} }
else { else {
require(node !is PtBinaryExpression)
children.add(node) children.add(node)
node.parent = this node.parent = this
} }

View File

@ -52,7 +52,6 @@ class AsmGen6502Internal (
private val assignmentAsmGen = AssignmentAsmGen(program, symbolTable, this, allocator) private val assignmentAsmGen = AssignmentAsmGen(program, symbolTable, this, allocator)
private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator) private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator)
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen) private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
private val rpnAssignmentAsmGen = RpnExpressionAsmGen(program, symbolTable, this)
fun compileToAssembly(): IAssemblyProgram? { fun compileToAssembly(): IAssemblyProgram? {
@ -1013,8 +1012,10 @@ $repeatLabel lda $counterVar
when (pointerOffsetExpr) { when (pointerOffsetExpr) {
is PtRpn -> { is PtRpn -> {
if(pointerOffsetExpr.children.size>3) if(pointerOffsetExpr.children.size>3) {
println("TODO: RPN: too complicated pointerViaIndexRegisterPossible") // TODO RPN
return null // expression is too complex, we need just a pointer var + index return null // expression is too complex, we need just a pointer var + index
}
val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation() val (leftNode, oper, rightNode) = pointerOffsetExpr.finalOperation()
operator=oper.operator operator=oper.operator
if (leftNode !is PtExpression || rightNode !is PtExpression) return null if (leftNode !is PtExpression || rightNode !is PtExpression) return null
@ -2909,6 +2910,8 @@ $repeatLabel lda $counterVar
} }
is PtRpn -> { is PtRpn -> {
val addrExpr = expr.address as PtRpn val addrExpr = expr.address as PtRpn
if(addrExpr.children.size>3)
println("TODO: RPN: too complicated translateDirectMemReadExpressionToRegAorStack") // TODO RPN
if(addrExpr.children.size==3 && tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { if(addrExpr.children.size==3 && tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
if(pushResultOnEstack) if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex") out(" sta P8ESTACK_LO,x | dex")

View File

@ -682,6 +682,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
return return
} }
} }
} else {
println("TODO: RPN: too complicated PokeW") // TODO RPN
} }
} }
is PtBinaryExpression -> { is PtBinaryExpression -> {
@ -763,7 +765,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
pla""") pla""")
} else fallback() } else fallback()
} else fallback() } else fallback()
} else fallback() } else {
println("TODO: RPN: too complicated PeekW") // TODO RPN
fallback()
}
} }
is PtBinaryExpression -> { is PtBinaryExpression -> {
if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) { if(addrExpr.operator=="+" && addrExpr.left is PtIdentifier && addrExpr.right is PtNumber) {

View File

@ -248,21 +248,22 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
private fun translateRpnExpression(expr: PtRpn) { private fun translateRpnExpression(expr: PtRpn) {
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
val oper = expr.finalOperator() val oper = expr.finalOperator()
val left = expr.finalLeftOperand() as? PtExpression
val leftDt = oper.leftType val leftDt = oper.leftType
val rightDt = oper.rightType val rightDt = oper.rightType
// comparison against zero // comparison against zero
if(oper.operator in ComparisonOperators) { if(left != null && oper.operator in ComparisonOperators) {
if(leftDt in NumericDatatypes && rightDt in NumericDatatypes) { if(leftDt in NumericDatatypes && rightDt in NumericDatatypes) {
val rightVal = (expr.finalRightOperand() as PtExpression).asConstInteger() val rightVal = (expr.finalRightOperand() as PtExpression).asConstInteger()
if(rightVal==0) if(rightVal==0)
return translateComparisonWithZero(expr.finalLeftOperand() as PtExpression, leftDt, oper.operator) return translateComparisonWithZero(left, leftDt, oper.operator)
} }
} }
// string compare // string compare
if(leftDt==DataType.STR && rightDt==DataType.STR && oper.operator in ComparisonOperators) { if(left!=null && leftDt==DataType.STR && rightDt==DataType.STR && oper.operator in ComparisonOperators) {
return translateCompareStrings(expr.finalLeftOperand() as PtExpression, oper.operator, expr.finalRightOperand() as PtExpression) return translateCompareStrings(left, oper.operator, expr.finalRightOperand() as PtExpression)
} }
// TODO: RPN: add the other optimizations that BinaryExpression has, to avoid eval stack usage // TODO: RPN: add the other optimizations that BinaryExpression has, to avoid eval stack usage
@ -277,7 +278,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
if(it is PtRpnOperator) { if(it is PtRpnOperator) {
when(it.leftType) { when(it.leftType) {
in ByteDatatypes -> translateBinaryOperatorBytes(it.operator, it.leftType) in ByteDatatypes -> translateBinaryOperatorBytes(it.operator, it.leftType)
in WordDatatypes -> translateBinaryOperatorWords(it.operator, it.leftType) in WordDatatypes, in PassByReferenceDatatypes -> translateBinaryOperatorWords(it.operator, it.leftType)
DataType.FLOAT -> translateBinaryOperatorFloats(it.operator) DataType.FLOAT -> translateBinaryOperatorFloats(it.operator)
else -> throw AssemblyError("non-numerical datatype ${it.leftType}") else -> throw AssemblyError("non-numerical datatype ${it.leftType}")
} }
@ -292,6 +293,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
private fun translateExpression(expr: PtBinaryExpression) { private fun translateExpression(expr: PtBinaryExpression) {
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
require(!program.binaryExpressionsAreRPN)
val leftDt = expr.left.type val leftDt = expr.left.type
val rightDt = expr.right.type val rightDt = expr.right.type
// see if we can apply some optimized routines still // see if we can apply some optimized routines still

View File

@ -146,6 +146,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
is PtRpn -> { is PtRpn -> {
val addrExpr = value.address as PtRpn val addrExpr = value.address as PtRpn
if(addrExpr.children.size>3)
println("TODO: RPN: too complex translateNormalAssignment") // TODO RPN
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
assignRegisterByte(assign.target, CpuRegister.A) assignRegisterByte(assign.target, CpuRegister.A)
} else { } else {
@ -307,6 +309,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignRegisterByte(assign.target, CpuRegister.A) assignRegisterByte(assign.target, CpuRegister.A)
} }
is PtBinaryExpression -> { is PtBinaryExpression -> {
require(!program.binaryExpressionsAreRPN)
if(!attemptAssignOptimizedBinexpr(value, assign)) { if(!attemptAssignOptimizedBinexpr(value, assign)) {
// All remaining binary expressions just evaluate via the stack for now. // All remaining binary expressions just evaluate via the stack for now.
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
@ -923,6 +926,9 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
is PtRpn -> { is PtRpn -> {
val addrExpr = value.address as PtRpn val addrExpr = value.address as PtRpn
if(addrExpr.children.size>3) {
println("TODO: RPN: too complex assignTypeCastedValue") // TODO RPN
}
if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) { if(addrExpr.children.size==3 && asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.finalOperator().operator, false)) {
asmgen.out(" ldy #0") asmgen.out(" ldy #0")
assignRegisterpairWord(target, RegisterOrPair.AY) assignRegisterpairWord(target, RegisterOrPair.AY)
@ -2853,6 +2859,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
asmgen.storeAIntoPointerVar(addressExpr) asmgen.storeAIntoPointerVar(addressExpr)
} }
addressExpr is PtRpn -> { addressExpr is PtRpn -> {
if(addressExpr.children.size>3)
println("TODO: RPN: too complex storeRegisterAInMemoryAddress $memoryAddress") // TODO RPN
if(addressExpr.children.size!=3 || !asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true)) if(addressExpr.children.size!=3 || !asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.finalOperator().operator, true))
storeViaExprEval() storeViaExprEval()
} }

View File

@ -9,11 +9,14 @@ main {
sub start() { sub start() {
test_stack.test() test_stack.test()
uword xx=32 uword xx=4000
cx16.r0L = 3 ubyte a
ubyte b
ubyte c
ubyte d
cx16.r0 = peekw(xx + 44) cx16.r0 = peekw(a+xx+b+c+d)
@(xx+44) = cx16.r0L ; TODO @(a+xx+b+c+d) = cx16.r0L
; if cx16.r0L in "derp" { ; if cx16.r0L in "derp" {
; xx++ ; xx++