mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-10 05:29:49 +00:00
Various optimizations
This commit is contained in:
parent
4a529b5ddc
commit
90a9538936
@ -36,6 +36,8 @@
|
||||
|
||||
* 8080: word negation now works.
|
||||
|
||||
* Various optimization improvements.
|
||||
|
||||
* Various other fixes.
|
||||
|
||||
* Improved some error messages.
|
||||
|
@ -1379,103 +1379,103 @@ object AlwaysGoodOptimizations {
|
||||
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF))).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDA) & HasAddrMode(Immediate) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDX, STX) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF))).* ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDX) & HasAddrMode(Immediate) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDY, STY) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF))).* ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDY) & HasAddrMode(Immediate) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDX, STX) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDY, STY) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDA) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_AF))).* ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_AF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDA) & HasAddrMode(Immediate) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDX) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesX) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_XF))).* ~
|
||||
(Linear & Not(ChangesX) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_XF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDX) & HasAddrMode(Immediate) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDY) & HasAddrMode(Immediate) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesY) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_YF))).* ~
|
||||
(Linear & Not(ChangesY) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_YF)) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDY) & HasAddrMode(Immediate) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesX) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesX) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesY) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesY) & Not(ChangesNAndZ) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(ShortConditionalBranching & MatchParameter(2)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(2)) ~
|
||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDX, STX) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(ShortConditionalBranching & MatchParameter(2)) ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesX) & Not(HasOpcode(DISCARD_XF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(2)) ~
|
||||
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDY, STY) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(ShortConditionalBranching & MatchParameter(2)) ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesY) & Not(HasOpcode(DISCARD_YF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(2)) ~
|
||||
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(ShortBranching & MatchParameter(3)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(HasOpcode(LABEL) & MatchParameter(3) & HasCallerCount(1)) ~
|
||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
HasOpcodeIn(TXA, TAX, LAX, LXA) ~
|
||||
(Not(HasOpcodeIn(TXA, TAX)) & Linear & Not(ChangesA) & Not(ChangesX)).* ~
|
||||
(Not(HasOpcodeIn(TXA, TAX)) & Linear & Not(ChangesA) & Not(ChangesX) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcodeIn(TXA, TAX) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
HasOpcodeIn(TYA, TAY) ~
|
||||
(Not(HasOpcodeIn(TYA, TAY)) & Linear & Not(ChangesA) & Not(ChangesY)).* ~
|
||||
(Not(HasOpcodeIn(TYA, TAY)) & Linear & Not(ChangesA) & Not(ChangesY) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcodeIn(TYA, TAY) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(STA, LDA) & HasAddrModeIn(ZeroPage, Absolute) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(HasOpcode(TAX)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(HasOpcode(TAX)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
HasOpcode(TAX) ~
|
||||
(LinearOrBranch & Not(ChangesX) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Elidable & HasOpcode(LDX) & HasAddrModeIn(ZeroPage, Absolute) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(STA, LDA) & HasAddrModeIn(ZeroPage, Absolute) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(HasOpcode(TAY)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(HasOpcode(TAY)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
HasOpcode(TAY) ~
|
||||
(LinearOrBranch & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Elidable & HasOpcode(LDY) & HasAddrModeIn(ZeroPage, Absolute) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAX)),
|
||||
|
||||
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1)).* ~
|
||||
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1) | HasOpcodeIn(OpcodeClasses.ShortConditionalBranching)).* ~
|
||||
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAY)),
|
||||
)
|
||||
|
||||
@ -3046,6 +3046,66 @@ object AlwaysGoodOptimizations {
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(1) & IsNotALabelUsedManyTimes & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V)) ~~> { code =>
|
||||
List(code(1).copy(opcode = LDA), code.head.copy(opcode = AND))
|
||||
},
|
||||
|
||||
(Elidable & HasOpcode(CMP) & HasAddrMode(Immediate)) ~
|
||||
(Elidable & HasOpcodeIn(BEQ, BNE) & MatchParameter(1)) ~
|
||||
(Elidable & HasAddrMode(Implied) & HasOpcodeIn(INC, DEC) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V)) ~
|
||||
(Elidable & HasOpcode(JMP) & HasAddrModeIn(Absolute, LongAbsolute)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V, State.A)) ~~> { code =>
|
||||
val delta = code(2).opcode match {
|
||||
case INC => +1
|
||||
case DEC => -1
|
||||
}
|
||||
val branch = code(1).opcode match {
|
||||
case BEQ => BNE
|
||||
case BNE => BEQ
|
||||
}
|
||||
List(
|
||||
code(2),
|
||||
code.head.copy(parameter = (code.head.parameter + delta).quickSimplify),
|
||||
code(1).copy(opcode = branch, parameter = code(3).parameter),
|
||||
code(4))
|
||||
},
|
||||
|
||||
(Elidable & HasOpcode(CPX) & HasAddrMode(Immediate)) ~
|
||||
(Elidable & HasOpcodeIn(BEQ, BNE) & MatchParameter(1)) ~
|
||||
(Elidable & HasAddrMode(Implied) & HasOpcodeIn(INX, DEX) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V)) ~
|
||||
(Elidable & HasOpcode(JMP) & HasAddrModeIn(Absolute, LongAbsolute)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V, State.X)) ~~> { code =>
|
||||
val delta = code(2).opcode match {
|
||||
case INX => +1
|
||||
case DEX => -1
|
||||
}
|
||||
val branch = code(1).opcode match {
|
||||
case BEQ => BNE
|
||||
case BNE => BEQ
|
||||
}
|
||||
List(
|
||||
code(2),
|
||||
code.head.copy(parameter = (code.head.parameter + delta).quickSimplify),
|
||||
code(1).copy(opcode = branch, parameter = code(3).parameter),
|
||||
code(4))
|
||||
},
|
||||
|
||||
(Elidable & HasOpcode(CPY) & HasAddrMode(Immediate)) ~
|
||||
(Elidable & HasOpcodeIn(BEQ, BNE) & MatchParameter(1)) ~
|
||||
(Elidable & HasAddrMode(Implied) & HasOpcodeIn(INY, DEY) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V)) ~
|
||||
(Elidable & HasOpcode(JMP) & HasAddrModeIn(Absolute, LongAbsolute)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V, State.Y)) ~~> { code =>
|
||||
val delta = code(2).opcode match {
|
||||
case INY => +1
|
||||
case DEY => -1
|
||||
}
|
||||
val branch = code(1).opcode match {
|
||||
case BEQ => BNE
|
||||
case BNE => BEQ
|
||||
}
|
||||
List(
|
||||
code(2),
|
||||
code.head.copy(parameter = (code.head.parameter + delta).quickSimplify),
|
||||
code(1).copy(opcode = branch, parameter = code(3).parameter),
|
||||
code(4))
|
||||
},
|
||||
)
|
||||
|
||||
private val powersOf2: List[(Int, Int)] = List(
|
||||
|
@ -94,55 +94,76 @@ object AlwaysGoodI80Optimizations {
|
||||
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
|
||||
for7Registers(register =>
|
||||
Is8BitLoad(ZRegister.MEM_HL, register) ~
|
||||
(Linear & Not(Changes(ZRegister.H)) & Not(Changes(ZRegister.L)) & Not(ChangesMemory) & Not(Changes(register)) & Not(IsRegular8BitLoadFrom(ZRegister.MEM_HL))).* ~
|
||||
(HasOpcodeIn(Set(JP,JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & Not(Changes(ZRegister.H)) & Not(Changes(ZRegister.L)) & Not(ChangesMemory) & Not(Changes(register)) & Not(IsRegular8BitLoadFrom(ZRegister.MEM_HL))).* ~
|
||||
(Elidable & Is8BitLoad(register, ZRegister.MEM_HL)) ~~> { code => code.init }
|
||||
),
|
||||
for7Registers(register =>
|
||||
Is8BitLoad(register, ZRegister.MEM_HL) ~
|
||||
(HasOpcodeIn(Set(JP,JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & Not(Changes(ZRegister.H)) & Not(Changes(ZRegister.L)) & Not(ChangesMemory) & Not(Changes(register)) & Not(IsRegular8BitLoadFrom(ZRegister.MEM_HL))).* ~
|
||||
(Elidable & Is8BitLoad(register, ZRegister.MEM_HL)) ~~> { code => code.init }
|
||||
),
|
||||
for7Registers(register =>
|
||||
Is8BitLoad(ZRegister.MEM_HL, register) ~
|
||||
(Linear & Not(Changes(ZRegister.H)) & Not(Changes(ZRegister.L)) & Not(ChangesMemory) & Not(Changes(register)) & Not(IsRegular8BitLoadFrom(ZRegister.MEM_HL))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & Not(Changes(ZRegister.H)) & Not(Changes(ZRegister.L)) & Not(ChangesMemory) & Not(Changes(register)) & Not(IsRegular8BitLoadFrom(ZRegister.MEM_HL))).* ~
|
||||
(Elidable & IsRegular8BitLoadFrom(ZRegister.MEM_HL)) ~~> { code =>
|
||||
val last = code.last
|
||||
code.init :+ last.copy(registers = TwoRegisters(last.registers.asInstanceOf[TwoRegisters].target, register))
|
||||
}
|
||||
),
|
||||
(Is8BitLoad(ZRegister.MEM_ABS_8, ZRegister.A) & MatchParameter(0)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8) & MatchParameter(0)) ~~> { code => code.init },
|
||||
(Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8) & MatchParameter(0)).captureLine(1) ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8) & MatchParameter(0)) ~~> { code => code.init },
|
||||
|
||||
(Is8BitLoad(ZRegister.MEM_HL, ZRegister.A) & MatchConstantInHL(0)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8) & MatchParameter(0)) ~~> { code => code.init },
|
||||
|
||||
(Is8BitLoad(ZRegister.MEM_ABS_8, ZRegister.A) & MatchParameter(0)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_HL) & MatchConstantInHL(0)) ~~> { code => code.init },
|
||||
|
||||
(Is8BitLoad(ZRegister.MEM_HL, ZRegister.A) & MatchConstantInHL(0)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.A))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_HL) & MatchConstantInHL(0)) ~~> { code => code.init },
|
||||
|
||||
(Is16BitLoad(ZRegister.MEM_ABS_16, ZRegister.HL) & MatchParameter(0)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.HL))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Changes(ZRegister.HL))).* ~
|
||||
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.MEM_ABS_16) & MatchParameter(0)) ~~> { code => code.init },
|
||||
|
||||
(Is8BitLoad(ZRegister.MEM_ABS_8, ZRegister.A) & MatchParameter(0) & MatchRegister(ZRegister.A, 2)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8))).* ~
|
||||
(Elidable & Is8BitLoad(ZRegister.A, ZRegister.MEM_ABS_8) & MatchParameter(0)) ~~> { (code, ctx) =>
|
||||
code.init :+ ZLine.ldImm8(ZRegister.A, ctx.get[Int](2))
|
||||
},
|
||||
|
||||
(Is16BitLoad(ZRegister.MEM_ABS_16, ZRegister.HL) & MatchParameter(0) & MatchConstantInHL(2)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Is16BitLoad(ZRegister.HL, ZRegister.MEM_ABS_16))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Is16BitLoad(ZRegister.HL, ZRegister.MEM_ABS_16))).* ~
|
||||
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.MEM_ABS_16) & MatchParameter(0)) ~~> { (code, ctx) =>
|
||||
code.init :+ ZLine.ldImm16(ZRegister.HL, ctx.get[Constant](2))
|
||||
},
|
||||
|
||||
for5LargeRegisters(register =>
|
||||
(Is8BitLoad(MEM_ABS_8, ZRegister.A) & MatchParameter(0) & MatchRegister(A, 2)).captureLine(1) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & Not(Is8BitLoad(MEM_ABS_8, ZRegister.A))).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & Not(Is8BitLoad(MEM_ABS_8, ZRegister.A))).* ~
|
||||
(Is8BitLoad(MEM_ABS_8, ZRegister.A) & MatchParameter(10) & MatchRegister(A, 12)).captureLine(11) ~
|
||||
Where(ctx => ctx.get[Constant](0).succ == ctx.get[Constant](10)) ~
|
||||
(Linear & DoesntChangeMemoryAt(1) & DoesntChangeMemoryAt(11)).* ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Not(HasRegisters(NoRegisters)) |
|
||||
Linear & DoesntChangeMemoryAt(1) & DoesntChangeMemoryAt(11)).* ~
|
||||
(Elidable & Is16BitLoad(register, MEM_ABS_16) & MatchParameter(0) & MatchRegister(A, 12)) ~~> { (code, ctx) =>
|
||||
val hi = ctx.get[Int](12)
|
||||
val lo = ctx.get[Int](2)
|
||||
@ -859,6 +880,50 @@ object AlwaysGoodI80Optimizations {
|
||||
),
|
||||
)
|
||||
|
||||
val SimplifiableComparison = new RuleBasedAssemblyOptimization("Simplifiable comparison",
|
||||
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
|
||||
|
||||
(Elidable & HasOpcode(CP) & HasRegisterParam(ZRegister.IMM_8)) ~
|
||||
(Elidable & HasOpcodeIn(Set(JR, JP)) & MatchJumpTarget(1) & (HasRegisters(IfFlagSet(ZFlag.Z)) | HasRegisters(IfFlagClear(ZFlag.Z)))) ~
|
||||
(Elidable & HasOpcodeIn(Set(INC, DEC)) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlags) ~
|
||||
(Elidable & HasOpcodeIn(Set(JR, JP)) & IsUnconditional) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchJumpTarget(1) & IsUnconditional & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(ZRegister.A)) ~~> { code =>
|
||||
val delta = code(2).opcode match {
|
||||
case INC => +1
|
||||
case DEC => -1
|
||||
}
|
||||
val branch = code(1).registers.negate
|
||||
List(
|
||||
code(2),
|
||||
code.head.copy(parameter = (code.head.parameter + delta).quickSimplify),
|
||||
code(1).copy(opcode=JP, registers = branch, parameter = code(3).parameter),
|
||||
code(4))
|
||||
},
|
||||
|
||||
for6Registers(reg =>
|
||||
(Elidable & Is8BitLoad(ZRegister.A, reg)) ~
|
||||
(Elidable & HasOpcode(CP) & HasRegisterParam(ZRegister.IMM_8)) ~
|
||||
(Elidable & HasOpcodeIn(Set(JR, JP)) & MatchJumpTarget(1) & DoesntMatterWhatItDoesWith(ZRegister.A) & (HasRegisters(IfFlagSet(ZFlag.Z)) | HasRegisters(IfFlagClear(ZFlag.Z)))) ~
|
||||
(Elidable & HasOpcodeIn(Set(INC, DEC)) & HasRegisterParam(reg) & DoesntMatterWhatItDoesWithFlags) ~
|
||||
(Elidable & HasOpcodeIn(Set(JR, JP)) & IsUnconditional) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchJumpTarget(1) & IsUnconditional & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(ZRegister.A, reg)) ~~> { code =>
|
||||
val delta = code(3).opcode match {
|
||||
case INC => +1
|
||||
case DEC => -1
|
||||
}
|
||||
val branch = code(2).registers.negate
|
||||
List(
|
||||
code(3),
|
||||
code.head,
|
||||
code(1).copy(parameter = (code(1).parameter + delta).quickSimplify),
|
||||
code(2).copy(opcode=JP, registers = branch, parameter = code(4).parameter),
|
||||
code(5))
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
)
|
||||
|
||||
val FreeHL = new RuleBasedAssemblyOptimization("Free HL",
|
||||
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
|
||||
// 0
|
||||
@ -1218,6 +1283,14 @@ object AlwaysGoodI80Optimizations {
|
||||
(HasOpcodeIn(Set(JP, JR)) & MatchJumpTarget(0) & Elidable) ~
|
||||
HasOpcodeIn(ZOpcodeClasses.NoopDiscards).* ~
|
||||
(HasOpcode(LABEL) & MatchJumpTarget(0)) ~~> (c => c.last :: Nil),
|
||||
(HasOpcodeIn(Set(JP, JR)) & MatchJumpTarget(0) & IsConditional & Elidable) ~
|
||||
(HasOpcodeIn(Set(JP, JR)) & Elidable & IsUnconditional) ~
|
||||
(HasOpcode(LABEL) & MatchJumpTarget(0)) ~~> { code =>
|
||||
List(
|
||||
code(1).copy(opcode = JP, registers = code.head.registers.negate),
|
||||
code(2)
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
val SimplifiableShifting = new RuleBasedAssemblyOptimization("Simplifiable shifting",
|
||||
@ -1762,6 +1835,7 @@ object AlwaysGoodI80Optimizations {
|
||||
PointlessStackUnstashing,
|
||||
ReloadingKnownValueFromMemory,
|
||||
ShiftingKnownValue,
|
||||
SimplifiableComparison,
|
||||
SimplifiableMaths,
|
||||
SimplifiableShifting,
|
||||
UnusedCodeRemoval,
|
||||
|
@ -719,6 +719,13 @@ case object IsUnconditional extends AssemblyLinePattern {
|
||||
override def hitRate: Double = 0.212
|
||||
}
|
||||
|
||||
case object IsConditional extends AssemblyLinePattern {
|
||||
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
|
||||
line.registers.isInstanceOf[IfFlagSet] || line.registers.isInstanceOf[IfFlagClear]
|
||||
|
||||
override def hitRate: Double = 0.212
|
||||
}
|
||||
|
||||
case class MatchConstantInHL(i: Int) extends AssemblyLinePattern {
|
||||
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||
|
@ -144,4 +144,28 @@ class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
test("Bubblesort") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
|array sorttable [2540] @$C000
|
||||
|
|
||||
|void main() {
|
||||
| byte t,i,n1,n2
|
||||
| for t,25,downto,0{
|
||||
| for i,0,to,25{
|
||||
| n1 = sorttable[i]
|
||||
| n2 = sorttable[i+1]
|
||||
| if n1>n2 {
|
||||
| sorttable[i] = n2
|
||||
| sorttable[i+1] = n1
|
||||
| }
|
||||
| }
|
||||
| }
|
||||
|}
|
||||
|
|
||||
|""".stripMargin) { m =>
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user