mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
optimize: flip if true/else blocks if the else block only contains a jump (inverting the condition)
This commit is contained in:
parent
01c2112881
commit
58400f53bc
@ -110,6 +110,22 @@ class StatementOptimizer(private val program: Program,
|
||||
IAstModification.InsertAfter(ifElse, elsePart, parent as IStatementContainer)
|
||||
)
|
||||
}
|
||||
|
||||
// switch if/else around if the else is just a jump or branch
|
||||
if(ifElse.elsepart.isNotEmpty() && ifElse.elsepart.statements.size==1) {
|
||||
val jump = ifElse.elsepart.statements[0]
|
||||
if(jump is Jump) {
|
||||
val newTruePart = AnonymousScope(mutableListOf(jump), ifElse.elsepart.position)
|
||||
val newElsePart = AnonymousScope(ifElse.truepart.statements, ifElse.truepart.position)
|
||||
val invertedCondition = PrefixExpression("not", ifElse.condition, ifElse.condition.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(ifElse.elsepart, newElsePart, ifElse),
|
||||
IAstModification.ReplaceNode(ifElse.truepart, newTruePart, ifElse),
|
||||
IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
@ -460,7 +476,7 @@ class StatementOptimizer(private val program: Program,
|
||||
if(whenStmt.condition.inferType(program).isBool) {
|
||||
if(whenStmt.choices.all { it.values?.size==1 }) {
|
||||
if (whenStmt.choices.all { it.values!!.single().constValue(program)!!.number in arrayOf(0.0, 1.0) }) {
|
||||
// it's a when statement on booleans that can just be replaced by an if or if..else.
|
||||
// it's a when statement on booleans that can just be replaced by an if or if-else.
|
||||
if (whenStmt.choices.size == 1) {
|
||||
return if(whenStmt.choices[0].values!![0].constValue(program)!!.number==1.0) {
|
||||
replaceWithIf(whenStmt.condition, whenStmt.choices[0].statements, null)
|
||||
|
@ -112,9 +112,11 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
|
||||
args.errors.report()
|
||||
|
||||
val intermediateAst = IntermediateAstMaker(program, args.errors).transform()
|
||||
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printProgram(program)
|
||||
|
||||
val intermediateAst = IntermediateAstMaker(program, args.errors).transform()
|
||||
|
||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printAst(intermediateAst, true, ::println)
|
||||
|
||||
|
@ -95,6 +95,16 @@ internal class BoolRemover(val program: Program) : AstWalker() {
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(expr.operator=="not") {
|
||||
val exprDt = expr.expression.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||
val nonBoolDt = if(exprDt==DataType.BOOL) DataType.UBYTE else exprDt
|
||||
val equalZero = BinaryExpression(expr.expression, "==", NumericLiteral(nonBoolDt, 0.0, expr.expression.position), expr.expression.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, equalZero, parent))
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
||||
internal fun wrapWithBooleanCastIfNeeded(expr: Expression, program: Program): Expression? {
|
||||
|
@ -2,17 +2,15 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- optimize: flip if true/else blocks if the else block only contains a jump (invert condition!)
|
||||
- IR (expericodegen): fix code for calling routines that return a boolean in a status register such as Carry flag, it has to store the flag value somewhere
|
||||
|
||||
- merge branch optimize-st for some optimizations regardign SymbolTable use
|
||||
- merge branch optimize-st for some optimizations regarding SymbolTable use
|
||||
|
||||
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
||||
modify programs (shell, paint) that now use callfar
|
||||
|
||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||
|
||||
- IR (expericodegen): fix code for calling routines that return a boolean in a status register such as Carry flag, it has to store the flag value somewhere
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -4,86 +4,23 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; expected output: 0000
|
||||
cx16.r0L = test_c_clear()
|
||||
cx16.r1L = test_z_clear()
|
||||
cx16.r2L = test_n_clear()
|
||||
cx16.r3L = test_v_clear()
|
||||
txt.print_ub(cx16.r0L)
|
||||
txt.print_ub(cx16.r1L)
|
||||
txt.print_ub(cx16.r2L)
|
||||
txt.print_ub(cx16.r3L)
|
||||
txt.nl()
|
||||
; expected output: 1111
|
||||
cx16.r0L = test_c_set()
|
||||
cx16.r1L = test_z_set()
|
||||
cx16.r2L = test_n_set()
|
||||
cx16.r3L = test_v_set()
|
||||
txt.print_ub(cx16.r0L)
|
||||
txt.print_ub(cx16.r1L)
|
||||
txt.print_ub(cx16.r2L)
|
||||
txt.print_ub(cx16.r3L)
|
||||
txt.nl()
|
||||
|
||||
; exptected output: no2, no3, no5, yes6, no7, yes8
|
||||
if not test_c_clear()
|
||||
goto skip1
|
||||
if test_c_set()
|
||||
txt.print("yes1\n")
|
||||
else
|
||||
txt.print("no1\n")
|
||||
goto skip1
|
||||
|
||||
txt.print("no1\n")
|
||||
|
||||
skip1:
|
||||
if test_c_clear()
|
||||
goto skip2
|
||||
txt.print("yes2\n")
|
||||
else
|
||||
txt.print("no2\n")
|
||||
goto skip2
|
||||
|
||||
txt.print("no1\n")
|
||||
|
||||
skip2:
|
||||
|
||||
if not test_c_set()
|
||||
goto skip3
|
||||
else
|
||||
txt.print("no3\n")
|
||||
|
||||
skip3:
|
||||
if test_c_set()
|
||||
goto skip4
|
||||
else
|
||||
txt.print("no4\n")
|
||||
|
||||
skip4:
|
||||
|
||||
if test_c_clear() {
|
||||
txt.print("yes5\n")
|
||||
goto skip5
|
||||
}
|
||||
txt.print("no5\n")
|
||||
|
||||
skip5:
|
||||
if not test_c_clear() {
|
||||
txt.print("yes6\n")
|
||||
goto skip6
|
||||
}
|
||||
txt.print("no6\n")
|
||||
|
||||
skip6:
|
||||
if test_c_clear()
|
||||
txt.print("yes7\n")
|
||||
else
|
||||
txt.print("no7\n")
|
||||
|
||||
if not test_c_clear()
|
||||
txt.print("yes8\n")
|
||||
else
|
||||
txt.print("no8\n")
|
||||
|
||||
|
||||
while test_c_clear() {
|
||||
cx16.r0++
|
||||
}
|
||||
|
||||
do {
|
||||
cx16.r0++
|
||||
} until test_c_set()
|
||||
txt.print("done\n")
|
||||
}
|
||||
|
||||
asmsub test_c_clear() -> bool @Pc {
|
||||
|
Loading…
Reference in New Issue
Block a user