mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +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)
|
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
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +476,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if(whenStmt.condition.inferType(program).isBool) {
|
if(whenStmt.condition.inferType(program).isBool) {
|
||||||
if(whenStmt.choices.all { it.values?.size==1 }) {
|
if(whenStmt.choices.all { it.values?.size==1 }) {
|
||||||
if (whenStmt.choices.all { it.values!!.single().constValue(program)!!.number in arrayOf(0.0, 1.0) }) {
|
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) {
|
if (whenStmt.choices.size == 1) {
|
||||||
return if(whenStmt.choices[0].values!![0].constValue(program)!!.number==1.0) {
|
return if(whenStmt.choices[0].values!![0].constValue(program)!!.number==1.0) {
|
||||||
replaceWithIf(whenStmt.condition, whenStmt.choices[0].statements, null)
|
replaceWithIf(whenStmt.condition, whenStmt.choices[0].statements, null)
|
||||||
|
@ -112,9 +112,11 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
|||||||
program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
|
program.processAstBeforeAsmGeneration(compilationOptions, args.errors)
|
||||||
args.errors.report()
|
args.errors.report()
|
||||||
|
|
||||||
val intermediateAst = IntermediateAstMaker(program, args.errors).transform()
|
|
||||||
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
||||||
// printProgram(program)
|
// printProgram(program)
|
||||||
|
|
||||||
|
val intermediateAst = IntermediateAstMaker(program, args.errors).transform()
|
||||||
|
|
||||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||||
// printAst(intermediateAst, true, ::println)
|
// printAst(intermediateAst, true, ::println)
|
||||||
|
|
||||||
|
@ -95,6 +95,16 @@ internal class BoolRemover(val program: Program) : AstWalker() {
|
|||||||
}
|
}
|
||||||
return noModifications
|
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? {
|
internal fun wrapWithBooleanCastIfNeeded(expr: Expression, program: Program): Expression? {
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
TODO
|
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())
|
- [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
|
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 ....
|
- [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 {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
; expected output: 0000
|
if test_c_set()
|
||||||
cx16.r0L = test_c_clear()
|
txt.print("yes1\n")
|
||||||
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
|
|
||||||
else
|
else
|
||||||
txt.print("no1\n")
|
goto skip1
|
||||||
|
|
||||||
|
txt.print("no1\n")
|
||||||
|
|
||||||
skip1:
|
skip1:
|
||||||
if test_c_clear()
|
if test_c_clear()
|
||||||
goto skip2
|
txt.print("yes2\n")
|
||||||
else
|
else
|
||||||
txt.print("no2\n")
|
goto skip2
|
||||||
|
|
||||||
|
txt.print("no1\n")
|
||||||
|
|
||||||
skip2:
|
skip2:
|
||||||
|
txt.print("done\n")
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub test_c_clear() -> bool @Pc {
|
asmsub test_c_clear() -> bool @Pc {
|
||||||
|
Loading…
Reference in New Issue
Block a user