optimize certain word multiplication with bit shifting if it's a power of 2

This commit is contained in:
Irmen de Jong
2025-09-18 20:23:29 +02:00
parent a71895cbe8
commit 231b50dacb
3 changed files with 56 additions and 60 deletions
@@ -5,6 +5,7 @@ import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal
import prog8.codegen.cpu6502.VariableAllocator
import kotlin.math.log2
internal class AssignmentAsmGen(
@@ -1145,6 +1146,14 @@ internal class AssignmentAsmGen(
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type.isSigned)
if (value in asmgen.optimizedByteMultiplications)
asmgen.out(" jsr prog8_math.mul_byte_${value}")
else if(value in powersOfTwoInt) {
val shifts = log2(value.toDouble()).toInt()
if(shifts>=8) {
asmgen.out(" lda #0")
} else {
repeat(shifts) { asmgen.out(" asl a") }
}
}
else
asmgen.out(" ldy #$value | jsr prog8_math.multiply_bytes")
assignRegisterByte(target, CpuRegister.A, false, true)
@@ -1155,7 +1164,26 @@ internal class AssignmentAsmGen(
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type.isSigned)
asmgen.out(" jsr prog8_math.mul_word_${value}")
}
else if(value in powersOfTwoInt) {
val shifts = log2(value.toDouble()).toInt()
if(shifts>=16) {
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type.isSigned)
asmgen.out(" lda #0 | ldy #0")
} else {
if(target.kind==TargetStorageKind.VARIABLE && target.datatype.isWord) {
assignExpressionToVariable(expr.left, target.asmVarname, target.datatype)
repeat(shifts) { asmgen.out(" asl ${target.asmVarname} | rol ${target.asmVarname}+1") }
return true
} else {
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type.isSigned)
asmgen.out(" sty P8ZP_SCRATCH_REG")
repeat(shifts) { asmgen.out(" asl a | rol P8ZP_SCRATCH_REG") }
asmgen.out(" ldy P8ZP_SCRATCH_REG")
}
}
}
else {
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type.isSigned)
if(expr.definingBlock()!!.options.veraFxMuls){
// cx16 verafx hardware mul
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "cx16.r1")
+3 -6
View File
@@ -58,18 +58,15 @@ and for example the below code omits line 5::
STRUCTS and TYPED POINTERS
--------------------------
- the type of struct initializer arrays should not be uword[] but ^^struct[] ?
- implement the remaining TODO's in PointerAssignmentsGen.
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
- optimize addUnsignedByteOrWordToAY in PointerAssignmentsGen a bit more
- optimize the float copying in assignIndexedPointer() (also word?)
- implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
- try to optimize pointer arithmetic used in peek/poke a bit more so the routines in sorting module can use typed pointers without increasing code size, see test.p8 in commit d394dc1e
- should @(wordpointer) be equivalent to wordpointer^^ (that would require a LOT of code rewrite that now knows that @() is strictly byte based) ?
or do an implicit cast @(wpointer as ubyte^^) ? And/or add a warning about that?
- optimize addUnsignedByteOrWordToAY in PointerAssignmentsGen a bit more
- support for typed function pointers? (&routine could be typed by default as well then)
- support @nosplit pointer arrays?
- support pointer to pointer?
- the type of struct initializer arrays should not be uword[] but ^^struct[]
- support for typed function pointers? (&routine could be typed by default as well then)
- really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
- (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
+25 -54
View File
@@ -1,63 +1,34 @@
%import textio
%zeropage basicsafe
main {
word bignum
struct Node {
ubyte id
str name
bool flag
word counter
}
sub start() {
^^Node test = []
bignum = 11111
test.counter = 22222
^^uword @shared ptr
txt.print_w(bignum)
txt.spc()
bignum++
add1()
add2()
sub1()
sub2()
txt.print_w(bignum)
txt.spc()
bignum--
sub add1() {
ptr += 5
cx16.r0 = ptr + 5
cx16.r0 = peekw(ptr + 5)
}
txt.print_w(bignum)
txt.nl()
sub add2() {
ptr += cx16.r0L
cx16.r0 = ptr + cx16.r0L
cx16.r0 = peekw(ptr + cx16.r0L)
}
txt.print_w(test.counter)
txt.spc()
test.counter ++
sub sub1() {
ptr -= 5
cx16.r0 = ptr - 5
cx16.r0 = peekw(ptr - 5)
}
txt.print_w(test.counter)
txt.spc()
test.counter --
txt.print_w(test.counter)
txt.nl()
txt.print_w(bignum)
txt.spc()
bignum+=5555
txt.print_w(bignum)
txt.spc()
bignum-=5555
txt.print_w(bignum)
txt.nl()
txt.print_w(test.counter)
txt.spc()
test.counter += 5555
txt.print_w(test.counter)
txt.spc()
test.counter -= 5555
txt.print_w(test.counter)
txt.nl()
sub sub2() {
ptr -= cx16.r0L
cx16.r0 = ptr - cx16.r0L
cx16.r0 = peekw(ptr - cx16.r0L)
}
}
}