Elide redundant bool conversions in logical ops
This commit is contained in:
parent
3e654ddd60
commit
7c28296f92
@ -2339,60 +2339,36 @@ class BytecodeCompiler(
|
|||||||
|
|
||||||
private fun compileLogicalAnd(ref: LogicalAndRef): CompiledValue? {
|
private fun compileLogicalAnd(ref: LogicalAndRef): CompiledValue? {
|
||||||
val leftValue = compileRefWithFallback(ref.left(), SlotType.BOOL, Pos.builtIn) ?: return null
|
val leftValue = compileRefWithFallback(ref.left(), SlotType.BOOL, Pos.builtIn) ?: return null
|
||||||
val leftBool = if (leftValue.type == SlotType.BOOL) {
|
if (leftValue.type != SlotType.BOOL) return null
|
||||||
leftValue
|
|
||||||
} else {
|
|
||||||
val slot = allocSlot()
|
|
||||||
builder.emit(Opcode.OBJ_TO_BOOL, leftValue.slot, slot)
|
|
||||||
CompiledValue(slot, SlotType.BOOL)
|
|
||||||
}
|
|
||||||
val resultSlot = allocSlot()
|
val resultSlot = allocSlot()
|
||||||
val falseId = builder.addConst(BytecodeConst.Bool(false))
|
val falseId = builder.addConst(BytecodeConst.Bool(false))
|
||||||
builder.emit(Opcode.CONST_BOOL, falseId, resultSlot)
|
builder.emit(Opcode.CONST_BOOL, falseId, resultSlot)
|
||||||
val endLabel = builder.label()
|
val endLabel = builder.label()
|
||||||
builder.emit(
|
builder.emit(
|
||||||
Opcode.JMP_IF_FALSE,
|
Opcode.JMP_IF_FALSE,
|
||||||
listOf(CmdBuilder.Operand.IntVal(leftBool.slot), CmdBuilder.Operand.LabelRef(endLabel))
|
listOf(CmdBuilder.Operand.IntVal(leftValue.slot), CmdBuilder.Operand.LabelRef(endLabel))
|
||||||
)
|
)
|
||||||
val rightValue = compileRefWithFallback(ref.right(), SlotType.BOOL, Pos.builtIn) ?: return null
|
val rightValue = compileRefWithFallback(ref.right(), SlotType.BOOL, Pos.builtIn) ?: return null
|
||||||
val rightBool = if (rightValue.type == SlotType.BOOL) {
|
if (rightValue.type != SlotType.BOOL) return null
|
||||||
rightValue
|
builder.emit(Opcode.MOVE_BOOL, rightValue.slot, resultSlot)
|
||||||
} else {
|
|
||||||
val slot = allocSlot()
|
|
||||||
builder.emit(Opcode.OBJ_TO_BOOL, rightValue.slot, slot)
|
|
||||||
CompiledValue(slot, SlotType.BOOL)
|
|
||||||
}
|
|
||||||
builder.emit(Opcode.MOVE_BOOL, rightBool.slot, resultSlot)
|
|
||||||
builder.mark(endLabel)
|
builder.mark(endLabel)
|
||||||
return CompiledValue(resultSlot, SlotType.BOOL)
|
return CompiledValue(resultSlot, SlotType.BOOL)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compileLogicalOr(ref: LogicalOrRef): CompiledValue? {
|
private fun compileLogicalOr(ref: LogicalOrRef): CompiledValue? {
|
||||||
val leftValue = compileRefWithFallback(ref.left(), SlotType.BOOL, Pos.builtIn) ?: return null
|
val leftValue = compileRefWithFallback(ref.left(), SlotType.BOOL, Pos.builtIn) ?: return null
|
||||||
val leftBool = if (leftValue.type == SlotType.BOOL) {
|
if (leftValue.type != SlotType.BOOL) return null
|
||||||
leftValue
|
|
||||||
} else {
|
|
||||||
val slot = allocSlot()
|
|
||||||
builder.emit(Opcode.OBJ_TO_BOOL, leftValue.slot, slot)
|
|
||||||
CompiledValue(slot, SlotType.BOOL)
|
|
||||||
}
|
|
||||||
val resultSlot = allocSlot()
|
val resultSlot = allocSlot()
|
||||||
val trueId = builder.addConst(BytecodeConst.Bool(true))
|
val trueId = builder.addConst(BytecodeConst.Bool(true))
|
||||||
builder.emit(Opcode.CONST_BOOL, trueId, resultSlot)
|
builder.emit(Opcode.CONST_BOOL, trueId, resultSlot)
|
||||||
val endLabel = builder.label()
|
val endLabel = builder.label()
|
||||||
builder.emit(
|
builder.emit(
|
||||||
Opcode.JMP_IF_TRUE,
|
Opcode.JMP_IF_TRUE,
|
||||||
listOf(CmdBuilder.Operand.IntVal(leftBool.slot), CmdBuilder.Operand.LabelRef(endLabel))
|
listOf(CmdBuilder.Operand.IntVal(leftValue.slot), CmdBuilder.Operand.LabelRef(endLabel))
|
||||||
)
|
)
|
||||||
val rightValue = compileRefWithFallback(ref.right(), SlotType.BOOL, Pos.builtIn) ?: return null
|
val rightValue = compileRefWithFallback(ref.right(), SlotType.BOOL, Pos.builtIn) ?: return null
|
||||||
val rightBool = if (rightValue.type == SlotType.BOOL) {
|
if (rightValue.type != SlotType.BOOL) return null
|
||||||
rightValue
|
builder.emit(Opcode.MOVE_BOOL, rightValue.slot, resultSlot)
|
||||||
} else {
|
|
||||||
val slot = allocSlot()
|
|
||||||
builder.emit(Opcode.OBJ_TO_BOOL, rightValue.slot, slot)
|
|
||||||
CompiledValue(slot, SlotType.BOOL)
|
|
||||||
}
|
|
||||||
builder.emit(Opcode.MOVE_BOOL, rightBool.slot, resultSlot)
|
|
||||||
builder.mark(endLabel)
|
builder.mark(endLabel)
|
||||||
return CompiledValue(resultSlot, SlotType.BOOL)
|
return CompiledValue(resultSlot, SlotType.BOOL)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,9 @@ Candidates (not started)
|
|||||||
2) Mixed numeric ops (done)
|
2) Mixed numeric ops (done)
|
||||||
- Allow INT+REAL arithmetic to use primitive REAL ops (no obj fallback).
|
- Allow INT+REAL arithmetic to use primitive REAL ops (no obj fallback).
|
||||||
- MixedCompareBenchmarkTest: 347 ms -> 275 ms.
|
- MixedCompareBenchmarkTest: 347 ms -> 275 ms.
|
||||||
3) Boolean conversion
|
3) Boolean conversion (done; do not revert without review)
|
||||||
- Skip OBJ_TO_BOOL when compiler already has a BOOL slot.
|
- Skip redundant OBJ_TO_BOOL in logical AND/OR when compiler already emits BOOL.
|
||||||
|
- MixedCompareBenchmarkTest: 275 ms -> 249 ms.
|
||||||
4) Range/loop hot path
|
4) Range/loop hot path
|
||||||
- Keep range iteration in INT ops, avoid accidental boxing.
|
- Keep range iteration in INT ops, avoid accidental boxing.
|
||||||
- Confirm loop-var slots avoid re-boxing in loop bodies.
|
- Confirm loop-var slots avoid re-boxing in loop bodies.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user