1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-11-17 16:05:31 +00:00

Fix several things:

– statement preprocessor
– unused label removal
– >>>> operator on 6502
– constant byte comparison on 6502
This commit is contained in:
Karol Stasiak 2018-07-28 00:02:57 +02:00
parent 847a7255c6
commit 514e819ddf
4 changed files with 65 additions and 27 deletions

View File

@ -685,19 +685,19 @@ object AlwaysGoodOptimizations {
needsFlowInfo = FlowInfoRequirement.NoRequirement, needsFlowInfo = FlowInfoRequirement.NoRequirement,
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~ (Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~ (Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil), (HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
(Elidable & HasOpcode(BRA) & MatchParameter(0)) ~ (Elidable & HasOpcode(BRA) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~ (Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil), (HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~ (Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~ (Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~ ((HasOpcode(LABEL) & MatchParameter(0)) ~
(HasOpcode(LABEL) | NoopDiscardsFlags).* ~ (HasOpcode(LABEL) | NoopDiscardsFlags).* ~
HasOpcode(RTS) ~~> (code => AssemblyLine.implied(RTS) :: code.tail), HasOpcode(RTS)).capture(1) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1) ++ code.tail),
(Elidable & ShortBranching & MatchParameter(0)) ~ (Elidable & ShortBranching & MatchParameter(0)) ~
(NoopDiscardsFlags.* ~ (NoopDiscardsFlags.* ~
(Elidable & HasOpcode(RTS))).capture(1) ~ (Elidable & HasOpcode(RTS)) ~
(HasOpcode(LABEL) & MatchParameter(0)) ~ (HasOpcode(LABEL) & MatchParameter(0))).capture(1) ~
NoopDiscardsFlags.* ~ NoopDiscardsFlags.* ~
(Elidable & HasOpcode(RTS)) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1)), (Elidable & HasOpcode(RTS)) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1)),
) )

View File

@ -19,7 +19,9 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
protected val localPrefix = ctx.function.name + "$" protected val localPrefix = ctx.function.name + "$"
protected val usedIdentifiers = if (optimize) statements.flatMap(_.getAllExpressions).flatMap(_.getAllIdentifiers) else Set() protected val usedIdentifiers = if (optimize) statements.flatMap(_.getAllExpressions).flatMap(_.getAllIdentifiers) else Set()
protected val trackableVars: Set[String] = if (optimize) { protected val trackableVars: Set[String] = if (optimize) {
env.getAllLocalVariables.map(_.name.stripPrefix(localPrefix)) env.getAllLocalVariables
.filterNot(_.typ.isSigned) // sadly, tracking loses signedness
.map(_.name.stripPrefix(localPrefix))
.filterNot(_.contains(".")) .filterNot(_.contains("."))
.filterNot(_.contains("$")) .filterNot(_.contains("$"))
.filterNot { vname => .filterNot { vname =>
@ -61,22 +63,25 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
stmt match { stmt match {
case Assignment(ve@VariableExpression(v), arg) if trackableVars(v) => case Assignment(ve@VariableExpression(v), arg) if trackableVars(v) =>
cv = search(arg, cv) cv = search(arg, cv)
Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> (env.eval(arg, currentVarValues) match { Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> (env.eval(arg, currentVarValues) match {
case Some(c) => cv + (v -> c) case Some(c) => cv + (v -> c)
case None => cv - v case None => cv - v
}) })
case Assignment(ve, arg) =>
cv = search(arg, cv)
cv = search(ve, cv)
Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> cv
case ExpressionStatement(expr@FunctionCallExpression("+=", List(VariableExpression(v), arg))) case ExpressionStatement(expr@FunctionCallExpression("+=", List(VariableExpression(v), arg)))
if currentVarValues.contains(v) => if currentVarValues.contains(v) =>
cv = search(arg, cv) cv = search(arg, cv)
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> (env.eval(expr, currentVarValues) match { ExpressionStatement(optimizeExpr(expr, cv - v)).pos(pos) -> (env.eval(expr, currentVarValues) match {
case Some(c) => if (cv.contains(v)) cv + (v -> (cv(v) + c)) else cv case Some(c) => if (cv.contains(v)) cv + (v -> (cv(v) + c)) else cv
case None => cv - v case None => cv - v
}) })
case ExpressionStatement(expr@FunctionCallExpression(op, List(VariableExpression(v), arg))) case ExpressionStatement(expr@FunctionCallExpression(op, List(VariableExpression(v), arg)))
if op.endsWith("=") && op != ">=" && op != "<=" && op != ":=" => if op.endsWith("=") && op != ">=" && op != "<=" && op != ":=" =>
cv = search(arg, cv) cv = search(arg, cv)
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> (cv - v) ExpressionStatement(optimizeExpr(expr, cv - v)).pos(pos) -> (cv - v)
case ExpressionStatement(expr) => case ExpressionStatement(expr) =>
cv = search(expr, cv) cv = search(expr, cv)
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> cv ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> cv
@ -88,7 +93,7 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
IfStatement(c, t, e).pos(pos) -> commonVV(vt, ve) IfStatement(c, t, e).pos(pos) -> commonVV(vt, ve)
case WhileStatement(cond, body, inc, labels) => case WhileStatement(cond, body, inc, labels) =>
cv = search(cond, cv) cv = search(cond, cv)
val c = optimizeExpr(cond, cv) val c = optimizeExpr(cond, Map())
val (b, _) = optimizeStmts(body, Map()) val (b, _) = optimizeStmts(body, Map())
val (i, _) = optimizeStmts(inc, Map()) val (i, _) = optimizeStmts(inc, Map())
WhileStatement(c, b, i, labels).pos(pos) -> Map() WhileStatement(c, b, i, labels).pos(pos) -> Map()
@ -161,13 +166,18 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
ErrorReporting.debug(s"Using node flow to replace $v with $constant", pos) ErrorReporting.debug(s"Using node flow to replace $v with $constant", pos)
GeneratedConstantExpression(constant, getExpressionType(ctx, expr)).pos(pos) GeneratedConstantExpression(constant, getExpressionType(ctx, expr)).pos(pos)
case FunctionCallExpression(t1, List(FunctionCallExpression(t2, List(arg)))) case FunctionCallExpression(t1, List(FunctionCallExpression(t2, List(arg))))
if optimize && pointlessDoubleCast(t1, t2, expr) => if optimize && pointlessDoubleCast(t1, t2, arg) =>
ErrorReporting.debug(s"Pointless double cast $t1($t2(...))", pos) ErrorReporting.debug(s"Pointless double cast $t1($t2(...))", pos)
optimizeExpr(FunctionCallExpression(t1, List(arg)), currentVarValues) optimizeExpr(FunctionCallExpression(t1, List(arg)), currentVarValues)
case FunctionCallExpression(t1, List(arg)) case FunctionCallExpression(t1, List(arg))
if optimize && pointlessCast(t1, expr) => if optimize && pointlessCast(t1, arg) =>
ErrorReporting.debug(s"Pointless cast $t1(...)", pos) ErrorReporting.debug(s"Pointless cast $t1(...)", pos)
optimizeExpr(arg, currentVarValues) optimizeExpr(arg, currentVarValues)
case FunctionCallExpression("nonet", args) =>
// Eliminating variables may eliminate carry
FunctionCallExpression("nonet", args.map(arg => optimizeExpr(arg, Map()))).pos(pos)
case FunctionCallExpression(name, args) =>
FunctionCallExpression(name, args.map(arg => optimizeExpr(arg, currentVarValues))).pos(pos)
case _ => expr // TODO case _ => expr // TODO
} }
} }

View File

@ -214,17 +214,21 @@ object BuiltIns {
} }
} }
def compileNonetOps(ctx: CompilationContext, lhs: LhsExpression, rhs: Expression): List[AssemblyLine] = { def compileNonetOps(ctx: CompilationContext, lhs: Expression, rhs: Expression): List[AssemblyLine] = {
val env = ctx.env val env = ctx.env
val b = env.get[Type]("byte") val b = env.get[Type]("byte")
val (ldaHi, ldaLo) = lhs match { val (ldaHi, ldaLo) = env.eval(lhs) match {
case v: VariableExpression => case Some(c) =>
val variable = env.get[Variable](v.name) List(AssemblyLine.immediate(LDA, c.hiByte)) -> List(AssemblyLine.immediate(LDA, c.loByte))
AssemblyLine.variable(ctx, LDA, variable, 1) -> AssemblyLine.variable(ctx, LDA, variable, 0) case _ => lhs match {
case SeparateBytesExpression(h: VariableExpression, l: VariableExpression) => case v: VariableExpression =>
AssemblyLine.variable(ctx, LDA, env.get[Variable](h.name), 0) -> AssemblyLine.variable(ctx, LDA, env.get[Variable](l.name), 0) val variable = env.get[Variable](v.name)
case _ => AssemblyLine.variable(ctx, LDA, variable, 1) -> AssemblyLine.variable(ctx, LDA, variable, 0)
??? case SeparateBytesExpression(h: VariableExpression, l: VariableExpression) =>
AssemblyLine.variable(ctx, LDA, env.get[Variable](h.name), 0) -> AssemblyLine.variable(ctx, LDA, env.get[Variable](l.name), 0)
case _ =>
???
}
} }
env.eval(rhs) match { env.eval(rhs) match {
case Some(NumericConstant(0, _)) => case Some(NumericConstant(0, _)) =>
@ -394,6 +398,33 @@ object BuiltIns {
case BranchIfTrue(l) => compType -> l case BranchIfTrue(l) => compType -> l
case BranchIfFalse(l) => ComparisonType.negate(compType) -> l case BranchIfFalse(l) => ComparisonType.negate(compType) -> l
} }
(env.eval(lhs), env.eval(rhs)) match {
case (Some(NumericConstant(lc, _)), Some(NumericConstant(rc, _))) =>
return if (effectiveComparisonType match {
// TODO: those masks are probably wrong
case ComparisonType.Equal =>
(lc & 0xff) == (rc & 0xff)
case ComparisonType.NotEqual =>
(lc & 0xff) != (rc & 0xff)
case ComparisonType.LessOrEqualUnsigned =>
(lc & 0xff) <= (rc & 0xff)
case ComparisonType.GreaterOrEqualUnsigned =>
(lc & 0xff) >= (rc & 0xff)
case ComparisonType.GreaterUnsigned =>
(lc & 0xff) > (rc & 0xff)
case ComparisonType.LessUnsigned =>
(lc & 0xff) < (rc & 0xff)
case ComparisonType.LessOrEqualSigned =>
lc.toByte <= rc.toByte
case ComparisonType.GreaterOrEqualSigned =>
lc.toByte >= rc.toByte
case ComparisonType.GreaterSigned =>
lc.toByte > rc.toByte
case ComparisonType.LessSigned =>
lc.toByte < rc.toByte
}) List(AssemblyLine.absolute(JMP, Label(label))) else Nil
case _ =>
}
val branchingCompiled = effectiveComparisonType match { val branchingCompiled = effectiveComparisonType match {
case ComparisonType.Equal => case ComparisonType.Equal =>
List(AssemblyLine.relative(BEQ, Label(label))) List(AssemblyLine.relative(BEQ, Label(label)))

View File

@ -777,11 +777,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
} }
case ">>>>" => case ">>>>" =>
val (l, r, 2) = assertArithmeticBinary(ctx, params) val (l, r, 2) = assertArithmeticBinary(ctx, params)
l match { zeroExtend = true
case v: LhsExpression => BuiltIns.compileNonetOps(ctx, l, r)
zeroExtend = true
BuiltIns.compileNonetOps(ctx, v, r)
}
case "<<" => case "<<" =>
val (l, r, size) = assertArithmeticBinary(ctx, params) val (l, r, size) = assertArithmeticBinary(ctx, params)
size match { size match {