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:
parent
847a7255c6
commit
514e819ddf
@ -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)),
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)))
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user