From afd155ac4f93f74c5e10db353aec89bebfb5e39e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 20 Nov 2020 22:15:14 +0100 Subject: [PATCH] optimize for loops over non const range, without translateExpression() --- .../target/c64/codegen/ForLoopsAsmGen.kt | 97 +++++---------- examples/test.p8 | 115 +++++++++++------- examples/test_stack.p8 | 47 +++++++ 3 files changed, 149 insertions(+), 110 deletions(-) create mode 100644 examples/test_stack.p8 diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt index 105e26b8a..b44151931 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt @@ -1,20 +1,16 @@ package prog8.compiler.target.c64.codegen import prog8.ast.Program +import prog8.ast.base.ArrayElementTypes import prog8.ast.base.DataType +import prog8.ast.base.RegisterOrPair import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.RangeExpr import prog8.ast.statements.ForLoop import prog8.compiler.AssemblyError -import prog8.compiler.target.c64.codegen.assignment.AsmAssignSource -import prog8.compiler.target.c64.codegen.assignment.AsmAssignTarget -import prog8.compiler.target.c64.codegen.assignment.AsmAssignment -import prog8.compiler.target.c64.codegen.assignment.TargetStorageKind import prog8.compiler.toHex import kotlin.math.absoluteValue -// todo reduce use of stack eval translateExpression() - internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal fun translate(stmt: ForLoop) { @@ -53,23 +49,17 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen: val incdec = if(stepsize==1) "inc" else "dec" // loop over byte range via loopvar val varname = asmgen.asmVariableName(stmt.loopVar) - asmgen.translateExpression(range.to) - asmgen.translateExpression(range.from) + asmgen.assignExpressionToVariable(range.from, varname, ArrayElementTypes.getValue(iterableDt), null) + asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayElementTypes.getValue(iterableDt), null) + asmgen.out(loopLabel) + asmgen.translate(stmt.body) asmgen.out(""" - inx - lda P8ESTACK_LO,x - sta $varname - lda P8ESTACK_LO+1,x - sta $modifiedLabel+1 -$loopLabel""") - asmgen.translate(stmt.body) - asmgen.out(""" lda $varname $modifiedLabel cmp #0 ; modified beq $endLabel $incdec $varname jmp $loopLabel -$endLabel inx""") +$endLabel""") } else { @@ -77,18 +67,11 @@ $endLabel inx""") // loop over byte range via loopvar val varname = asmgen.asmVariableName(stmt.loopVar) - asmgen.translateExpression(range.to) - asmgen.translateExpression(range.from) - asmgen.out(""" - inx - lda P8ESTACK_LO,x - sta $varname - lda P8ESTACK_LO+1,x - sta $modifiedLabel+1 -$loopLabel""") + asmgen.assignExpressionToVariable(range.from, varname, ArrayElementTypes.getValue(iterableDt), null) + asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayElementTypes.getValue(iterableDt), null) + asmgen.out(loopLabel) asmgen.translate(stmt.body) - asmgen.out(""" - lda $varname""") + asmgen.out(" lda $varname") if(stepsize>0) { asmgen.out(""" clc @@ -105,8 +88,7 @@ $modifiedLabel cmp #0 ; modified $modifiedLabel cmp #0 ; modified bcs $loopLabel""") } - asmgen.out(""" -$endLabel inx""") + asmgen.out(endLabel) } } DataType.ARRAY_W, DataType.ARRAY_UW -> { @@ -115,13 +97,11 @@ $endLabel inx""") // words, step 1 or -1 stepsize == 1 || stepsize == -1 -> { - asmgen.translateExpression(range.to) - assignLoopvar(stmt, range) val varname = asmgen.asmVariableName(stmt.loopVar) + assignLoopvar(stmt, range) + asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) asmgen.out(""" - lda P8ESTACK_HI+1,x - sta $modifiedLabel+1 - lda P8ESTACK_LO+1,x + sty $modifiedLabel+1 sta $modifiedLabel2+1 $loopLabel""") asmgen.translate(stmt.body) @@ -148,21 +128,17 @@ $modifiedLabel2 cmp #0 ; modified jmp $loopLabel""") } asmgen.out(endLabel) - asmgen.out(" inx") } stepsize > 0 -> { // (u)words, step >= 2 - asmgen.translateExpression(range.to) - asmgen.out(""" - lda P8ESTACK_HI+1,x - sta $modifiedLabel+1 - lda P8ESTACK_LO+1,x - sta $modifiedLabel2+1 - """) - assignLoopvar(stmt, range) val varname = asmgen.asmVariableName(stmt.loopVar) - asmgen.out(loopLabel) + assignLoopvar(stmt, range) + asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) + asmgen.out(""" + sty $modifiedLabel+1 + sta $modifiedLabel2+1 +$loopLabel""") asmgen.translate(stmt.body) if (iterableDt == DataType.ARRAY_UW) { @@ -181,7 +157,7 @@ $modifiedLabel2 lda #0 ; modified cmp $varname bcc $endLabel bcs $loopLabel -$endLabel inx""") +$endLabel""") } else { asmgen.out(""" lda $varname @@ -198,22 +174,19 @@ $modifiedLabel lda #0 ; modified bvc + eor #$80 + bpl $loopLabel -$endLabel inx""") +$endLabel""") } } else -> { // (u)words, step <= -2 - asmgen.translateExpression(range.to) - asmgen.out(""" - lda P8ESTACK_HI+1,x - sta $modifiedLabel+1 - lda P8ESTACK_LO+1,x - sta $modifiedLabel2+1 - """) - assignLoopvar(stmt, range) val varname = asmgen.asmVariableName(stmt.loopVar) - asmgen.out(loopLabel) + assignLoopvar(stmt, range) + asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) + asmgen.out(""" + sty $modifiedLabel+1 + sta $modifiedLabel2+1 +$loopLabel""") asmgen.translate(stmt.body) if(iterableDt==DataType.ARRAY_UW) { @@ -231,7 +204,7 @@ $modifiedLabel cmp #0 ; modified lda $varname $modifiedLabel2 cmp #0 ; modified bcs $loopLabel -$endLabel inx""") +$endLabel""") } else { asmgen.out(""" lda $varname @@ -249,7 +222,7 @@ $modifiedLabel sbc #0 ; modified bvc + eor #$80 + bpl $loopLabel -$endLabel inx""") +$endLabel""") } } } @@ -611,10 +584,6 @@ $endLabel""") asmgen.loopEndLabels.pop() } - private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) { - val target = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, stmt.loopVarDt(program).typeOrElse(DataType.STRUCT), stmt.definingSubroutine(), variableAsmName=asmgen.asmVariableName(stmt.loopVar)) - val src = AsmAssignSource.fromAstSource(range.from, program, asmgen).adjustSignedUnsigned(target) - val assign = AsmAssignment(src, target, false, range.position) - asmgen.translateNormalAssignment(assign) - } + private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) = + asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).typeOrElse(DataType.STRUCT), stmt.definingSubroutine()) } diff --git a/examples/test.p8 b/examples/test.p8 index 286da1f67..d2e3022e3 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,62 +1,85 @@ %import textio %import floats %zeropage basicsafe +%import test_stack main { sub start() { - ubyte ub = 30 - byte bb = -30 - float f1 + ubyte ub + byte bb + uword uw + word ww - f1 = ub - floats.print_f(f1) - txt.chrout('\n') - f1 = bb - floats.print_f(f1) + ubyte arrub = 10 + uword arruw = 10 + byte arrb = 10 + word arrw = 10 + + test_stack.test() + + for ub in 0 to arrub step 2 { + txt.print_ub(ub) + txt.chrout(',') + } txt.chrout('\n') - testX() - } + for ub in 5 to arrub step 2 { + txt.print_ub(ub) + txt.chrout(',') + } + txt.chrout('\n') - sub ding(ubyte argument) -> ubyte { - txt.chrout(' ') - return argument*2 - } + for uw in 0 to arruw step 2 { + txt.print_uw(uw) + txt.chrout(',') + } + txt.chrout('\n') - sub dingw(uword argument) -> uword { - txt.chrout(' ') - return argument*2 - } + for uw in 5 to arruw step 2 { + txt.print_uw(uw) + txt.chrout(',') + } + txt.chrout('\n') - asmsub testX() { - %asm {{ - stx _saveX - lda #13 - jsr txt.chrout - lda #'x' - jsr txt.chrout - lda #'=' - jsr txt.chrout - lda _saveX - jsr txt.print_ub - lda #' ' - jsr txt.chrout - lda #'s' - jsr txt.chrout - lda #'p' - jsr txt.chrout - lda #'=' - jsr txt.chrout - tsx - txa - jsr txt.print_ub - lda #13 - jsr txt.chrout - ldx _saveX - rts -_saveX .byte 0 - }} + for bb in 0 to arrb step 2 { + txt.print_b(bb) + txt.chrout(',') + } + txt.chrout('\n') + + for bb in -2 to arrb-2 step 2 { + txt.print_b(bb) + txt.chrout(',') + } + txt.chrout('\n') + + for ww in 0 to arrw step 2 { + txt.print_w(ww) + txt.chrout(',') + } + txt.chrout('\n') + + for ww in -2 to arrw-2 step 2{ + txt.print_w(ww) + txt.chrout(',') + } + txt.chrout('\n') + + for bb in arrb-2 to -2 step -2 { + txt.print_b(bb) + txt.chrout(',') + } + txt.chrout('\n') + + for ww in arrw-2 to -2 step -2 { + txt.print_w(ww) + txt.chrout(',') + } + txt.chrout('\n') + + test_stack.test() + txt.chrout('\n') } } diff --git a/examples/test_stack.p8 b/examples/test_stack.p8 new file mode 100644 index 000000000..a079cca48 --- /dev/null +++ b/examples/test_stack.p8 @@ -0,0 +1,47 @@ + +test_stack { + + asmsub test() { + %asm {{ + stx _saveX + lda #13 + jsr txt.chrout + lda #'-' + ldy #12 +- jsr txt.chrout + dey + bne - + lda #13 + jsr txt.chrout + lda #'x' + jsr txt.chrout + lda #'=' + jsr txt.chrout + lda _saveX + jsr txt.print_ub + lda #' ' + jsr txt.chrout + lda #'s' + jsr txt.chrout + lda #'p' + jsr txt.chrout + lda #'=' + jsr txt.chrout + tsx + txa + jsr txt.print_ub + lda #13 + jsr txt.chrout + lda #'-' + ldy #12 +- jsr txt.chrout + dey + bne - + lda #13 + jsr txt.chrout + ldx _saveX + rts +_saveX .byte 0 + }} + } +}