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

8080: Fix some stack-related optimizations

This commit is contained in:
Karol Stasiak 2020-04-06 12:00:10 +02:00
parent f04f5ec111
commit 5b3e812bb1
2 changed files with 31 additions and 9 deletions

View File

@ -419,7 +419,7 @@ object AlwaysGoodI80Optimizations {
},
//20
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.HL) & DoesntMatterWhatItDoesWith(ZRegister.DE)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(DE))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.DE)) ~~> { code =>
ZLine.ld8(ZRegister.D, ZRegister.H) ::
ZLine.ld8(ZRegister.E, ZRegister.L) ::
@ -427,7 +427,7 @@ object AlwaysGoodI80Optimizations {
},
//21
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.HL) & DoesntMatterWhatItDoesWith(ZRegister.BC)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(BC))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.BC)) ~~> { code =>
ZLine.ld8(ZRegister.B, ZRegister.H) ::
ZLine.ld8(ZRegister.C, ZRegister.L) ::
@ -435,7 +435,7 @@ object AlwaysGoodI80Optimizations {
},
//22
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.DE) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(HL))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.HL)) ~~> { code =>
ZLine.ld8(ZRegister.H, ZRegister.D) ::
ZLine.ld8(ZRegister.L, ZRegister.E) ::
@ -443,7 +443,7 @@ object AlwaysGoodI80Optimizations {
},
//23
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.BC) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(HL))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.HL)) ~~> { code =>
ZLine.ld8(ZRegister.H, ZRegister.B) ::
ZLine.ld8(ZRegister.L, ZRegister.C) ::
@ -451,7 +451,7 @@ object AlwaysGoodI80Optimizations {
},
//24
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.BC) & DoesntMatterWhatItDoesWith(ZRegister.DE)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(DE))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.DE)) ~~> { code =>
ZLine.ld8(ZRegister.D, ZRegister.B) ::
ZLine.ld8(ZRegister.E, ZRegister.C) ::
@ -459,7 +459,7 @@ object AlwaysGoodI80Optimizations {
},
//25
(Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.DE) & DoesntMatterWhatItDoesWith(ZRegister.BC)) ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
(Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(BC))).* ~
(Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.BC)) ~~> { code =>
ZLine.ld8(ZRegister.B, ZRegister.D) ::
ZLine.ld8(ZRegister.C, ZRegister.E) ::

View File

@ -99,8 +99,10 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
}
// generic warnings:
stmt match {
case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy", params)) =>
case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy" | "strzpaste", params)) =>
for (param <- params) checkIfNullTerminated(ctx, stmt, param)
case ExpressionStatement(expr@FunctionCallExpression("pstrlen" | "putpstr" | "pstrcmp" | "pstrcopy" | "pstrpaste", params)) =>
for (param <- params) checkIfLengthPrefixed(ctx, stmt, param)
case ExpressionStatement(expr@FunctionCallExpression(f, List(VariableExpression(v)))) if hiddenEffectFreeFunctions(f)=>
val volatile = ctx.env.maybeGet[ThingInMemory](v).fold(false)(_.isVolatile)
@ -276,14 +278,34 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
val TERMINATOR = ctx.options.platform.defaultCodec.stringTerminator.head
param match {
case TextLiteralExpression(ch) =>
ch.last match {
case LiteralExpression(TERMINATOR, _) => //ok
ch.lastOption match {
case Some(LiteralExpression(TERMINATOR, _)) => //ok
case _ => ctx.log.warn("Passing a non-null-terminated string to a function that expects a null-terminated string.", stmt.position)
}
case _ =>
}
}
private def checkIfLengthPrefixed(ctx: CompilationContext, stmt: ExecutableStatement, param: Expression): Unit = {
if (!ctx.options.flag(CompilationFlag.BuggyCodeWarning)) return
val TERMINATOR = ctx.options.platform.defaultCodec.stringTerminator.head
param match {
case TextLiteralExpression(ch) =>
if (ch.headOption match {
case Some(LiteralExpression(length, _)) if length == ch.size - 1 => false
case Some(LiteralExpression(length, _)) if length == ch.size + 2 =>
ch.lastOption match {
case Some(LiteralExpression(TERMINATOR, _)) => false
case _ => true
}
case _ => true
}) {
ctx.log.warn("Passing a non-length-prefixed string to a function that expects a length-prefixed string.", stmt.position)
}
case _ =>
}
}
def search(expr: Expression, cv: VV): VV = {
expr match {
case FunctionCallExpression(op, List(VariableExpression(v), arg)) if op.endsWith("=") && op != "<=" && op != ">=" =>