1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-23 23:30:22 +00:00

Optimize loads of the same value that was just checked to be in a register

This commit is contained in:
Karol Stasiak 2019-12-01 03:11:30 +01:00
parent 3b7ceb3900
commit 7be5b14a7d
5 changed files with 102 additions and 1 deletions

View File

@ -554,6 +554,43 @@ object LaterOptimizations {
(Elidable & HasOpcode(STA) & HasAddrModeIn(Absolute, ZeroPage) & DoesntMatterWhatItDoesWith(State.A)) ~~>{ code =>
List(code.head, code.last.copy(opcode = STY))
},
(Elidable & HasOpcode(CMP) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDA) & MatchParameter(0) & MatchAddrMode(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~>{ code =>
code.init
},
(Elidable & HasOpcode(CPX) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDX) & MatchParameter(0) & MatchAddrMode(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~>{ code =>
code.init
},
(Elidable & HasOpcode(CPY) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDY) & MatchParameter(0) & MatchAddrMode(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~>{ code =>
code.init
},
(Elidable & HasOpcode(CMP) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDX) & MatchParameter(0) & MatchAddrMode(1)) ~~>{ code =>
code.init :+ AssemblyLine.implied(TAX).pos(code.last.source)
},
(Elidable & HasOpcode(CMP) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE) & IsNotALabelUsedManyTimes) ~
(Elidable & HasOpcode(LDY) & MatchParameter(0) & MatchAddrMode(1)) ~~>{ code =>
code.init :+ AssemblyLine.implied(TAY).pos(code.last.source)
},
(Elidable & HasOpcode(CPX) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDA) & MatchParameter(0) & MatchAddrMode(1)) ~~>{ code =>
code.init :+ AssemblyLine.implied(TXA).pos(code.last.source)
},
(Elidable & HasOpcode(CPY) & MatchParameter(0) & MatchAddrMode(1)) ~
(Elidable & HasOpcode(BNE)) ~
(Elidable & HasOpcode(LDA) & MatchParameter(0) & MatchAddrMode(1)) ~~>{ code =>
code.init :+ AssemblyLine.implied(TYA).pos(code.last.source)
},
)
val DontUseIndexRegisters = new RuleBasedAssemblyOptimization("Don't use index registers unnecessarily",

View File

@ -1625,3 +1625,15 @@ case object IsNotALabelUsedManyTimes extends AssemblyLinePattern {
override def hitRate: Double = 0.92 // ?
}
case object ParameterIsLabel extends AssemblyLinePattern {
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit = FlowInfoRequirement.assertLabels(needsFlowInfo)
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: AssemblyLine): Boolean = line.parameter match {
case MemoryAddressConstant(Label(l)) => true
case _ => false
}
override def hitRate: Double = 0.09 // ?
}

View File

@ -324,6 +324,16 @@ object AlwaysGoodI80Optimizations {
//69
(HasOpcode(LD) & MatchSourceRealRegister(2) & MatchTargetRealRegister(3)) ~
(Elidable & HasOpcode(LD) & MatchSourceRealRegister(3) & MatchTargetRealRegister(2)) ~~> (_.init),
// 70
(HasOpcode(CP) & Match8BitImmediate(1)) ~
(HasOpcodeIn(Set(JP, JR, RET)) & HasRegisters(IfFlagClear(ZFlag.Z))) ~
(Elidable & HasOpcode(LD) & HasTargetRegister(A) & Match8BitImmediate(1)) ~~> (_.init),
// 71
(HasOpcode(CP) & MatchSoleRegisterAndOffset(1)) ~
(HasOpcodeIn(Set(JP, JR, RET)) & HasRegisters(IfFlagClear(ZFlag.Z))) ~
(Elidable & HasOpcode(LD) & HasTargetRegister(A) & MatchSourceRegisterAndOffset(1)) ~~> (_.init),
)
val PointlessStackStashing = new RuleBasedAssemblyOptimization("Pointless stack stashing",

View File

@ -584,6 +584,15 @@ case class MatchSourceRegisterAndOffset(i: Int) extends AssemblyLinePattern {
override def hitRate: Double = 0.931
}
case class HasTargetRegister(i: ZRegister.Value) extends AssemblyLinePattern {
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
line.registers match {
case TwoRegisters(t, _) => t == i
case _ => false
}
override def hitRate: Double = 0.879
}
case class MatchTargetRegisterAndOffset(i: Int) extends AssemblyLinePattern {
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
line.registers match {
@ -1323,4 +1332,16 @@ case object IsNotALabelUsedManyTimes extends AssemblyLinePattern {
}
override def hitRate: Double = 0.999
}
}
case object ParameterIsLabel extends AssemblyLinePattern {
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit = FlowInfoRequirement.assertLabels(needsFlowInfo)
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean = line.parameter match {
case MemoryAddressConstant(Label(l)) => true
case _ => false
}
override def hitRate: Double = 0.09 // ?
}

View File

@ -747,4 +747,25 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
EmuOptimizedZ80Run(c).readByte(0xc000) should equal(13)
EmuOptimizedIntel8080Run(c).readByte(0xc000) should equal(13)
}
test("Optimize load after test") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Intel8080)(
"""
| byte output @ $c000
| void main() {
| f(2)
| }
| noinline void f(byte i) {
| if (i == 2) {
| g(2)
| }
| }
| noinline void g(byte i) {
| output = i
| }
""".stripMargin
) { m =>
m.readByte(0xc000) should equal(2)
}
}
}