slightly optimize certain pointer indexing calculation, fix invalid deref optimization

This commit is contained in:
Irmen de Jong
2025-08-31 12:42:02 +02:00
parent 13e6f64d3b
commit a9142b9ce5
4 changed files with 56 additions and 29 deletions
@@ -447,26 +447,11 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
fun complicatedFallback() {
// slow fallback routine that can deal with any expression for value
require(value.type.isWord)
asmgen.pushCpuStack(BaseDataType.UWORD, value)
if (scale == null || scale == 1) {
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", DataType.UWORD)
} else {
// P8ZP_SCRATCH_W1 = value * scale
// TODO optimize this when the value is a binary expression with operator '+'
val mult = PtBinaryExpression("*", DataType.UWORD, value.position)
mult.parent = value.parent
mult.add(value)
mult.add(PtNumber(BaseDataType.UWORD, scale.toDouble(), value.position))
val multSrc = AsmAssignSource.fromAstSource(mult, asmgen.program, asmgen)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, value.definingISub(), value.position, variableAsmName = "P8ZP_SCRATCH_W1")
val assign= AsmAssignment(multSrc, listOf(target), asmgen.program.memsizer, value.position)
asmgen.translateNormalAssignment(assign, value.definingISub())
}
asmgen.restoreRegisterStack(CpuRegister.Y, false) // msb
asmgen.restoreRegisterStack(CpuRegister.A, false) // lsb
asmgen.out("""
fun restoreAYandAddAsmVariable(varname: String) {
asmgen.restoreRegisterStack(CpuRegister.Y, false) // msb
asmgen.restoreRegisterStack(CpuRegister.A, false) // lsb
asmgen.out("""
clc
adc P8ZP_SCRATCH_W1
pha
@@ -474,6 +459,31 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
adc P8ZP_SCRATCH_W1+1
tay
pla""")
}
if (scale == null || scale == 1) {
asmgen.pushCpuStack(BaseDataType.UWORD, value)
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", DataType.UWORD)
restoreAYandAddAsmVariable("P8ZP_SCRATCH_W1")
} else {
// P8ZP_SCRATCH_W1 = value * scale
if(value is PtBinaryExpression && value.operator=="+" && value.right is PtNumber) {
// (x + y) * scale == (x * scale) + (y * scale)
addUnsignedWordToAY(value.left, scale)
addUnsignedWordToAY(value.right, scale)
} else {
asmgen.pushCpuStack(BaseDataType.UWORD, value)
val mult = PtBinaryExpression("*", DataType.UWORD, value.position)
mult.parent = value.parent
mult.add(value)
mult.add(PtNumber(BaseDataType.UWORD, scale.toDouble(), value.position))
val multSrc = AsmAssignSource.fromAstSource(mult, asmgen.program, asmgen)
val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, value.definingISub(), value.position, variableAsmName = "P8ZP_SCRATCH_W1")
val assign= AsmAssignment(multSrc, listOf(target), asmgen.program.memsizer, value.position)
asmgen.translateNormalAssignment(assign, value.definingISub())
restoreAYandAddAsmVariable("P8ZP_SCRATCH_W1")
}
}
}
when(value) {
@@ -430,11 +430,13 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
if(arrayIndexedExpression.indexer.constIndex()==0) {
if(arrayIndexedExpression.plainarrayvar!=null) {
val dt = arrayIndexedExpression.plainarrayvar!!.inferType(program).getOrUndef()
if(dt.isPointer) {
// pointer[0] --> pointer^^
val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource, true, arrayIndexedExpression.plainarrayvar!!.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression,deref, parent))
if((arrayIndexedExpression.parent as? BinaryExpression)?.operator !=".") {
val dt = arrayIndexedExpression.plainarrayvar!!.inferType(program).getOrUndef()
if(dt.isPointer) {
// pointer[0] --> pointer^^
val deref = PtrDereference(arrayIndexedExpression.plainarrayvar!!.nameInSource, true, arrayIndexedExpression.plainarrayvar!!.position)
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression,deref, parent))
}
}
}
val ptrDeref = arrayIndexedExpression.pointerderef
+20 -2
View File
@@ -1027,7 +1027,7 @@ main {
st[8] shouldBe instanceOf<Assignment>()
}
test("indexing pointers with index 0 is just a direct pointer dereference") {
test("indexing pointers with index 0 is just a direct pointer dereference except when followed by a struct field lookup") {
val src="""
%import floats
main {
@@ -1062,12 +1062,16 @@ main {
f2 = fptr[0]
fptr^^ = 1.234
fptr[0] = 1.234
; not changed to dereference:
cx16.r0L = l1[0].n
cx16.r1L = l1[1].n
}
}"""
val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 28
st.size shouldBe 30
val dr0 = (st[10] as Assignment).value as PtrDereference
val dr1 = (st[11] as Assignment).value as PtrDereference
val dr2 = (st[12] as Assignment).value as PtrDereference
@@ -1119,6 +1123,20 @@ main {
dr13.derefLast shouldBe true
dr15.chain shouldBe listOf("fptr")
dr15.derefLast shouldBe true
val list0 = (st[27] as Assignment).value as BinaryExpression
val list1 = (st[28] as Assignment).value as BinaryExpression
list0.operator shouldBe "."
(list0.right as IdentifierReference).nameInSource shouldBe listOf("n")
val list0left = list0.left as ArrayIndexedExpression
list0left.plainarrayvar!!.nameInSource shouldBe listOf("l1")
list0left.indexer.constIndex() shouldBe 0
list1.operator shouldBe "."
(list1.right as IdentifierReference).nameInSource shouldBe listOf("n")
val list1left = list0.left as ArrayIndexedExpression
list1left.plainarrayvar!!.nameInSource shouldBe listOf("l1")
list1left.indexer.constIndex() shouldBe 0
}
test("indexing pointers to structs") {
-3
View File
@@ -1,9 +1,6 @@
TODO
====
fix compiler crash about structpointer[0].name (works fine with index 1...)
not all source lines are correctly reported in the IR file,
for example the below subroutine only shows the sub() line:
sub two() {