1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +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,
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
(Elidable & HasOpcode(BRA) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (code => List(code.last)),
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~
((HasOpcode(LABEL) & MatchParameter(0)) ~
(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)) ~
(NoopDiscardsFlags.* ~
(Elidable & HasOpcode(RTS))).capture(1) ~
(HasOpcode(LABEL) & MatchParameter(0)) ~
(Elidable & HasOpcode(RTS)) ~
(HasOpcode(LABEL) & MatchParameter(0))).capture(1) ~
NoopDiscardsFlags.* ~
(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 usedIdentifiers = if (optimize) statements.flatMap(_.getAllExpressions).flatMap(_.getAllIdentifiers) else Set()
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 { vname =>
@ -61,22 +63,25 @@ abstract class AbstractStatementPreprocessor(ctx: CompilationContext, statements
stmt match {
case Assignment(ve@VariableExpression(v), arg) if trackableVars(v) =>
cv = search(arg, cv)
Assignment(ve, optimizeExpr(arg, cv)).pos(pos) -> (env.eval(arg, currentVarValues) match {
case Some(c) => cv + (v -> c)
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)))
if currentVarValues.contains(v) =>
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 None => cv - v
})
case ExpressionStatement(expr@FunctionCallExpression(op, List(VariableExpression(v), arg)))
if op.endsWith("=") && op != ">=" && op != "<=" && op != ":=" =>
cv = search(arg, cv)
ExpressionStatement(optimizeExpr(expr, cv)).pos(pos) -> (cv - v)
ExpressionStatement(optimizeExpr(expr, cv - v)).pos(pos) -> (cv - v)
case ExpressionStatement(expr) =>
cv = search(expr, 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)
case WhileStatement(cond, body, inc, labels) =>
cv = search(cond, cv)
val c = optimizeExpr(cond, cv)
val c = optimizeExpr(cond, Map())
val (b, _) = optimizeStmts(body, Map())
val (i, _) = optimizeStmts(inc, 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)
GeneratedConstantExpression(constant, getExpressionType(ctx, expr)).pos(pos)
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)
optimizeExpr(FunctionCallExpression(t1, List(arg)), currentVarValues)
case FunctionCallExpression(t1, List(arg))
if optimize && pointlessCast(t1, expr) =>
if optimize && pointlessCast(t1, arg) =>
ErrorReporting.debug(s"Pointless cast $t1(...)", pos)
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
}
}

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 b = env.get[Type]("byte")
val (ldaHi, ldaLo) = lhs match {
case v: VariableExpression =>
val variable = env.get[Variable](v.name)
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 _ =>
???
val (ldaHi, ldaLo) = env.eval(lhs) match {
case Some(c) =>
List(AssemblyLine.immediate(LDA, c.hiByte)) -> List(AssemblyLine.immediate(LDA, c.loByte))
case _ => lhs match {
case v: VariableExpression =>
val variable = env.get[Variable](v.name)
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 {
case Some(NumericConstant(0, _)) =>
@ -394,6 +398,33 @@ object BuiltIns {
case BranchIfTrue(l) => 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 {
case ComparisonType.Equal =>
List(AssemblyLine.relative(BEQ, Label(label)))

View File

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