mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
split some additional binary expressions to avoid stack-based evaluation
This commit is contained in:
parent
47c2c0376a
commit
32068a832a
@ -46,8 +46,32 @@ X = BinExpr X = LeftExpr
|
||||
|
||||
*/
|
||||
if(binExpr.operator in augmentAssignmentOperators && isSimpleTarget(assignment.target)) {
|
||||
if(assignment.target isSameAs binExpr.left || assignment.target isSameAs binExpr.right)
|
||||
if(assignment.target isSameAs binExpr.right)
|
||||
return noModifications
|
||||
if(assignment.target isSameAs binExpr.left) {
|
||||
if(binExpr.right.isSimple)
|
||||
return noModifications
|
||||
val leftBx = binExpr.left as? BinaryExpression
|
||||
if(leftBx!=null && (!leftBx.left.isSimple || !leftBx.right.isSimple))
|
||||
return noModifications
|
||||
val rightBx = binExpr.right as? BinaryExpression
|
||||
if(rightBx!=null && (!rightBx.left.isSimple || !rightBx.right.isSimple))
|
||||
return noModifications
|
||||
|
||||
// TODO below attempts to remove stack-based evaluated expressions, but sometimes the resulting code is BIGGER.
|
||||
val dt = assignment.target.inferType(program)
|
||||
if(!dt.isInteger)
|
||||
return noModifications
|
||||
val tempVar = IdentifierReference(getTempVarName(dt), binExpr.right.position)
|
||||
val assignTempVar = Assignment(
|
||||
AssignTarget(tempVar, null, null, binExpr.right.position),
|
||||
binExpr.right, binExpr.right.position
|
||||
)
|
||||
return listOf(
|
||||
IAstModification.InsertBefore(assignment, assignTempVar, assignment.parent as IStatementContainer),
|
||||
IAstModification.ReplaceNode(binExpr.right, tempVar.copy(), binExpr)
|
||||
)
|
||||
}
|
||||
|
||||
if(binExpr.right.isSimple) {
|
||||
val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position)
|
||||
|
@ -2,6 +2,9 @@ package prog8.optimizer
|
||||
|
||||
import prog8.ast.IBuiltinFunctions
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.InferredTypes
|
||||
import prog8.compilerinterface.CompilationOptions
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
@ -65,3 +68,15 @@ fun Program.splitBinaryExpressions(options: CompilationOptions, compTarget: ICom
|
||||
opti.visit(this)
|
||||
return opti.applyModifications()
|
||||
}
|
||||
|
||||
fun getTempVarName(dt: InferredTypes.InferredType): List<String> {
|
||||
return when {
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else...
|
||||
dt.istype(DataType.UBYTE) -> listOf("cx16", "r9L")
|
||||
dt.istype(DataType.BYTE) -> listOf("cx16", "r9sL")
|
||||
dt.istype(DataType.UWORD) -> listOf("cx16", "r9")
|
||||
dt.istype(DataType.WORD) -> listOf("cx16", "r9s")
|
||||
dt.isPassByReference -> listOf("cx16", "r9")
|
||||
else -> throw FatalAstException("invalid dt $dt")
|
||||
}
|
||||
}
|
||||
|
@ -120,16 +120,7 @@ class StatementOptimizer(private val program: Program,
|
||||
if(functionCallStatement.target.nameInSource !in listOf(listOf("pop"), listOf("popw")) && functionCallStatement.args.size==1) {
|
||||
val arg = functionCallStatement.args[0]
|
||||
if(!arg.isSimple && arg !is TypecastExpression && arg !is IFunctionCall) {
|
||||
val dt = arg.inferType(program)
|
||||
val name = when {
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else...
|
||||
dt.istype(DataType.UBYTE) -> listOf("cx16","r9L")
|
||||
dt.istype(DataType.BYTE) -> listOf("cx16","r9sL")
|
||||
dt.istype(DataType.UWORD) -> listOf("cx16","r9")
|
||||
dt.istype(DataType.WORD) -> listOf("cx16","r9s")
|
||||
dt.isPassByReference -> listOf("cx16","r9")
|
||||
else -> throw FatalAstException("invalid dt $dt")
|
||||
}
|
||||
val name = getTempVarName(arg.inferType(program))
|
||||
val tempvar = IdentifierReference(name, functionCallStatement.position)
|
||||
val assignTempvar = Assignment(AssignTarget(tempvar.copy(), null, null, functionCallStatement.position), arg, functionCallStatement.position)
|
||||
return listOf(
|
||||
|
@ -13,6 +13,7 @@ import prog8.ast.walk.IAstVisitor
|
||||
import prog8.compiler.astprocessing.isSubroutineParameter
|
||||
import prog8.compiler.target.AssemblyError
|
||||
import prog8.compilerinterface.*
|
||||
import prog8.optimizer.getTempVarName
|
||||
|
||||
|
||||
internal class BeforeAsmGenerationAstChanger(val program: Program, private val options: CompilationOptions,
|
||||
@ -228,16 +229,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
|
||||
val separateRightExpr = !expr.right.isSimple && expr.right !is IFunctionCall
|
||||
|
||||
if(separateLeftExpr) {
|
||||
val dt = expr.left.inferType(program)
|
||||
val name = when {
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else...
|
||||
dt.istype(DataType.UBYTE) -> listOf("cx16","r9L")
|
||||
dt.istype(DataType.BYTE) -> listOf("cx16","r9sL")
|
||||
dt.istype(DataType.UWORD) -> listOf("cx16","r9")
|
||||
dt.istype(DataType.WORD) -> listOf("cx16","r9s")
|
||||
dt.isPassByReference -> listOf("cx16","r9")
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
val name = getTempVarName(expr.left.inferType(program))
|
||||
leftOperandReplacement = IdentifierReference(name, expr.position)
|
||||
leftAssignment = Assignment(
|
||||
AssignTarget(IdentifierReference(name, expr.position), null, null, expr.position),
|
||||
|
@ -8,14 +8,11 @@ Use GoSub to call subroutines (statements):
|
||||
- [DONE] turn a regular subroutine call into assignments to the parameters + GoSub (take code from gosub branch)
|
||||
- [DONE] also do this for asmsubs taking >0 parameters
|
||||
|
||||
- make that push(x+1) doesn't use stack evaluation, via a temp var cx16.R9?
|
||||
|
||||
Optimize Function calls in expressions:
|
||||
- move args to assignments to params
|
||||
- add tempvar immediately in front of expression with the fuction call
|
||||
- replace the function call in the expression with the tempvar
|
||||
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -25,6 +25,8 @@ main {
|
||||
anglex+=500
|
||||
angley+=215
|
||||
anglez+=453
|
||||
sys.waitvsync()
|
||||
sys.waitvsync()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,9 @@ main {
|
||||
sub start() {
|
||||
test_stack.test()
|
||||
|
||||
ubyte x1 = 10
|
||||
ubyte x2 = 20
|
||||
ubyte x3 = 30
|
||||
|
||||
x1 += x2+x3 ; TODO WHY SLOW EVAL????
|
||||
x1 += x2-x3 ; TODO WHY SLOW EVAL????
|
||||
|
||||
txt.print_ub(x1)
|
||||
ubyte @shared x1 = 10
|
||||
ubyte @shared x2 = 20
|
||||
ubyte @shared x3 = 30
|
||||
|
||||
test_stack.test()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user