remove redundant IR instructions like SNZ

This commit is contained in:
Irmen de Jong 2024-02-24 13:15:44 +01:00
parent fe9a9fc5cb
commit f5e332daf7
7 changed files with 82 additions and 26 deletions

View File

@ -57,7 +57,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
is PtBinaryExpression -> { /* no cmp necessary the lda has been done just prior */ }
is PtTypeCast -> {
if(condition.value.type !in ByteDatatypes)
asmgen.out(" cmp #0")
asmgen.out(" cmp #0") // maybe can be eliminated altogether? depends on how the actual type cast is done...
}
else -> asmgen.out(" cmp #0")
}

View File

@ -310,18 +310,24 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
var actualResultFpReg2 = -1
when(cast.type) {
DataType.BOOL -> {
if (cast.value.type in IntegerDatatypes) {
actualResultReg2 = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg), null)
}
else if(cast.value.type==DataType.FLOAT) {
actualResultReg2 = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.SGN, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg)
it += IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=actualResultReg2, immediate = 1)
when (cast.value.type) {
in ByteDatatypes -> {
actualResultReg2 = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg), null)
}
in WordDatatypes -> {
actualResultReg2 = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg), null)
}
DataType.FLOAT -> {
actualResultReg2 = codeGen.registers.nextFree()
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.SGN, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg)
it += IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=actualResultReg2, immediate = 1)
}
}
else -> throw AssemblyError("weird cast value type")
}
else throw AssemblyError("weird cast value type")
}
DataType.UBYTE -> {
when(cast.value.type) {

View File

@ -337,10 +337,33 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
}
}
}
// a SNZ etc. whose target register is not used can be removed altogether
if(ins.opcode in OpcodesThatSetRegFromStatusbits) {
val usages = regUsages(ins.reg1!!)
if(usages.toList().sumOf { it.second } <= 1) {
chunk.instructions.removeAt(idx)
changed = true
}
}
}
return changed
}
private fun regUsages(register: Int): Map<IRCodeChunkBase, Int> {
val chunks = mutableMapOf<IRCodeChunkBase, Int>()
irprog.foreachSub { sub ->
sub.chunks.forEach { chunk ->
val used = chunk.usedRegisters()
val numUsages = used.readRegs.getOrDefault(register, 0) + used.writeRegs.getOrDefault(register, 0)
if(numUsages>0) {
chunks[chunk] = numUsages
}
}
}
return chunks
}
private fun removeUselessArithmetic(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
// note: this is hard to solve for the non-immediate instructions atm because the values are loaded into registers first
var changed = false

View File

@ -1,9 +1,7 @@
TODO
====
fix casting uword to bool (don't take only the lsb!)
fix IR adding snz in bool casts inside if
fix 6502 casting uword to bool (don't take only the lsb!)
fix "wordGreaterValue"

View File

@ -7,20 +7,29 @@
main {
sub start() {
test_stack.test()
broken_word_gt()
broken_word_lt()
broken_uword_gt()
broken_uword_lt()
if cx16.r0L as bool
cx16.r0L++
test_bool()
test_float()
test_byte()
test_ubyte()
test_word()
test_uword()
if cx16.r0 as bool
cx16.r0L++
test_stack.test()
if @(cx16.r0) as bool
cx16.r0L++
; test_stack.test()
; broken_word_gt()
; broken_word_lt()
; broken_uword_gt()
; broken_uword_lt()
;
; test_bool()
; test_float()
; test_byte()
; test_ubyte()
; test_word()
; test_uword()
;
; test_stack.test()
if sys.target!=255
repeat { }

View File

@ -472,6 +472,23 @@ val OpcodesThatDependOnCarry = arrayOf(
Opcode.ROXRM,
)
val OpcodesThatSetRegFromStatusbits = arrayOf(
Opcode.SCC,
Opcode.SCS,
Opcode.SZ,
Opcode.SNZ,
Opcode.SEQ,
Opcode.SNE,
Opcode.SLT,
Opcode.SLTS,
Opcode.SGT,
Opcode.SGTS,
Opcode.SLE,
Opcode.SLES,
Opcode.SGE,
Opcode.SGES
)
val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThatSetStatusbitsIncludingCarry

View File

@ -536,6 +536,9 @@ class RegistersUsed(
fun isEmpty() = readRegs.isEmpty() && writeRegs.isEmpty() && readFpRegs.isEmpty() && writeFpRegs.isEmpty()
fun isNotEmpty() = !isEmpty()
fun used(register: Int) = register in readRegs || register in writeRegs
fun usedFp(fpRegister: Int) = fpRegister in readFpRegs || fpRegister in writeFpRegs
}
private fun registersUsedInAssembly(isIR: Boolean, assembly: String): RegistersUsed {