until-loop condition now also simplified to avoid stack-eval

This commit is contained in:
Irmen de Jong 2021-11-14 22:51:02 +01:00
parent 53e1729e2f
commit c80df4140b
3 changed files with 53 additions and 10 deletions

View File

@ -235,6 +235,10 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
)
private fun simplifyConditionalExpression(expr: BinaryExpression): CondExprSimplificationResult {
// TODO: somehow figure out if the expr will result in stack-evaluation STILL after being split off,
// in that case: do *not* split it off but just keep it as it is (otherwise code size increases)
var leftAssignment: Assignment? = null
var leftOperandReplacement: Expression? = null
var rightAssignment: Assignment? = null
@ -302,9 +306,21 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
(binExpr.right as? NumericLiteralValue)?.number!=0)
throw FatalAstException("0==X should have been swapped to if X==0")
// TODO simplify conditional expression like in if-statement
// simplify the conditional expression, introduce simple assignments if required.
// NOTE: sometimes this increases code size because additional stores/loads are generated for the
// intermediate variables. We assume these are optimized away from the resulting assembly code later.
val simplify = simplifyConditionalExpression(binExpr)
val modifications = mutableListOf<IAstModification>()
if(simplify.rightVarAssignment!=null) {
modifications += IAstModification.ReplaceNode(binExpr.right, simplify.rightOperandReplacement!!, binExpr)
modifications += IAstModification.InsertLast(simplify.rightVarAssignment, untilLoop.body)
}
if(simplify.leftVarAssignment!=null) {
modifications += IAstModification.ReplaceNode(binExpr.left, simplify.leftOperandReplacement!!, binExpr)
modifications += IAstModification.InsertLast(simplify.leftVarAssignment, untilLoop.body)
}
return noModifications
return modifications
}
@Suppress("DuplicatedCode")
@ -327,8 +343,13 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
(binExpr.right as? NumericLiteralValue)?.number!=0)
throw FatalAstException("0==X should have been swapped to if X==0")
// TODO simplify conditional expression like in if-statement
// TODO simplify the conditional expression, introduce simple assignments if required.
// NOTE: sometimes this increases code size because additional stores/loads are generated for the
// intermediate variables. We assume these are optimized away from the resulting assembly code later.
// NOTE: this is nasty for a while-statement as the condition occurs at the top of the loop
// so the expression needs to be evaluated also before the loop is entered...
// but I don't want to duplicate the expression.
// val simplify = simplifyConditionalExpression(binExpr)
return noModifications
}

View File

@ -3,7 +3,7 @@ TODO
For next compiler release (7.3)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- add expression simplification to while and until loops as well.
...
Blocked by an official Commander-x16 v39 release
@ -14,6 +14,11 @@ Blocked by an official Commander-x16 v39 release
Future
^^^^^^
- simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation
- remove special code generation for while and util expression
by rewriting while and until expressions into if+jump (consider them syntactic sugar)
but the result should not produce larger code ofcourse!
- while-expression should now also get the simplifyConditionalExpression() treatment
- fix the asm-labels problem (github issue #62)
- find a way to optimize asm-subroutine param passing where it now sometimes uses the evalstack?
- document the various compiler command line options in more detail. See "Compiling program code" in the docs

View File

@ -1,16 +1,33 @@
%import textio
main {
sub start() {
byte xx=1
ubyte xx=10
if xx+2 {
xx++
txt.print("if\n")
if xx-2 {
txt.print("in if\n")
}
sub test() -> ubyte {
txt.print("\nwhile\n")
xx=6
while xx-2 {
xx--
txt.print_ub(xx)
txt.spc()
}
txt.print("\nuntil\n")
xx=2
do {
xx++
return xx
txt.print_ub(xx)
txt.spc()
} until xx+2==10
txt.print("\ndone")
repeat {
}
}