mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
removed redundant branch opcodes in IR: BLT(S), BLE(S). Just use swapped BGT(S), BGE(S).
This commit is contained in:
parent
7ee777f405
commit
eb4cff202c
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user