translate address-of into + expression for non-const address ptrs too,

also IR optimization to use immediate arithmetic opcodes if possible
This commit is contained in:
Irmen de Jong
2025-11-09 00:51:44 +01:00
parent afb458a7da
commit b7d1fb1342
3 changed files with 72 additions and 13 deletions

View File

@@ -440,6 +440,52 @@ jump p8_label_gen_2
} }
else -> {} else -> {}
} }
fun optimizeImmediateLoadAssociative(replacementOpcode: Opcode) {
fun getImmediateLoad(reg: Int): Pair<Int, Int>? {
// look if the given register gets an immediate value 1 or 2 istructions back
// returns (index of load instruction, immediate value) or null.
if(idx>=1) {
val previous = indexedInstructions[idx-1].value
if(previous.opcode==Opcode.LOAD && previous.reg1==reg)
return idx-1 to previous.immediate!!
}
if(idx>=2) {
val previous = indexedInstructions[idx-2].value
if(previous.opcode==Opcode.LOAD && previous.reg1==reg)
return idx-2 to previous.immediate!!
}
return null
}
val immediate1 = getImmediateLoad(ins.reg1!!)
if(immediate1!=null) {
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg2, immediate = immediate1.second)
chunk.instructions.removeAt(immediate1.first)
changed=true
} else {
val immediate2 = getImmediateLoad(ins.reg2!!)
if (immediate2 != null) {
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg1, immediate = immediate2.second)
chunk.instructions.removeAt(immediate2.first)
changed=true
}
}
}
// try to use immediate arithmetic instruction if possible
when(ins.opcode) {
Opcode.ADDR -> optimizeImmediateLoadAssociative(Opcode.ADD)
Opcode.MULR -> optimizeImmediateLoadAssociative(Opcode.MUL)
Opcode.MULSR -> optimizeImmediateLoadAssociative(Opcode.MULS)
// Opcode.SUBR -> TODO("ir peephole Subr")
// Opcode.DIVR -> TODO("ir peephole Divr")
// Opcode.DIVSR -> TODO("ir peephole Divsr")
// Opcode.MODR -> TODO("ir peephole Modr")
// Opcode.DIVMODR -> TODO("ir peephole DivModr")
else -> {}
}
} }
return changed return changed
} }

View File

@@ -480,18 +480,31 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
override fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> { override fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> {
if(addressOf.arrayIndex!=null) { if(addressOf.arrayIndex!=null) {
val tgt = addressOf.identifier?.constValue(program) val tgt = addressOf.identifier
if (tgt != null && tgt.type.isInteger) { if(tgt!=null) {
// &constant[idx] --> constant + idx val constAddress = tgt.constValue(program)
val indexExpr = addressOf.arrayIndex!!.indexExpr if (constAddress != null && constAddress.type.isInteger) {
val right = if(indexExpr.inferType(program) issimpletype tgt.type) // &constant[idx] --> constant + idx
indexExpr val indexExpr = addressOf.arrayIndex!!.indexExpr
else val right = if (indexExpr.inferType(program) issimpletype constAddress.type)
TypecastExpression(indexExpr, DataType.forDt(tgt.type), true, indexExpr.position) indexExpr
val add = BinaryExpression(tgt, "+", right, addressOf.position) else
return listOf( TypecastExpression(indexExpr, DataType.forDt(constAddress.type), true, indexExpr.position)
IAstModification.ReplaceNode(addressOf, add, parent) val add = BinaryExpression(constAddress, "+", right, addressOf.position)
) return listOf(IAstModification.ReplaceNode(addressOf, add, parent))
} else {
val decl = tgt.targetVarDecl()!!
if(decl.datatype.isInteger) {
// &addressvar[idx] --> addressvar + idx
val indexExpr = addressOf.arrayIndex!!.indexExpr
val right = if (indexExpr.inferType(program) istype decl.datatype)
indexExpr
else
TypecastExpression(indexExpr, decl.datatype, true, indexExpr.position)
val add = BinaryExpression(tgt, "+", right, addressOf.position)
return listOf(IAstModification.ReplaceNode(addressOf, add, parent))
}
}
} }
} }
return noModifications return noModifications

View File

@@ -88,7 +88,7 @@ IR/VM
- implement fast code paths for TODO("inplace split.... - implement fast code paths for TODO("inplace split....
- implement more TODOs in AssignmentGen - implement more TODOs in AssignmentGen
- do something with the 'split' tag on split word arrays - do something with the 'split' tag on split word arrays
- add more optimizations in IRPeepholeOptimizer - add more optimizations in IRPeepholeOptimizer, implement the TODOs in there at least
- idea: replace all scalar variables that are not @shared by an allocated register. Keep a table of the variable to register mapping (including the datatype) - idea: replace all scalar variables that are not @shared by an allocated register. Keep a table of the variable to register mapping (including the datatype)
global initialization values are simply a list of LOAD instructions. global initialization values are simply a list of LOAD instructions.
Variables replaced include all subroutine parameters? Or not? So the only variables that remain as variables are arrays and strings. Variables replaced include all subroutine parameters? Or not? So the only variables that remain as variables are arrays and strings.