fix IR long comparisons (used in for loops for instance)

This commit is contained in:
Irmen de Jong
2026-03-01 01:17:22 +01:00
parent 10d80d0274
commit da6e47d422
5 changed files with 43 additions and 27 deletions
@@ -673,7 +673,12 @@ class IRCodeGen(
if(iterable.step==0)
throw AssemblyError("step 0")
val rangeEndExclusiveUntyped = iterable.last + iterable.step
val rangeEndExclusiveWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndExclusiveUntyped and 255 else rangeEndExclusiveUntyped and 65535
val rangeEndExclusiveWrapped =
when (loopvarDtIr) {
IRDataType.BYTE -> rangeEndExclusiveUntyped and 255
IRDataType.WORD -> rangeEndExclusiveUntyped and 65535
else -> rangeEndExclusiveUntyped and 0x7fffffff
}
val result = mutableListOf<IRCodeChunkBase>()
val chunk = IRCodeChunk(null, null)
val indexReg = registers.next(loopvarDtIr)
+12 -2
View File
@@ -186,19 +186,29 @@ class TestIRPeepholeOpt: FunSpec({
test("remove useless and/or/xor") {
val irProg = makeIRProgram(listOf(
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 0),
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 0),
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = 0),
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 255),
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 65535),
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = 2147483647),
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = -1),
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 0),
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 255),
IRInstruction(Opcode.OR, IRDataType.WORD, reg1=42, immediate = 65535),
IRInstruction(Opcode.OR, IRDataType.LONG, reg1=42, immediate = 2147483647),
IRInstruction(Opcode.OR, IRDataType.LONG, reg1=42, immediate = -1),
IRInstruction(Opcode.XOR, IRDataType.BYTE, reg1=42, immediate = 0),
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 200),
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 60000),
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 1),
IRInstruction(Opcode.XOR, IRDataType.BYTE, reg1=42, immediate = 1)
))
irProg.chunks().single().instructions.size shouldBe 8
irProg.chunks().single().instructions.size shouldBe 17
val opt = IRPeepholeOptimizer(irProg, false)
opt.optimize(true, ErrorReporterForTests())
irProg.chunks().single().instructions.size shouldBe 4
irProg.chunks().single().instructions.size shouldBe 12
irProg.chunks().single().instructions.count { it.opcode == Opcode.LOAD } shouldBe 6
}
test("replace and/or/xor by constant number") {
@@ -466,8 +466,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
rightVal?.number==0.0 -> expr.left
rightIDt.isBytes && rightVal?.number==255.0 -> NumericLiteral(BaseDataType.UBYTE, 255.0, rightVal.position)
rightIDt.isWords && rightVal?.number==65535.0 -> NumericLiteral(BaseDataType.UWORD, 65535.0, rightVal.position)
rightIDt.isLong && rightVal?.number==-1.0 -> NumericLiteral(BaseDataType.LONG, -1.0, rightVal.position)
leftIDt.isBytes && leftVal?.number==255.0 -> NumericLiteral(BaseDataType.UBYTE, 255.0, leftVal.position)
leftIDt.isWords && leftVal?.number==65535.0 -> NumericLiteral(BaseDataType.UWORD, 65535.0, leftVal.position)
leftIDt.isLong && leftVal?.number==-1.0 -> NumericLiteral(BaseDataType.LONG, -1.0, leftVal.position)
else -> null
}
}
@@ -477,8 +479,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
rightVal?.number==0.0 -> expr.left
rightIDt.isBytes && rightVal?.number==255.0 -> PrefixExpression("~", expr.left, expr.left.position)
rightIDt.isWords && rightVal?.number==65535.0 -> PrefixExpression("~", expr.left, expr.left.position)
rightIDt.isLong && rightVal?.number==-1.0 -> PrefixExpression("~", expr.left, expr.left.position)
leftIDt.isBytes && leftVal?.number==255.0 -> PrefixExpression("~", expr.right, expr.right.position)
leftIDt.isWords && leftVal?.number==65535.0 -> PrefixExpression("~", expr.right, expr.right.position)
leftIDt.isLong && leftVal?.number==-1.0 -> PrefixExpression("~", expr.right, expr.right.position)
else -> null
}
}
@@ -488,8 +492,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
rightVal?.number==0.0 -> constFalse
rightIDt.isBytes && rightVal?.number==255.0 -> expr.left
rightIDt.isWords && rightVal?.number==65535.0 -> expr.left
rightIDt.isLong && rightVal?.number==-1.0 -> expr.left
leftIDt.isBytes && leftVal?.number==255.0 -> expr.right
leftIDt.isWords && leftVal?.number==65535.0 -> expr.right
leftIDt.isLong && leftVal?.number==-1.0 -> expr.right
else -> null
}
}
@@ -187,7 +187,11 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
when(expr.operator) {
">" -> {
// X>N -> X>=N+1, easier to do in 6502
val maximum = if(rightNum.type.isByte) 255 else 65535
val maximum = when {
rightNum.type.isByte -> 255
rightNum.type.isWord -> 65535
else -> 0x7fffffff
}
if(rightNum.number<maximum) {
val numPlusOne = rightNum.number.toInt()+1
val newExpr = BinaryExpression(expr.left, ">=", NumericLiteral(rightNum.type, numPlusOne.toDouble(), rightNum.position), expr.position)
@@ -196,7 +200,11 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
}
"<=" -> {
// X<=N -> X<N+1, easier to do in 6502
val maximum = if(rightNum.type.isByte) 255 else 65535
val maximum = when {
rightNum.type.isByte -> 255
rightNum.type.isWord -> 65535
else -> 0x7fffffff
}
if(rightNum.number<maximum) {
val numPlusOne = rightNum.number.toInt()+1
val newExpr = BinaryExpression(expr.left, "<", NumericLiteral(rightNum.type, numPlusOne.toDouble(), rightNum.position), expr.position)
+9 -22
View File
@@ -1,32 +1,19 @@
%import textio
%import math
%zeropage basicsafe
%option no_sysinit
main {
; Test the routine
sub start() {
str buffer = iso:"The Quick Brown Fox Jumps Over The Lazy Dog. 1234567890 abcdefghijklmnopqrstuvwxyz !@#$%^&*()_+=-[]{}|;':,./<>? Mary had a little lamb. It's fleece was white as snow. Qoth the raven, 'It's wedding day,"
str buffer2 = iso:"Qoth the raven, nevermore. Qoth the raven, nevermore. The raven is not the raven, but the nightingale."
str buffer3 = iso:"99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, 98 bottles of beer on the wall."
txt.print_uwhex(cx16.memory_crc(buffer, len(buffer)), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer, len(buffer), $ffff, 0), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer,len(buffer), 0, 0), true)
txt.nl()
txt.print_uwhex(cx16.memory_crc(buffer2, len(buffer2)), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer2,len(buffer2), $ffff, 0), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer2,len(buffer2), 0, 0), true)
txt.nl()
txt.print_uwhex(cx16.memory_crc(buffer3, len(buffer3)), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer3,len(buffer3), $ffff, 0), true)
txt.spc()
txt.print_uwhex(math.crc16(buffer3,len(buffer3), 0, 0), true)
long counter
long lv
for lv in 4000 to 94000-1 {
counter++
}
for lv in 94000-1 downto 4000 {
counter++
}
txt.print_l(counter)
txt.nl()
}
}