removed redundant branch opcodes in IR: BLT(S), BLE(S). Just use swapped BGT(S), BGE(S).

This commit is contained in:
Irmen de Jong 2022-12-27 19:33:28 +01:00
parent 7ee777f405
commit eb4cff202c
4 changed files with 105 additions and 98 deletions

View File

@ -551,8 +551,9 @@ class IRCodeGen(
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step)
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol), null)
val branchOpcode = if(loopvarDt in SignedDatatypes) Opcode.BLES else Opcode.BLE
addInstr(result, IRInstruction(branchOpcode, loopvarDtIr, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null)
// if endvalue >= index, iterate loop
val branchOpcode = if(loopvarDt in SignedDatatypes) Opcode.BGES else Opcode.BGE
addInstr(result, IRInstruction(branchOpcode, loopvarDtIr, reg1=endvalueReg, reg2=indexReg, labelSymbol=loopLabel), null)
result += IRCodeChunk(labelAfterFor, null)
return result
@ -907,56 +908,117 @@ class IRCodeGen(
if(ifElse.condition.operator !in ComparisonOperators)
throw AssemblyError("if condition should only be a binary comparison expression")
val signed = ifElse.condition.left.type in arrayOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
val signed = ifElse.condition.left.type in SignedDatatypes
val irDt = irType(ifElse.condition.left.type)
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
if(goto!=null && ifElse.elseScope.children.isEmpty()) {
// special case the form: if <condition> goto <place>
val result = mutableListOf<IRCodeChunkBase>()
val leftReg = registers.nextFree()
val rightReg = registers.nextFree()
result += expressionEval.translateExpression(ifElse.condition.left, leftReg, -1)
result += expressionEval.translateExpression(ifElse.condition.right, rightReg, -1)
val opcode = when(ifElse.condition.operator) {
"==" -> Opcode.BEQ
"!=" -> Opcode.BNE
"<" -> Opcode.BLT
">" -> Opcode.BGT
"<=" -> Opcode.BLE
">=" -> Opcode.BGE
val leftRegNum = registers.nextFree()
val rightRegNum = registers.nextFree()
result += expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1)
result += expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1)
val opcode: Opcode
val firstReg: Int
val secondReg: Int
when(ifElse.condition.operator) {
"==" -> {
opcode = Opcode.BEQ
firstReg = leftRegNum
secondReg = rightRegNum
}
"!=" -> {
opcode = Opcode.BNE
firstReg = leftRegNum
secondReg = rightRegNum
}
"<" -> {
// swapped '>'
opcode = if(signed) Opcode.BGTS else Opcode.BGT
firstReg = rightRegNum
secondReg = leftRegNum
}
">" -> {
opcode = if(signed) Opcode.BGTS else Opcode.BGT
firstReg = leftRegNum
secondReg = rightRegNum
}
"<=" -> {
// swapped '>='
opcode = if(signed) Opcode.BGES else Opcode.BGE
firstReg = rightRegNum
secondReg = leftRegNum
}
">=" -> {
opcode = if(signed) Opcode.BGES else Opcode.BGE
firstReg = leftRegNum
secondReg = rightRegNum
}
else -> throw AssemblyError("invalid comparison operator")
}
if(goto.address!=null)
addInstr(result, IRInstruction(opcode, irDt, reg1=leftReg, reg2=rightReg, value = goto.address?.toInt()), null)
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, value = goto.address?.toInt()), null)
else if(goto.generatedLabel!=null)
addInstr(result, IRInstruction(opcode, irDt, reg1=leftReg, reg2=rightReg, labelSymbol = goto.generatedLabel), null)
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, labelSymbol = goto.generatedLabel), null)
else
addInstr(result, IRInstruction(opcode, irDt, reg1=leftReg, reg2=rightReg, labelSymbol = goto.identifier!!.targetName.joinToString(".")), null)
addInstr(result, IRInstruction(opcode, irDt, reg1=firstReg, reg2=secondReg, labelSymbol = goto.identifier!!.targetName.joinToString(".")), null)
return result
}
fun translateNonZeroComparison(): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>()
val elseBranch = when(ifElse.condition.operator) {
"==" -> Opcode.BNE
"!=" -> Opcode.BEQ
"<" -> if(signed) Opcode.BGES else Opcode.BGE
">" -> if(signed) Opcode.BLES else Opcode.BLE
"<=" -> if(signed) Opcode.BGTS else Opcode.BGT
">=" -> if(signed) Opcode.BLTS else Opcode.BLT
val leftRegNum = registers.nextFree()
val rightRegNum = registers.nextFree()
result += expressionEval.translateExpression(ifElse.condition.left, leftRegNum, -1)
result += expressionEval.translateExpression(ifElse.condition.right, rightRegNum, -1)
val elseBranchOpcode: Opcode
val elseBranchFirstReg: Int
val elseBranchSecondReg: Int
when(ifElse.condition.operator) {
"==" -> {
elseBranchOpcode = Opcode.BNE
elseBranchFirstReg = leftRegNum
elseBranchSecondReg = rightRegNum
}
"!=" -> {
elseBranchOpcode = Opcode.BEQ
elseBranchFirstReg = leftRegNum
elseBranchSecondReg = rightRegNum
}
"<" -> {
// else part when left >= right
elseBranchOpcode = if(signed) Opcode.BGES else Opcode.BGE
elseBranchFirstReg = leftRegNum
elseBranchSecondReg = rightRegNum
}
">" -> {
// else part when left <= right --> right >= left
elseBranchOpcode = if(signed) Opcode.BGES else Opcode.BGE
elseBranchFirstReg = rightRegNum
elseBranchSecondReg = leftRegNum
}
"<=" -> {
// else part when left > right
elseBranchOpcode = if(signed) Opcode.BGTS else Opcode.BGT
elseBranchFirstReg = leftRegNum
elseBranchSecondReg = rightRegNum
}
">=" -> {
// else part when left < right --> right > left
elseBranchOpcode = if(signed) Opcode.BGTS else Opcode.BGT
elseBranchFirstReg = rightRegNum
elseBranchSecondReg = leftRegNum
}
else -> throw AssemblyError("invalid comparison operator")
}
val leftReg = registers.nextFree()
val rightReg = registers.nextFree()
result += expressionEval.translateExpression(ifElse.condition.left, leftReg, -1)
result += expressionEval.translateExpression(ifElse.condition.right, rightReg, -1)
if(ifElse.elseScope.children.isNotEmpty()) {
// if and else parts
val elseLabel = createLabelName()
val afterIfLabel = createLabelName()
addInstr(result, IRInstruction(elseBranch, irDt, reg1=leftReg, reg2=rightReg, labelSymbol = elseLabel), null)
addInstr(result, IRInstruction(elseBranchOpcode, irDt, reg1=elseBranchFirstReg, reg2=elseBranchSecondReg, labelSymbol = elseLabel), null)
result += translateNode(ifElse.ifScope)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
@ -964,7 +1026,7 @@ class IRCodeGen(
} else {
// only if part
val afterIfLabel = createLabelName()
addInstr(result, IRInstruction(elseBranch, irDt, reg1=leftReg, reg2=rightReg, labelSymbol = afterIfLabel), null)
addInstr(result, IRInstruction(elseBranchOpcode, irDt, reg1=elseBranchFirstReg, reg2=elseBranchSecondReg, labelSymbol = afterIfLabel), null)
result += translateNode(ifElse.ifScope)
result += IRCodeChunk(afterIfLabel, null)
}
@ -1006,6 +1068,7 @@ class IRCodeGen(
}
else -> {
// another comparison against 0, just use regular codegen for this.
// TODO optimize this
translateNonZeroComparison()
}
}

View File

@ -3,7 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- remove redundant branch opcodes in IR: BLT(S), BLE(S). Replace by swapped BGT(S), BGE(S).
- 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

@ -76,20 +76,17 @@ bz reg1, address - branch to location if reg1 is zero
bnz reg1, address - branch to location if reg1 is not zero
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
blt reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (unsigned) TODO REMOVE
blts reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (signed) TODO REMOVE
ble reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (unsigned) TODO REMOVE
bles reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) TODO REMOVE
bgt reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (unsigned)
bgts reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (signed)
bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned)
bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed)
( NOTE: there are no blt/ble instructions because these are equivalent to bgt/bge with the operands swapped around.)
seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0
sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0 TODO REMOVE
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0 TODO REMOVE
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0 TODO REMOVE
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0 TODO REMOVE
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0
sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0
sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
@ -244,22 +241,18 @@ enum class Opcode {
BNZ,
BEQ,
BNE,
BLT, // TODO REMOVE
BLTS, // TODO REMOVE
BGT,
BGTS,
BLE, // TODO REMOVE
BLES, // TODO REMOVE
BGE,
BGES,
SEQ,
SNE,
SLT, // TODO REMOVE ?
SLTS, // TODO REMOVE ?
SLT,
SLTS,
SGT,
SGTS,
SLE, // TODO REMOVE ?
SLES, // TODO REMOVE ?
SLE,
SLES,
SGE,
SGES,
@ -379,12 +372,8 @@ val OpcodesThatBranch = setOf(
Opcode.BNZ,
Opcode.BEQ,
Opcode.BNE,
Opcode.BLT,
Opcode.BLTS,
Opcode.BGT,
Opcode.BGTS,
Opcode.BLE,
Opcode.BLES,
Opcode.BGE,
Opcode.BGES
)
@ -419,12 +408,8 @@ val OpcodesWithMemoryAddressAsValue = setOf(
Opcode.BNZ,
Opcode.BEQ,
Opcode.BNE,
Opcode.BLT,
Opcode.BLTS,
Opcode.BGT,
Opcode.BGTS,
Opcode.BLE,
Opcode.BLES,
Opcode.BGE,
Opcode.BGES,
Opcode.INCM,
@ -560,12 +545,8 @@ val instructionFormats = mutableMapOf(
Opcode.BNZ 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.BLT to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BLTS to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGT to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGTS to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BLE to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BLES to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGE to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"),
@ -734,8 +715,8 @@ data class IRInstruction(
fpReg1direction = format.fpReg1
fpReg2direction = format.fpReg2
if(opcode in setOf(Opcode.BEQ, Opcode.BNE, Opcode.BLT, Opcode.BLTS,
Opcode.BGT, Opcode.BGTS, Opcode.BLE, Opcode.BLES,
if(opcode in setOf(Opcode.BEQ, Opcode.BNE,
Opcode.BGT, Opcode.BGTS,
Opcode.BGE, Opcode.BGES,
Opcode.SEQ, Opcode.SNE, Opcode.SLT, Opcode.SLTS,
Opcode.SGT, Opcode.SGTS, Opcode.SLE, Opcode.SLES,

View File

@ -178,12 +178,8 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BNZ -> InsBNZ(ins)
Opcode.BEQ -> InsBEQ(ins)
Opcode.BNE -> InsBNE(ins)
Opcode.BLT -> InsBLTU(ins)
Opcode.BLTS -> InsBLTS(ins)
Opcode.BGT -> InsBGTU(ins)
Opcode.BGTS -> InsBGTS(ins)
Opcode.BLE -> InsBLEU(ins)
Opcode.BLES -> InsBLES(ins)
Opcode.BGE -> InsBGEU(ins)
Opcode.BGES -> InsBGES(ins)
Opcode.SEQ -> InsSEQ(ins)
@ -676,22 +672,6 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc()
}
private fun InsBLTU(i: IRInstruction) {
val (left: UInt, right: UInt) = getBranchOperandsU(i)
if(left<right)
branchTo(i)
else
nextPc()
}
private fun InsBLTS(i: IRInstruction) {
val (left: Int, right: Int) = getBranchOperands(i)
if(left<right)
branchTo(i)
else
nextPc()
}
private fun InsBGTU(i: IRInstruction) {
val (left: UInt, right: UInt) = getBranchOperandsU(i)
if(left>right)
@ -709,23 +689,6 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc()
}
private fun InsBLEU(i: IRInstruction) {
val (left: UInt, right: UInt) = getBranchOperandsU(i)
if(left<=right)
branchTo(i)
else
nextPc()
}
private fun InsBLES(i: IRInstruction) {
val (left: Int, right: Int) = getBranchOperands(i)
if(left<=right)
branchTo(i)
else
nextPc()
}
private fun InsBGEU(i: IRInstruction) {
val (left: UInt, right: UInt) = getBranchOperandsU(i)
if(left>=right)