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

View File

@ -3,7 +3,7 @@ TODO
For next release 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: - make sure bool value is always 0 or 1 (all casts should convert), then:
- rewrite bool=bool^1 into bool=not bool - rewrite bool=bool^1 into bool=not bool
- should solve: bool bb = not bb -> larger code than bool bb ^= 1 - 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 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 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 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) 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) 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) 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) 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 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 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 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 TODO REMOVE 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 TODO REMOVE 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 TODO REMOVE 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 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 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 sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
@ -244,22 +241,18 @@ enum class Opcode {
BNZ, BNZ,
BEQ, BEQ,
BNE, BNE,
BLT, // TODO REMOVE
BLTS, // TODO REMOVE
BGT, BGT,
BGTS, BGTS,
BLE, // TODO REMOVE
BLES, // TODO REMOVE
BGE, BGE,
BGES, BGES,
SEQ, SEQ,
SNE, SNE,
SLT, // TODO REMOVE ? SLT,
SLTS, // TODO REMOVE ? SLTS,
SGT, SGT,
SGTS, SGTS,
SLE, // TODO REMOVE ? SLE,
SLES, // TODO REMOVE ? SLES,
SGE, SGE,
SGES, SGES,
@ -379,12 +372,8 @@ val OpcodesThatBranch = setOf(
Opcode.BNZ, Opcode.BNZ,
Opcode.BEQ, Opcode.BEQ,
Opcode.BNE, Opcode.BNE,
Opcode.BLT,
Opcode.BLTS,
Opcode.BGT, Opcode.BGT,
Opcode.BGTS, Opcode.BGTS,
Opcode.BLE,
Opcode.BLES,
Opcode.BGE, Opcode.BGE,
Opcode.BGES Opcode.BGES
) )
@ -419,12 +408,8 @@ val OpcodesWithMemoryAddressAsValue = setOf(
Opcode.BNZ, Opcode.BNZ,
Opcode.BEQ, Opcode.BEQ,
Opcode.BNE, Opcode.BNE,
Opcode.BLT,
Opcode.BLTS,
Opcode.BGT, Opcode.BGT,
Opcode.BGTS, Opcode.BGTS,
Opcode.BLE,
Opcode.BLES,
Opcode.BGE, Opcode.BGE,
Opcode.BGES, Opcode.BGES,
Opcode.INCM, Opcode.INCM,
@ -560,12 +545,8 @@ val instructionFormats = mutableMapOf(
Opcode.BNZ to InstructionFormat.from("BW,<r1,<v"), Opcode.BNZ to InstructionFormat.from("BW,<r1,<v"),
Opcode.BEQ to InstructionFormat.from("BW,<r1,<r2,<v"), Opcode.BEQ to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BNE 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.BGT to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGTS 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.BGE to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"), Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"),
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"), Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"),
@ -734,8 +715,8 @@ data class IRInstruction(
fpReg1direction = format.fpReg1 fpReg1direction = format.fpReg1
fpReg2direction = format.fpReg2 fpReg2direction = format.fpReg2
if(opcode in setOf(Opcode.BEQ, Opcode.BNE, Opcode.BLT, Opcode.BLTS, if(opcode in setOf(Opcode.BEQ, Opcode.BNE,
Opcode.BGT, Opcode.BGTS, Opcode.BLE, Opcode.BLES, Opcode.BGT, Opcode.BGTS,
Opcode.BGE, Opcode.BGES, Opcode.BGE, Opcode.BGES,
Opcode.SEQ, Opcode.SNE, Opcode.SLT, Opcode.SLTS, Opcode.SEQ, Opcode.SNE, Opcode.SLT, Opcode.SLTS,
Opcode.SGT, Opcode.SGTS, Opcode.SLE, Opcode.SLES, Opcode.SGT, Opcode.SGTS, Opcode.SLE, Opcode.SLES,

View File

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