mirror of
https://github.com/irmen/prog8.git
synced 2026-04-21 02:16:41 +00:00
ir: consolidate IRCodeInstruction and Instruction
This commit is contained in:
@@ -34,9 +34,9 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove nops") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "dummy"),
|
||||
IRCodeInstruction(Opcode.NOP),
|
||||
IRCodeInstruction(Opcode.NOP)
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "dummy"),
|
||||
IRInstruction(Opcode.NOP),
|
||||
IRInstruction(Opcode.NOP)
|
||||
))
|
||||
irProg.lines().size shouldBe 3
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@@ -46,13 +46,13 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove jmp to label below") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label"), // removed
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label"), // removed
|
||||
IRCodeLabel("label"),
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label2"), // removed
|
||||
IRCodeInstruction(Opcode.NOP), // removed
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label2"), // removed
|
||||
IRInstruction(Opcode.NOP), // removed
|
||||
IRCodeLabel("label2"),
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label3"),
|
||||
IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=1),
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label3"),
|
||||
IRInstruction(Opcode.INC, VmDataType.BYTE, reg1=1),
|
||||
IRCodeLabel("label3")
|
||||
))
|
||||
irProg.lines().size shouldBe 8
|
||||
@@ -62,57 +62,57 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
lines.size shouldBe 5
|
||||
(lines[0] as IRCodeLabel).name shouldBe "label"
|
||||
(lines[1] as IRCodeLabel).name shouldBe "label2"
|
||||
(lines[2] as IRCodeInstruction).ins.opcode shouldBe Opcode.JUMP
|
||||
(lines[3] as IRCodeInstruction).ins.opcode shouldBe Opcode.INC
|
||||
(lines[2] as IRInstruction).opcode shouldBe Opcode.JUMP
|
||||
(lines[3] as IRInstruction).opcode shouldBe Opcode.INC
|
||||
(lines[4] as IRCodeLabel).name shouldBe "label3"
|
||||
}
|
||||
|
||||
test("remove double sec/clc") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.CLC),
|
||||
IRCodeInstruction(Opcode.CLC),
|
||||
IRCodeInstruction(Opcode.CLC)
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.CLC),
|
||||
IRInstruction(Opcode.CLC),
|
||||
IRInstruction(Opcode.CLC)
|
||||
))
|
||||
irProg.lines().size shouldBe 6
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 1
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.CLC
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.CLC
|
||||
}
|
||||
|
||||
test("push followed by pop") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=42),
|
||||
IRCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=42),
|
||||
IRCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=99),
|
||||
IRCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=222)
|
||||
IRInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=42),
|
||||
IRInstruction(Opcode.POP, VmDataType.BYTE, reg1=42),
|
||||
IRInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=99),
|
||||
IRInstruction(Opcode.POP, VmDataType.BYTE, reg1=222)
|
||||
))
|
||||
irProg.lines().size shouldBe 4
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 1
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOADR
|
||||
(lines[0] as IRCodeInstruction).ins.reg1 shouldBe 222
|
||||
(lines[0] as IRCodeInstruction).ins.reg2 shouldBe 99
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.LOADR
|
||||
(lines[0] as IRInstruction).reg1 shouldBe 222
|
||||
(lines[0] as IRInstruction).reg2 shouldBe 99
|
||||
}
|
||||
|
||||
test("remove useless div/mul, add/sub") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 0)
|
||||
IRInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 0)
|
||||
))
|
||||
irProg.lines().size shouldBe 10
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@@ -123,28 +123,28 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("replace add/sub 1 by inc/dec") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 1)
|
||||
IRInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
irProg.lines().size shouldBe 2
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 2
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.INC
|
||||
(lines[1] as IRCodeInstruction).ins.opcode shouldBe Opcode.DEC
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.INC
|
||||
(lines[1] as IRInstruction).opcode shouldBe Opcode.DEC
|
||||
}
|
||||
|
||||
test("remove useless and/or/xor") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 65535),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 200),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 60000),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 1)
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 65535),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 200),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 60000),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
irProg.lines().size shouldBe 8
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@@ -155,23 +155,23 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("replace and/or/xor by constant number") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.WORD, reg1=42, value = 65535)
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRInstruction(Opcode.OR, VmDataType.WORD, reg1=42, value = 65535)
|
||||
))
|
||||
irProg.lines().size shouldBe 4
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 4
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[1] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[2] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[3] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[0] as IRCodeInstruction).ins.value shouldBe 0
|
||||
(lines[1] as IRCodeInstruction).ins.value shouldBe 0
|
||||
(lines[2] as IRCodeInstruction).ins.value shouldBe 255
|
||||
(lines[3] as IRCodeInstruction).ins.value shouldBe 65535
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[1] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[2] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[3] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[0] as IRInstruction).value shouldBe 0
|
||||
(lines[1] as IRInstruction).value shouldBe 0
|
||||
(lines[2] as IRInstruction).value shouldBe 255
|
||||
(lines[3] as IRInstruction).value shouldBe 65535
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user