ir: 4 new instructions to branch on signed <0, >0, <=0, >=0

This commit is contained in:
Irmen de Jong 2022-12-28 13:14:20 +01:00
parent eb4cff202c
commit 1e6fa77633
4 changed files with 103 additions and 14 deletions

View File

@ -1058,19 +1058,13 @@ class IRCodeGen(
}
return when (ifElse.condition.operator) {
"==" -> {
// if X==0 ... so we just branch on left expr is Not-zero.
equalOrNotEqualZero(Opcode.BNZ)
}
"!=" -> {
// if X!=0 ... so we just branch on left expr is Zero.
equalOrNotEqualZero(Opcode.BZ)
}
else -> {
// another comparison against 0, just use regular codegen for this.
// TODO optimize this
translateNonZeroComparison()
}
"==" -> equalOrNotEqualZero(Opcode.BNZ)
"!=" -> equalOrNotEqualZero(Opcode.BZ)
"<" -> if(signed) equalOrNotEqualZero(Opcode.BGEZS) else throw AssemblyError("unsigned < 0 shouldn't occur in codegen")
">" -> if(signed) equalOrNotEqualZero(Opcode.BLEZS) else throw AssemblyError("unsigned > 0 shouldn't occur in codegen")
"<=" -> if(signed) equalOrNotEqualZero(Opcode.BGZS) else throw AssemblyError("unsigned <= 0 shouldn't occur in codegen")
">=" -> if(signed) equalOrNotEqualZero(Opcode.BLZS) else throw AssemblyError("unsigned >= 0 shouldn't occur in codegen")
else -> throw AssemblyError("weird operator")
}
}

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- try to optimize IR for branching on signed <0, >0, <=0, >=0 by using new branch instructions like we have BNZ. To avoid explicit compares. See translateZeroComparison()
- make sure bool value is always 0 or 1 (all casts should convert), then:
- rewrite bool=bool^1 into bool=not bool
- should solve: bool bb = not bb -> larger code than bool bb ^= 1

View File

@ -74,6 +74,10 @@ bstvc address - branch to location if Status bit Overf
bstvs address - branch to location if Status bit Overflow is not set
bz reg1, address - branch to location if reg1 is zero
bnz reg1, address - branch to location if reg1 is not zero
bgzs reg1, address - branch to location if reg1 > 0 (signed)
bgezs reg1, address - branch to location if reg1 >= 0 (signed)
blzs reg1, address - branch to location if reg1 < 0 (signed)
blezs reg1, address - branch to location if reg1 <= 0 (signed)
beq reg1, reg2, address - jump to location in program given by location, if reg1 == reg2
bne reg1, reg2, address - jump to location in program given by location, if reg1 != reg2
bgt reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (unsigned)
@ -239,6 +243,10 @@ enum class Opcode {
BSTVS,
BZ,
BNZ,
BGZS,
BGEZS,
BLZS,
BLEZS,
BEQ,
BNE,
BGT,
@ -370,6 +378,10 @@ val OpcodesThatBranch = setOf(
Opcode.BSTVS,
Opcode.BZ,
Opcode.BNZ,
Opcode.BGZS,
Opcode.BGEZS,
Opcode.BLZS,
Opcode.BLEZS,
Opcode.BEQ,
Opcode.BNE,
Opcode.BGT,
@ -406,6 +418,10 @@ val OpcodesWithMemoryAddressAsValue = setOf(
Opcode.BSTVS,
Opcode.BZ,
Opcode.BNZ,
Opcode.BGZS,
Opcode.BGEZS,
Opcode.BLZS,
Opcode.BLEZS,
Opcode.BEQ,
Opcode.BNE,
Opcode.BGT,
@ -543,6 +559,10 @@ val instructionFormats = mutableMapOf(
Opcode.BSTVS to InstructionFormat.from("N,<v"),
Opcode.BZ to InstructionFormat.from("BW,<r1,<v"),
Opcode.BNZ to InstructionFormat.from("BW,<r1,<v"),
Opcode.BGZS to InstructionFormat.from("BW,<r1,<v"),
Opcode.BGEZS to InstructionFormat.from("BW,<r1,<v"),
Opcode.BLZS to InstructionFormat.from("BW,<r1,<v"),
Opcode.BLEZS to InstructionFormat.from("BW,<r1,<v"),
Opcode.BEQ to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BNE to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGT to InstructionFormat.from("BW,<r1,<r2,<v"),

View File

@ -176,6 +176,10 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BSTVC, Opcode.BSTVS -> TODO("overflow status flag not yet supported in VM (BSTVC,BSTVS)")
Opcode.BZ -> InsBZ(ins)
Opcode.BNZ -> InsBNZ(ins)
Opcode.BGZS -> InsBGZS(ins)
Opcode.BGEZS -> InsBGEZS(ins)
Opcode.BLZS -> InsBLZS(ins)
Opcode.BLEZS -> InsBLEZS(ins)
Opcode.BEQ -> InsBEQ(ins)
Opcode.BNE -> InsBNE(ins)
Opcode.BGT -> InsBGTU(ins)
@ -656,6 +660,78 @@ class VirtualMachine(irProgram: IRProgram) {
}
}
private fun InsBGZS(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
if(registers.getSB(i.reg1!!)>0)
branchTo(i)
else
nextPc()
}
IRDataType.WORD -> {
if(registers.getSW(i.reg1!!)>0)
branchTo(i)
else
nextPc()
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
}
private fun InsBGEZS(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
if(registers.getSB(i.reg1!!)>=0)
branchTo(i)
else
nextPc()
}
IRDataType.WORD -> {
if(registers.getSW(i.reg1!!)>=0)
branchTo(i)
else
nextPc()
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
}
private fun InsBLZS(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
if(registers.getSB(i.reg1!!)<0)
branchTo(i)
else
nextPc()
}
IRDataType.WORD -> {
if(registers.getSW(i.reg1!!)<0)
branchTo(i)
else
nextPc()
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
}
private fun InsBLEZS(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
if(registers.getSB(i.reg1!!)<=0)
branchTo(i)
else
nextPc()
}
IRDataType.WORD -> {
if(registers.getSW(i.reg1!!)<=0)
branchTo(i)
else
nextPc()
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
}
private fun InsBEQ(i: IRInstruction) {
val (left: Int, right: Int) = getBranchOperands(i)
if(left==right)