optimize for loops over non const range, without translateExpression()

This commit is contained in:
Irmen de Jong 2020-11-20 22:15:14 +01:00
parent ee724eb4f1
commit afd155ac4f
3 changed files with 149 additions and 110 deletions

View File

@ -1,20 +1,16 @@
package prog8.compiler.target.c64.codegen package prog8.compiler.target.c64.codegen
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.ArrayElementTypes
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.base.RegisterOrPair
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.RangeExpr import prog8.ast.expressions.RangeExpr
import prog8.ast.statements.ForLoop import prog8.ast.statements.ForLoop
import prog8.compiler.AssemblyError 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 prog8.compiler.toHex
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
// todo reduce use of stack eval translateExpression()
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
internal fun translate(stmt: ForLoop) { internal fun translate(stmt: ForLoop) {
@ -53,15 +49,9 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
val incdec = if(stepsize==1) "inc" else "dec" val incdec = if(stepsize==1) "inc" else "dec"
// loop over byte range via loopvar // loop over byte range via loopvar
val varname = asmgen.asmVariableName(stmt.loopVar) val varname = asmgen.asmVariableName(stmt.loopVar)
asmgen.translateExpression(range.to) asmgen.assignExpressionToVariable(range.from, varname, ArrayElementTypes.getValue(iterableDt), null)
asmgen.translateExpression(range.from) asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayElementTypes.getValue(iterableDt), null)
asmgen.out(""" asmgen.out(loopLabel)
inx
lda P8ESTACK_LO,x
sta $varname
lda P8ESTACK_LO+1,x
sta $modifiedLabel+1
$loopLabel""")
asmgen.translate(stmt.body) asmgen.translate(stmt.body)
asmgen.out(""" asmgen.out("""
lda $varname lda $varname
@ -69,7 +59,7 @@ $modifiedLabel cmp #0 ; modified
beq $endLabel beq $endLabel
$incdec $varname $incdec $varname
jmp $loopLabel jmp $loopLabel
$endLabel inx""") $endLabel""")
} else { } else {
@ -77,18 +67,11 @@ $endLabel inx""")
// loop over byte range via loopvar // loop over byte range via loopvar
val varname = asmgen.asmVariableName(stmt.loopVar) val varname = asmgen.asmVariableName(stmt.loopVar)
asmgen.translateExpression(range.to) asmgen.assignExpressionToVariable(range.from, varname, ArrayElementTypes.getValue(iterableDt), null)
asmgen.translateExpression(range.from) asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayElementTypes.getValue(iterableDt), null)
asmgen.out(""" asmgen.out(loopLabel)
inx
lda P8ESTACK_LO,x
sta $varname
lda P8ESTACK_LO+1,x
sta $modifiedLabel+1
$loopLabel""")
asmgen.translate(stmt.body) asmgen.translate(stmt.body)
asmgen.out(""" asmgen.out(" lda $varname")
lda $varname""")
if(stepsize>0) { if(stepsize>0) {
asmgen.out(""" asmgen.out("""
clc clc
@ -105,8 +88,7 @@ $modifiedLabel cmp #0 ; modified
$modifiedLabel cmp #0 ; modified $modifiedLabel cmp #0 ; modified
bcs $loopLabel""") bcs $loopLabel""")
} }
asmgen.out(""" asmgen.out(endLabel)
$endLabel inx""")
} }
} }
DataType.ARRAY_W, DataType.ARRAY_UW -> { DataType.ARRAY_W, DataType.ARRAY_UW -> {
@ -115,13 +97,11 @@ $endLabel inx""")
// words, step 1 or -1 // words, step 1 or -1
stepsize == 1 || stepsize == -1 -> { stepsize == 1 || stepsize == -1 -> {
asmgen.translateExpression(range.to)
assignLoopvar(stmt, range)
val varname = asmgen.asmVariableName(stmt.loopVar) val varname = asmgen.asmVariableName(stmt.loopVar)
assignLoopvar(stmt, range)
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
asmgen.out(""" asmgen.out("""
lda P8ESTACK_HI+1,x sty $modifiedLabel+1
sta $modifiedLabel+1
lda P8ESTACK_LO+1,x
sta $modifiedLabel2+1 sta $modifiedLabel2+1
$loopLabel""") $loopLabel""")
asmgen.translate(stmt.body) asmgen.translate(stmt.body)
@ -148,21 +128,17 @@ $modifiedLabel2 cmp #0 ; modified
jmp $loopLabel""") jmp $loopLabel""")
} }
asmgen.out(endLabel) asmgen.out(endLabel)
asmgen.out(" inx")
} }
stepsize > 0 -> { stepsize > 0 -> {
// (u)words, step >= 2 // (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) 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) asmgen.translate(stmt.body)
if (iterableDt == DataType.ARRAY_UW) { if (iterableDt == DataType.ARRAY_UW) {
@ -181,7 +157,7 @@ $modifiedLabel2 lda #0 ; modified
cmp $varname cmp $varname
bcc $endLabel bcc $endLabel
bcs $loopLabel bcs $loopLabel
$endLabel inx""") $endLabel""")
} else { } else {
asmgen.out(""" asmgen.out("""
lda $varname lda $varname
@ -198,22 +174,19 @@ $modifiedLabel lda #0 ; modified
bvc + bvc +
eor #$80 eor #$80
+ bpl $loopLabel + bpl $loopLabel
$endLabel inx""") $endLabel""")
} }
} }
else -> { else -> {
// (u)words, step <= -2 // (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) 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) asmgen.translate(stmt.body)
if(iterableDt==DataType.ARRAY_UW) { if(iterableDt==DataType.ARRAY_UW) {
@ -231,7 +204,7 @@ $modifiedLabel cmp #0 ; modified
lda $varname lda $varname
$modifiedLabel2 cmp #0 ; modified $modifiedLabel2 cmp #0 ; modified
bcs $loopLabel bcs $loopLabel
$endLabel inx""") $endLabel""")
} else { } else {
asmgen.out(""" asmgen.out("""
lda $varname lda $varname
@ -249,7 +222,7 @@ $modifiedLabel sbc #0 ; modified
bvc + bvc +
eor #$80 eor #$80
+ bpl $loopLabel + bpl $loopLabel
$endLabel inx""") $endLabel""")
} }
} }
} }
@ -611,10 +584,6 @@ $endLabel""")
asmgen.loopEndLabels.pop() asmgen.loopEndLabels.pop()
} }
private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) { 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)) asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).typeOrElse(DataType.STRUCT), stmt.definingSubroutine())
val src = AsmAssignSource.fromAstSource(range.from, program, asmgen).adjustSignedUnsigned(target)
val assign = AsmAssignment(src, target, false, range.position)
asmgen.translateNormalAssignment(assign)
}
} }

View File

@ -1,62 +1,85 @@
%import textio %import textio
%import floats %import floats
%zeropage basicsafe %zeropage basicsafe
%import test_stack
main { main {
sub start() { sub start() {
ubyte ub = 30 ubyte ub
byte bb = -30 byte bb
float f1 uword uw
word ww
f1 = ub ubyte arrub = 10
floats.print_f(f1) uword arruw = 10
txt.chrout('\n') byte arrb = 10
f1 = bb word arrw = 10
floats.print_f(f1)
test_stack.test()
for ub in 0 to arrub step 2 {
txt.print_ub(ub)
txt.chrout(',')
}
txt.chrout('\n') 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 { for uw in 0 to arruw step 2 {
txt.chrout(' ') txt.print_uw(uw)
return argument*2 txt.chrout(',')
} }
txt.chrout('\n')
sub dingw(uword argument) -> uword { for uw in 5 to arruw step 2 {
txt.chrout(' ') txt.print_uw(uw)
return argument*2 txt.chrout(',')
} }
txt.chrout('\n')
asmsub testX() { for bb in 0 to arrb step 2 {
%asm {{ txt.print_b(bb)
stx _saveX txt.chrout(',')
lda #13 }
jsr txt.chrout txt.chrout('\n')
lda #'x'
jsr txt.chrout for bb in -2 to arrb-2 step 2 {
lda #'=' txt.print_b(bb)
jsr txt.chrout txt.chrout(',')
lda _saveX }
jsr txt.print_ub txt.chrout('\n')
lda #' '
jsr txt.chrout for ww in 0 to arrw step 2 {
lda #'s' txt.print_w(ww)
jsr txt.chrout txt.chrout(',')
lda #'p' }
jsr txt.chrout txt.chrout('\n')
lda #'='
jsr txt.chrout for ww in -2 to arrw-2 step 2{
tsx txt.print_w(ww)
txa txt.chrout(',')
jsr txt.print_ub }
lda #13 txt.chrout('\n')
jsr txt.chrout
ldx _saveX for bb in arrb-2 to -2 step -2 {
rts txt.print_b(bb)
_saveX .byte 0 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')
} }
} }

47
examples/test_stack.p8 Normal file
View File

@ -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
}}
}
}