mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
Fix IR peephole crash on lsigb.l + ext.b with mismatched register types
regression was introduced in commit 2ce7a63c1e
This commit is contained in:
1 parent
c9a7dc05d9
commit
8c2bc15b41
2 files changed
+54
-4
No files matched your search
@@ -1158,13 +1158,18 @@ jump p8_label_gen_2
|
||||
mods.add(Mod(i+1, IRInstructions.binaryImmediate(Opcode.AND, IRDataType.LONG, outer.requireDest().registerNumber, 0xffff)))
|
||||
mods.add(Mod(i, IRInstructions.move(IRDataType.LONG, outer.requireDest().registerNumber, inner.requireSrcA().registerNumber)))
|
||||
}
|
||||
// truncate-long/word-to-byte followed by zero-extend byte-to-word == mask with $ff
|
||||
// truncate-long/word-to-byte followed by zero-extend byte-to-word == mask with $ff.
|
||||
// This is only valid when the source and destination have the same type, because
|
||||
// the rewritten loadr would otherwise access the source register with a different
|
||||
// type than its definition (e.g. long source to word dest).
|
||||
inner.opcode==Opcode.LSIGB && inner.type in setOf(IRDataType.WORD, IRDataType.LONG)
|
||||
&& outer.opcode==Opcode.EXT && outer.type==IRDataType.BYTE
|
||||
&& mid!=null && mid==outer.srcA?.register && inner.srcA!=null && outer.dest!=null
|
||||
&& readCounts.getValue(mid)==1 -> {
|
||||
mods.add(Mod(i+1, IRInstructions.binaryImmediate(Opcode.AND, inner.type!!, outer.requireDest().registerNumber, 0xff)))
|
||||
mods.add(Mod(i, IRInstructions.move(inner.type!!, outer.requireDest().registerNumber, inner.requireSrcA().registerNumber)))
|
||||
&& readCounts.getValue(mid)==1
|
||||
&& inner.type == outer.requireDest().type -> {
|
||||
val resultType = outer.requireDest().type
|
||||
mods.add(Mod(i+1, IRInstructions.binaryImmediate(Opcode.AND, resultType, outer.requireDest().registerNumber, 0xff)))
|
||||
mods.add(Mod(i, IRInstructions.move(resultType, outer.requireDest().registerNumber, inner.requireSrcA().registerNumber)))
|
||||
}
|
||||
else -> continue
|
||||
}
|
||||
|
||||
@@ -514,6 +514,51 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
instr[2].requireImmediateInt() shouldBe 42
|
||||
}
|
||||
|
||||
test("collapse lsigb.w + ext.b into loadr.w + and.w") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRInstructions.loadMemory(Opcode.LOADM, IRDataType.WORD, 7, IRMemory.direct("src")),
|
||||
IRInstructions.binary(Opcode.LSIGB, IRDataType.WORD, 8, 7),
|
||||
IRInstructions.binary(Opcode.EXT, IRDataType.BYTE, 9, 8),
|
||||
IRInstructions.binary(Opcode.ADDR, IRDataType.WORD, 2, 9),
|
||||
IRInstructions.returnVoid()
|
||||
))
|
||||
val opt = IRPeepholeOptimizer(irProg, false)
|
||||
opt.optimize(true, ErrorReporterForTests())
|
||||
val instr = irProg.chunks().single().instructions
|
||||
instr.any { it.opcode == Opcode.LSIGB } shouldBe false
|
||||
instr.any { it.opcode == Opcode.EXT && it.requireDest().register == VirtualRegister.int(9) } shouldBe false
|
||||
instr.any {
|
||||
it.opcode == Opcode.LOADR &&
|
||||
it.type == IRDataType.WORD &&
|
||||
it.requireDest().register == VirtualRegister.int(9) &&
|
||||
it.requireSrcA().register == VirtualRegister.int(7)
|
||||
} shouldBe true
|
||||
instr.any {
|
||||
it.opcode == Opcode.AND &&
|
||||
it.type == IRDataType.WORD &&
|
||||
it.requireDest().register == VirtualRegister.int(9) &&
|
||||
it.requireImmediateInt() == 0xff
|
||||
} shouldBe true
|
||||
}
|
||||
|
||||
test("do not collapse lsigb.l + ext.b when source and dest types differ") {
|
||||
// lsigb.l produces a byte from a long; ext.b widens it to word. Rewriting this as
|
||||
// loadr + and would require accessing the long source as word, which conflicts with
|
||||
// the register type system. The optimizer must leave the original sequence intact.
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRInstructions.loadMemory(Opcode.LOADM, IRDataType.LONG, 7, IRMemory.direct("src")),
|
||||
IRInstructions.binary(Opcode.LSIGB, IRDataType.LONG, 8, 7),
|
||||
IRInstructions.binary(Opcode.EXT, IRDataType.BYTE, 9, 8),
|
||||
IRInstructions.binary(Opcode.ADDR, IRDataType.WORD, 2, 9),
|
||||
IRInstructions.returnVoid()
|
||||
))
|
||||
val opt = IRPeepholeOptimizer(irProg, false)
|
||||
opt.optimize(true, ErrorReporterForTests())
|
||||
val instr = irProg.chunks().single().instructions
|
||||
instr.any { it.opcode == Opcode.LSIGB } shouldBe true
|
||||
instr.any { it.opcode == Opcode.EXT && it.requireDest().register == VirtualRegister.int(9) } shouldBe true
|
||||
}
|
||||
|
||||
test("coalesce redundant LOADX/STOREX to same index is removed") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRInstructions.loadMemory(Opcode.LOADX, IRDataType.BYTE, 1, IRMemory.indexed("myArray", 10, indexRegType)),
|
||||
|
||||
Reference in new issue
Block a user