optimize dangling else

This commit is contained in:
Irmen de Jong 2023-06-18 13:34:56 +02:00
parent 0aac9350d5
commit a587482edf
5 changed files with 51 additions and 69 deletions

View File

@ -43,9 +43,9 @@ fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget)
fun Program.optimizeStatements(errors: IErrorReporter,
functions: IBuiltinFunctions,
compTarget: ICompilationTarget
options: CompilationOptions
): Int {
val optimizer = StatementOptimizer(this, errors, functions, compTarget)
val optimizer = StatementOptimizer(this, errors, functions, options)
optimizer.visit(this)
val optimizationCount = optimizer.applyModifications()

View File

@ -13,7 +13,7 @@ import kotlin.math.floor
class StatementOptimizer(private val program: Program,
private val errors: IErrorReporter,
private val functions: IBuiltinFunctions,
private val compTarget: ICompilationTarget
private val options: CompilationOptions
) : AstWalker() {
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
@ -39,7 +39,7 @@ class StatementOptimizer(private val program: Program,
if(string!=null) {
val pos = functionCallStatement.position
if (string.value.length == 1) {
val firstCharEncoded = compTarget.encodeString(string.value, string.encoding)[0]
val firstCharEncoded = options.compTarget.encodeString(string.value, string.encoding)[0]
val chrout = FunctionCallStatement(
IdentifierReference(listOf("txt", "chrout"), pos),
mutableListOf(NumericLiteral(DataType.UBYTE, firstCharEncoded.toDouble(), pos)),
@ -51,7 +51,7 @@ class StatementOptimizer(private val program: Program,
IAstModification.Remove(stringDecl, stringDecl.parent as IStatementContainer)
)
} else if (string.value.length == 2) {
val firstTwoCharsEncoded = compTarget.encodeString(string.value.take(2), string.encoding)
val firstTwoCharsEncoded = options.compTarget.encodeString(string.value.take(2), string.encoding)
val chrout1 = FunctionCallStatement(
IdentifierReference(listOf("txt", "chrout"), pos),
mutableListOf(NumericLiteral(DataType.UBYTE, firstTwoCharsEncoded[0].toDouble(), pos)),
@ -108,6 +108,16 @@ class StatementOptimizer(private val program: Program,
}
}
// remove obvious dangling elses (else after a return)
if(ifElse.elsepart.isNotEmpty() && ifElse.truepart.statements.singleOrNull() is Return) {
val elsePart = AnonymousScope(ifElse.elsepart.statements, ifElse.elsepart.position)
if(options.slowCodegenWarnings)
errors.warn("else can be omitted", ifElse.elsepart.position)
return listOf(
IAstModification.ReplaceNode(ifElse.elsepart, AnonymousScope(mutableListOf(), ifElse.elsepart.position), ifElse),
IAstModification.InsertAfter(ifElse, elsePart, parent as IStatementContainer)
)
}
return noModifications
}
@ -141,7 +151,7 @@ class StatementOptimizer(private val program: Program,
val size = sv.value.length
if(size==1) {
// loop over string of length 1 -> just assign the single character
val character = compTarget.encodeString(sv.value, sv.encoding)[0]
val character = options.compTarget.encodeString(sv.value, sv.encoding)[0]
val byte = NumericLiteral(DataType.UBYTE, character.toDouble(), iterable.position)
val scope = AnonymousScope(mutableListOf(), forLoop.position)
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, AssignmentOrigin.OPTIMIZER, forLoop.position))
@ -326,7 +336,7 @@ class StatementOptimizer(private val program: Program,
if (rightCv == 0.0) {
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && compTarget.name!=VMTarget.NAME) {
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
val incs = AnonymousScope(mutableListOf(), assignment.position)
repeat(rightCv.toInt()) {
@ -340,7 +350,7 @@ class StatementOptimizer(private val program: Program,
if (rightCv == 0.0) {
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && compTarget.name!=VMTarget.NAME) {
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
val decs = AnonymousScope(mutableListOf(), assignment.position)
repeat(rightCv.toInt()) {

View File

@ -371,7 +371,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
// keep optimizing expressions and statements until no more steps remain
val optsDone1 = program.simplifyExpressions(errors, compTarget)
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
val optsDone3 = program.optimizeStatements(errors, functions, compTarget)
val optsDone3 = program.optimizeStatements(errors, functions, compilerOptions)
val optsDone4 = program.inlineSubroutines()
program.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
errors.report()

View File

@ -1,8 +1,6 @@
TODO
====
- optimize a "dangling else"
...

View File

@ -1,67 +1,41 @@
%import math
%import textio
%zeropage basicsafe
main {
const ubyte WIDTH=255
const ubyte HEIGHT=240
main {
sub start() {
sys.gfx_enable(0) ; enable lo res screen
;; gfx2.screen_mode(4)
repeat {
txt.print_ub(danglingelse(32))
txt.spc()
txt.print_ub(danglingelse(99))
txt.spc()
txt.print_ub(danglingelse(1))
txt.spc()
txt.print_ub(danglingelse(100))
txt.nl()
txt.print_ub(danglingelse2(32))
txt.spc()
txt.print_ub(danglingelse2(99))
txt.spc()
txt.print_ub(danglingelse2(1))
txt.spc()
txt.print_ub(danglingelse2(100))
txt.nl()
}
ubyte xx
ubyte yy
sub danglingelse(ubyte bb) -> ubyte {
if bb==32
return 32
else if bb==99
return 99
else
return 0
}
for yy in 0 to HEIGHT-1 {
for xx in 0 to WIDTH-1 {
ubyte value = math.direction(WIDTH/2, HEIGHT/2, xx, yy)
;; gfx2.plot(xx,yy,value)
sys.gfx_plot(xx, yy, value*10)
}
}
}
sub danglingelse2(ubyte bb) -> ubyte {
if bb==32
return 32
if bb==99
return 99
return 0
}
}
;main {
;
; sub start() {
;
; const ubyte HEIGHT = txt.DEFAULT_HEIGHT
; const ubyte WIDTH = txt.DEFAULT_WIDTH
; const ubyte HALFWIDTH = txt.DEFAULT_WIDTH/2
; const ubyte HALFHEIGHT = txt.DEFAULT_HEIGHT/2
;
; ubyte @zp value
; ubyte xx
; ubyte yy
;; for yy in 0 to HEIGHT-1 {
;; for xx in 0 to WIDTH-1 {
;; value = math.atan(HALFWIDTH, HALFHEIGHT, xx, yy)
;; txt.setchr(xx,yy,value)
;; }
;; }
;;
;; byte sx
;; byte sy
;; for sy in -HEIGHT/2 to HEIGHT/2 {
;; for sx in -WIDTH/2 to WIDTH/2 {
;; value = math.direction_sc(0, 0, sx, sy)
;; txt.setchr(sx+WIDTH/2 as ubyte,sy+HEIGHT/2 as ubyte,value)
;; }
;; }
;
; for yy in 0 to HEIGHT-1 {
; for xx in 0 to WIDTH-1 {
; value = math.direction(HALFWIDTH, HALFHEIGHT, xx, yy)
; txt.setchr(xx,yy,value)
; }
; }
;
; goto start
; }
;}