mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-14 07:54:29 +00:00
Constant pointer optimization
This commit is contained in:
parent
f8bd496b6b
commit
50b93db337
@ -133,6 +133,7 @@ object OptimizationPresets {
|
|||||||
AlwaysGoodOptimizations.CommonBranchBodyOptimization,
|
AlwaysGoodOptimizations.CommonBranchBodyOptimization,
|
||||||
AlwaysGoodOptimizations.CommonExpressionInConditional,
|
AlwaysGoodOptimizations.CommonExpressionInConditional,
|
||||||
AlwaysGoodOptimizations.CommonIndexSubexpressionElimination,
|
AlwaysGoodOptimizations.CommonIndexSubexpressionElimination,
|
||||||
|
AlwaysGoodOptimizations.ConstantPointer,
|
||||||
AlwaysGoodOptimizations.ConstantFlowAnalysis,
|
AlwaysGoodOptimizations.ConstantFlowAnalysis,
|
||||||
AlwaysGoodOptimizations.ConstantIndexPropagation,
|
AlwaysGoodOptimizations.ConstantIndexPropagation,
|
||||||
AlwaysGoodOptimizations.DoubleJumpSimplification,
|
AlwaysGoodOptimizations.DoubleJumpSimplification,
|
||||||
|
@ -1395,4 +1395,53 @@ object AlwaysGoodOptimizations {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this grows the code by one byte, but shaves 1 cycle and allows for optimizing some stores away
|
||||||
|
val ConstantPointer = new RuleBasedAssemblyOptimization("Constant pointer optimization",
|
||||||
|
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
|
||||||
|
|
||||||
|
(HasOpcode(STA) & MatchA(0) & HasAddrModeIn(Set(Absolute, ZeroPage)) & MatchParameter(4)) ~
|
||||||
|
Where(ctx => {
|
||||||
|
val lo = ctx.get[Constant](4)
|
||||||
|
ctx.addObject(5, lo + 1)
|
||||||
|
ctx.addObject(3, ZeroPage)
|
||||||
|
true
|
||||||
|
}) ~
|
||||||
|
(Linear & DoesNotConcernMemoryAt(3,4) & DoesNotConcernMemoryAt(3,5)).* ~
|
||||||
|
(HasOpcode(STA) & MatchA(1) & HasAddrModeIn(Set(Absolute, ZeroPage)) & MatchParameter(5)) ~
|
||||||
|
Where(ctx => {
|
||||||
|
val lo = ctx.get[Int](0) & 0xff
|
||||||
|
val hi = ctx.get[Int](1) & 0xff
|
||||||
|
ctx.addObject(2, hi * 256 + lo)
|
||||||
|
true
|
||||||
|
}) ~
|
||||||
|
(Linear & DoesNotConcernMemoryAt(3,4) & DoesNotConcernMemoryAt(3,5)).* ~
|
||||||
|
(Elidable & MatchParameter(6) & HasAddrModeIn(Set(ZeroPageIndirect, IndexedY))) ~~> { (code, ctx) =>
|
||||||
|
val addr = ctx.get[Int](2)
|
||||||
|
val last = code.last
|
||||||
|
code.init :+ last.copy(parameter = NumericConstant(addr, 2), addrMode = if (last.addrMode == ZeroPageIndirect) Absolute else AbsoluteY)
|
||||||
|
},
|
||||||
|
|
||||||
|
(HasOpcode(STA) & MatchA(0) & HasAddrModeIn(Set(Absolute, ZeroPage)) & MatchParameter(4)) ~
|
||||||
|
Where(ctx => {
|
||||||
|
val lo = ctx.get[Constant](4)
|
||||||
|
ctx.addObject(5, lo + 1)
|
||||||
|
ctx.addObject(3, ZeroPage)
|
||||||
|
true
|
||||||
|
}) ~
|
||||||
|
(Linear & DoesNotConcernMemoryAt(3,4) & DoesNotConcernMemoryAt(3,5)).* ~
|
||||||
|
(HasOpcode(STX) & MatchX(1) & HasAddrModeIn(Set(Absolute, ZeroPage)) & MatchParameter(5)) ~
|
||||||
|
Where(ctx => {
|
||||||
|
val lo = ctx.get[Int](0) & 0xff
|
||||||
|
val hi = ctx.get[Int](1) & 0xff
|
||||||
|
ctx.addObject(2, hi * 256 + lo)
|
||||||
|
true
|
||||||
|
}) ~
|
||||||
|
(Linear & DoesNotConcernMemoryAt(3,4) & DoesNotConcernMemoryAt(3,5)).* ~
|
||||||
|
(Elidable & MatchParameter(6) & HasAddrModeIn(Set(ZeroPageIndirect, IndexedY))) ~~> { (code, ctx) =>
|
||||||
|
val addr = ctx.get[Int](2)
|
||||||
|
val last = code.last
|
||||||
|
code.init :+ last.copy(parameter = NumericConstant(addr, 2), addrMode = if (last.addrMode == ZeroPageIndirect) Absolute else AbsoluteY)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
2
src/main/scala/millfork/env/Constant.scala
vendored
2
src/main/scala/millfork/env/Constant.scala
vendored
@ -158,6 +158,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
val l = lhs.quickSimplify
|
val l = lhs.quickSimplify
|
||||||
val r = rhs.quickSimplify
|
val r = rhs.quickSimplify
|
||||||
(l, r) match {
|
(l, r) match {
|
||||||
|
case (CompoundConstant(MathOperator.Shl, HalfWordConstant(c1, true), NumericConstant(8, _)), HalfWordConstant(c2, false)) if operator == MathOperator.Or && c1 == c2 => c1
|
||||||
case (NumericConstant(lv, ls), NumericConstant(rv, rs)) =>
|
case (NumericConstant(lv, ls), NumericConstant(rv, rs)) =>
|
||||||
var size = ls max rs
|
var size = ls max rs
|
||||||
val value = operator match {
|
val value = operator match {
|
||||||
@ -233,6 +234,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
val That = that
|
val That = that
|
||||||
val MinusThat = -that
|
val MinusThat = -that
|
||||||
this match {
|
this match {
|
||||||
|
case CompoundConstant(Plus, CompoundConstant(Shl, HalfWordConstant(c1, true), NumericConstant(8, _)), HalfWordConstant(c2, false)) if c1 == c2 => c1
|
||||||
case CompoundConstant(Plus, NumericConstant(MinusThat, _), r) => r
|
case CompoundConstant(Plus, NumericConstant(MinusThat, _), r) => r
|
||||||
case CompoundConstant(Plus, l, NumericConstant(MinusThat, _)) => l
|
case CompoundConstant(Plus, l, NumericConstant(MinusThat, _)) => l
|
||||||
case CompoundConstant(Plus, NumericConstant(x, _), r) => CompoundConstant(Plus, r, NumericConstant(x + that, minimumSize(x + that)))
|
case CompoundConstant(Plus, NumericConstant(x, _), r) => CompoundConstant(Plus, r, NumericConstant(x + that, minimumSize(x + that)))
|
||||||
|
@ -408,4 +408,24 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
|||||||
| }
|
| }
|
||||||
""".stripMargin).readByte(0xc000) should equal(1)
|
""".stripMargin).readByte(0xc000) should equal(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("Constant pointers") {
|
||||||
|
EmuBenchmarkRun(
|
||||||
|
"""
|
||||||
|
|byte output0 @$c000
|
||||||
|
|byte output1 @$c001
|
||||||
|
|void main() {
|
||||||
|
| pointer p
|
||||||
|
| p = output0.addr
|
||||||
|
| p[0] = 33
|
||||||
|
| p = op()
|
||||||
|
| p[0] = 34
|
||||||
|
|}
|
||||||
|
|word op () { return output1.addr }
|
||||||
|
""".stripMargin
|
||||||
|
){m =>
|
||||||
|
m.readByte(0xc000) should equal(33)
|
||||||
|
m.readByte(0xc001) should equal(34)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ object EmuOptimizedInlinedRun extends EmuRun(
|
|||||||
OptimizationPresets.Good,
|
OptimizationPresets.Good,
|
||||||
false) {
|
false) {
|
||||||
override def inline: Boolean = true
|
override def inline: Boolean = true
|
||||||
override def blastProcessing: Boolean = true
|
override def blastProcessing: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user