mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +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(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
|
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) {
|
if(binExpr.right.isSimple) {
|
||||||
val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position)
|
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.IBuiltinFunctions
|
||||||
import prog8.ast.Program
|
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.CompilationOptions
|
||||||
import prog8.compilerinterface.ICompilationTarget
|
import prog8.compilerinterface.ICompilationTarget
|
||||||
import prog8.compilerinterface.IErrorReporter
|
import prog8.compilerinterface.IErrorReporter
|
||||||
@ -65,3 +68,15 @@ fun Program.splitBinaryExpressions(options: CompilationOptions, compTarget: ICom
|
|||||||
opti.visit(this)
|
opti.visit(this)
|
||||||
return opti.applyModifications()
|
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) {
|
if(functionCallStatement.target.nameInSource !in listOf(listOf("pop"), listOf("popw")) && functionCallStatement.args.size==1) {
|
||||||
val arg = functionCallStatement.args[0]
|
val arg = functionCallStatement.args[0]
|
||||||
if(!arg.isSimple && arg !is TypecastExpression && arg !is IFunctionCall) {
|
if(!arg.isSimple && arg !is TypecastExpression && arg !is IFunctionCall) {
|
||||||
val dt = arg.inferType(program)
|
val name = getTempVarName(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 tempvar = IdentifierReference(name, functionCallStatement.position)
|
val tempvar = IdentifierReference(name, functionCallStatement.position)
|
||||||
val assignTempvar = Assignment(AssignTarget(tempvar.copy(), null, null, functionCallStatement.position), arg, functionCallStatement.position)
|
val assignTempvar = Assignment(AssignTarget(tempvar.copy(), null, null, functionCallStatement.position), arg, functionCallStatement.position)
|
||||||
return listOf(
|
return listOf(
|
||||||
|
@ -13,6 +13,7 @@ import prog8.ast.walk.IAstVisitor
|
|||||||
import prog8.compiler.astprocessing.isSubroutineParameter
|
import prog8.compiler.astprocessing.isSubroutineParameter
|
||||||
import prog8.compiler.target.AssemblyError
|
import prog8.compiler.target.AssemblyError
|
||||||
import prog8.compilerinterface.*
|
import prog8.compilerinterface.*
|
||||||
|
import prog8.optimizer.getTempVarName
|
||||||
|
|
||||||
|
|
||||||
internal class BeforeAsmGenerationAstChanger(val program: Program, private val options: CompilationOptions,
|
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
|
val separateRightExpr = !expr.right.isSimple && expr.right !is IFunctionCall
|
||||||
|
|
||||||
if(separateLeftExpr) {
|
if(separateLeftExpr) {
|
||||||
val dt = expr.left.inferType(program)
|
val name = getTempVarName(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")
|
|
||||||
}
|
|
||||||
leftOperandReplacement = IdentifierReference(name, expr.position)
|
leftOperandReplacement = IdentifierReference(name, expr.position)
|
||||||
leftAssignment = Assignment(
|
leftAssignment = Assignment(
|
||||||
AssignTarget(IdentifierReference(name, expr.position), null, null, expr.position),
|
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] 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
|
- [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:
|
Optimize Function calls in expressions:
|
||||||
- move args to assignments to params
|
- move args to assignments to params
|
||||||
- add tempvar immediately in front of expression with the fuction call
|
- add tempvar immediately in front of expression with the fuction call
|
||||||
- replace the function call in the expression with the tempvar
|
- replace the function call in the expression with the tempvar
|
||||||
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ main {
|
|||||||
anglex+=500
|
anglex+=500
|
||||||
angley+=215
|
angley+=215
|
||||||
anglez+=453
|
anglez+=453
|
||||||
|
sys.waitvsync()
|
||||||
|
sys.waitvsync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,9 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
|
|
||||||
ubyte x1 = 10
|
ubyte @shared x1 = 10
|
||||||
ubyte x2 = 20
|
ubyte @shared x2 = 20
|
||||||
ubyte x3 = 30
|
ubyte @shared x3 = 30
|
||||||
|
|
||||||
x1 += x2+x3 ; TODO WHY SLOW EVAL????
|
|
||||||
x1 += x2-x3 ; TODO WHY SLOW EVAL????
|
|
||||||
|
|
||||||
txt.print_ub(x1)
|
|
||||||
|
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user