mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
improve codegen for for loops downto 0,1 when start value is not const
This commit is contained in:
parent
699a2bb7ab
commit
8eaf884f69
@ -48,22 +48,36 @@ internal class ForLoopsAsmGen(
|
|||||||
|
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
if (stepsize==1 || stepsize==-1) {
|
val varname = asmgen.asmVariableName(stmt.variable)
|
||||||
|
asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt))
|
||||||
|
if (stepsize==-1 && range.to.asConstInteger()==0) {
|
||||||
|
// simple loop downto 0 step -1
|
||||||
|
asmgen.out(loopLabel)
|
||||||
|
asmgen.translate(stmt.statements)
|
||||||
|
asmgen.out("""
|
||||||
|
dec $varname
|
||||||
|
lda $varname
|
||||||
|
cmp #255
|
||||||
|
bne $loopLabel""")
|
||||||
|
}
|
||||||
|
else if (stepsize==-1 && range.to.asConstInteger()==1) {
|
||||||
|
// simple loop downto 1 step -1
|
||||||
|
asmgen.out(loopLabel)
|
||||||
|
asmgen.translate(stmt.statements)
|
||||||
|
asmgen.out("""
|
||||||
|
dec $varname
|
||||||
|
bne $loopLabel""")
|
||||||
|
}
|
||||||
|
else if (stepsize==1 || stepsize==-1) {
|
||||||
// bytes array, step 1 or -1
|
// bytes array, step 1 or -1
|
||||||
|
|
||||||
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.variable)
|
|
||||||
asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt))
|
|
||||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
||||||
// pre-check for end already reached
|
// pre-check for end already reached
|
||||||
if(iterableDt==DataType.ARRAY_B) {
|
if(iterableDt==DataType.ARRAY_B) {
|
||||||
asmgen.out(" sta $modifiedLabel+1")
|
asmgen.out(" sta $modifiedLabel+1")
|
||||||
if(stepsize<0) {
|
if(stepsize<0) {
|
||||||
if(range.to.asConstInteger()==0 && asmgen.options.optimize) {
|
|
||||||
throw AssemblyError("downto 0 (signed byte) should have been replaced by an until-loop")
|
|
||||||
} else {
|
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
clc
|
clc
|
||||||
sbc $varname
|
sbc $varname
|
||||||
@ -71,7 +85,6 @@ internal class ForLoopsAsmGen(
|
|||||||
eor #${'$'}80
|
eor #${'$'}80
|
||||||
+ bpl $endLabel""")
|
+ bpl $endLabel""")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
sec
|
sec
|
||||||
@ -81,16 +94,12 @@ internal class ForLoopsAsmGen(
|
|||||||
+ bmi $endLabel""")
|
+ bmi $endLabel""")
|
||||||
} else {
|
} else {
|
||||||
if(stepsize<0) {
|
if(stepsize<0) {
|
||||||
if(range.to.asConstInteger()==0 && asmgen.options.optimize) {
|
|
||||||
throw AssemblyError("downto 0 (unsigned byte) should have been replaced by an until-loop")
|
|
||||||
} else {
|
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
cmp $varname
|
cmp $varname
|
||||||
beq +
|
beq +
|
||||||
bcs $endLabel
|
bcs $endLabel
|
||||||
+""")
|
+""")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
asmgen.out(" cmp $varname | bcc $endLabel")
|
asmgen.out(" cmp $varname | bcc $endLabel")
|
||||||
asmgen.out(" sta $modifiedLabel+1")
|
asmgen.out(" sta $modifiedLabel+1")
|
||||||
@ -110,8 +119,6 @@ $modifiedLabel cmp #0 ; modified
|
|||||||
// bytes, step >= 2 or <= -2
|
// bytes, step >= 2 or <= -2
|
||||||
|
|
||||||
// loop over byte range via loopvar
|
// loop over byte range via loopvar
|
||||||
val varname = asmgen.asmVariableName(stmt.variable)
|
|
||||||
asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt))
|
|
||||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
||||||
// pre-check for end already reached
|
// pre-check for end already reached
|
||||||
if(iterableDt==DataType.ARRAY_B) {
|
if(iterableDt==DataType.ARRAY_B) {
|
||||||
@ -165,15 +172,43 @@ $modifiedLabel cmp #0 ; modified
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||||
when {
|
|
||||||
|
|
||||||
// words, step 1 or -1
|
|
||||||
|
|
||||||
stepsize == 1 || stepsize == -1 -> {
|
|
||||||
if(range.to.asConstInteger()==0 && asmgen.options.optimize)
|
|
||||||
throw AssemblyError("downto 0 (words) should have been replaced by an until-loop")
|
|
||||||
val varname = asmgen.asmVariableName(stmt.variable)
|
val varname = asmgen.asmVariableName(stmt.variable)
|
||||||
assignLoopvarWord(stmt, range)
|
assignLoopvarWord(stmt, range)
|
||||||
|
if(stepsize==-1 && range.to.asConstInteger()==0) {
|
||||||
|
// simple loop downto 0 step -1 (words)
|
||||||
|
asmgen.out(loopLabel)
|
||||||
|
asmgen.translate(stmt.statements)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
bne ++
|
||||||
|
lda $varname+1
|
||||||
|
beq $endLabel
|
||||||
|
+ lda $varname
|
||||||
|
bne +
|
||||||
|
dec $varname+1
|
||||||
|
+ dec $varname""")
|
||||||
|
asmgen.jmp(loopLabel)
|
||||||
|
asmgen.out(endLabel)
|
||||||
|
}
|
||||||
|
else if (stepsize==-1 && range.to.asConstInteger()==1) {
|
||||||
|
// simple loop downto 1 step -1 (words)
|
||||||
|
asmgen.out(loopLabel)
|
||||||
|
asmgen.translate(stmt.statements)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
cmp #1
|
||||||
|
bne +
|
||||||
|
lda $varname+1
|
||||||
|
beq $endLabel
|
||||||
|
+ lda $varname
|
||||||
|
bne +
|
||||||
|
dec $varname+1
|
||||||
|
+ dec $varname""")
|
||||||
|
asmgen.jmp(loopLabel)
|
||||||
|
asmgen.out(endLabel)
|
||||||
|
}
|
||||||
|
else if (stepsize == 1 || stepsize == -1) {
|
||||||
|
// words, step 1 or -1
|
||||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -204,11 +239,8 @@ $modifiedLabel2 cmp #0 ; modified
|
|||||||
}
|
}
|
||||||
asmgen.out(endLabel)
|
asmgen.out(endLabel)
|
||||||
}
|
}
|
||||||
stepsize > 0 -> {
|
else if (stepsize > 0) {
|
||||||
|
|
||||||
// (u)words, step >= 2
|
// (u)words, step >= 2
|
||||||
val varname = asmgen.asmVariableName(stmt.variable)
|
|
||||||
assignLoopvarWord(stmt, range)
|
|
||||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -253,11 +285,9 @@ $modifiedLabel lda #0 ; modified
|
|||||||
$endLabel""")
|
$endLabel""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else {
|
||||||
|
|
||||||
// (u)words, step <= -2
|
// (u)words, step <= -2
|
||||||
val varname = asmgen.asmVariableName(stmt.variable)
|
|
||||||
assignLoopvarWord(stmt, range)
|
|
||||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -285,7 +315,6 @@ $modifiedLabel sbc #0 ; modified
|
|||||||
$endLabel""")
|
$endLabel""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
else -> throw AssemblyError("range expression can only be byte or word")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,35 +200,6 @@ class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val loopvarDt = forLoop.loopVarDt(program)
|
|
||||||
if(loopvarDt.istype(DataType.UWORD) || loopvarDt.istype(DataType.UBYTE)) {
|
|
||||||
|
|
||||||
fun incOrDec(inc: Boolean): Assignment {
|
|
||||||
val pos = forLoop.position
|
|
||||||
val loopVar = forLoop.loopVar
|
|
||||||
val addSubOne = BinaryExpression(loopVar.copy(), if(inc) "+" else "-", NumericLiteral.optimalInteger(1, pos), pos, false)
|
|
||||||
return Assignment(AssignTarget(loopVar.copy(), null, null, null, false, pos), addSubOne, AssignmentOrigin.USERCODE, pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range != null && range.to.constValue(program)?.number == 0.0 && range.step.constValue(program)?.number==-1.0) {
|
|
||||||
val fromExpr = range.from
|
|
||||||
if(fromExpr.constValue(program)==null) {
|
|
||||||
// FOR X = something DOWNTO 0 {...} --> X=something, DO { ... , X-- } UNTIL X=255 (or 65535 if uword)
|
|
||||||
val pos = forLoop.position
|
|
||||||
val checkValue = NumericLiteral(loopvarDt.getOr(DataType.UNDEFINED), if(loopvarDt.istype(DataType.UBYTE)) 255.0 else 65535.0, pos)
|
|
||||||
val condition = BinaryExpression(forLoop.loopVar.copy(), "==", checkValue, pos)
|
|
||||||
val decOne = incOrDec(false)
|
|
||||||
forLoop.body.statements.add(decOne)
|
|
||||||
val replacement = AnonymousScope(mutableListOf(
|
|
||||||
Assignment(AssignTarget(forLoop.loopVar.copy(), null, null, null, false, pos),
|
|
||||||
fromExpr, AssignmentOrigin.OPTIMIZER, pos),
|
|
||||||
UntilLoop(forLoop.body, condition, pos)
|
|
||||||
), pos)
|
|
||||||
return listOf(IAstModification.ReplaceNode(forLoop, replacement, parent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
improve codegen for for loops downto 0,1 when start value is not const.
|
Badapple has become 200 bytes LARGER than before!!
|
||||||
|
|
||||||
|
Fix testgfx2 screen text being uppercase (should be upper+lowercased)
|
||||||
|
|
||||||
|
assembler seems to crash on hello4...
|
||||||
|
|
||||||
|
|
||||||
IR: Improve codegen for for loops downto 0. (BPL if <=127 etc like 6502 codegen?)
|
IR: Improve codegen for for loops downto 0. (BPL if <=127 etc like 6502 codegen?)
|
||||||
|
@ -7,28 +7,29 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
ubyte x
|
ubyte x
|
||||||
uword w
|
uword w
|
||||||
uword @shared wstart=50000
|
uword @shared wstart=1000
|
||||||
ubyte @shared bstart=127
|
ubyte @shared bstart=100
|
||||||
uword y
|
uword y
|
||||||
uword duration
|
uword duration
|
||||||
byte b
|
byte b
|
||||||
|
|
||||||
|
|
||||||
cbm.SETTIM(0,0,0)
|
cbm.SETTIM(0,0,0)
|
||||||
repeat 5000 {
|
repeat 1000 {
|
||||||
y=0
|
y=0
|
||||||
; for x in bstart downto 0 {
|
for w in wstart downto 0 {
|
||||||
; y++
|
|
||||||
; }
|
|
||||||
x = bstart
|
|
||||||
do {
|
|
||||||
y++
|
y++
|
||||||
x--
|
}
|
||||||
} until x==255
|
for w in wstart downto 1 {
|
||||||
|
y++
|
||||||
|
}
|
||||||
|
; TODO words
|
||||||
}
|
}
|
||||||
txt.print_uw(cbm.RDTIM16())
|
txt.print_uw(cbm.RDTIM16())
|
||||||
if y!=128
|
if y!=2001
|
||||||
txt.print("error 1\n")
|
txt.print("error\n")
|
||||||
|
|
||||||
|
; without new loops: $26e, 482 jiffies
|
||||||
|
|
||||||
/*
|
/*
|
||||||
for w in 65535 downto 0 {
|
for w in 65535 downto 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user