From 8e927e0b73bc97373f1d39b72b3f80ae1843bbd7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 31 Dec 2020 22:13:24 +0100 Subject: [PATCH] nontrivial return value evaluation now via intermediary variable to try to avoid slow stack based evaluation --- compiler/res/prog8lib/prog8_lib.p8 | 2 + .../codegen/assignment/AssignmentAsmGen.kt | 6 +- .../src/prog8/optimizer/StatementOptimizer.kt | 38 ++++++++ examples/cx16/testgfx2.p8 | 10 +- examples/test.p8 | 97 ++++--------------- 5 files changed, 69 insertions(+), 84 deletions(-) diff --git a/compiler/res/prog8lib/prog8_lib.p8 b/compiler/res/prog8lib/prog8_lib.p8 index 430bac265..22eff4287 100644 --- a/compiler/res/prog8lib/prog8_lib.p8 +++ b/compiler/res/prog8lib/prog8_lib.p8 @@ -8,6 +8,8 @@ prog8_lib { %asminclude "library:prog8_lib.asm", "" %asminclude "library:prog8_funcs.asm", "" + uword @zp retval_interm_w ; to store intermediary expression results for return values (hopefully allocated on ZP to reduce code size) + ubyte @zp retval_interm_b ; to store intermediary expression results for return values (hopefully allocated on ZP to reduce code size) asmsub pattern_match(str string @AY, str pattern @R0) clobbers(Y) -> ubyte @A { %asm {{ diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 858043685..305ef6549 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -215,12 +215,12 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen // Everything else just evaluate via the stack. // (we can't use the assignment helper functions to do it via registers here, // because the code here is the implementation of exactly that...) - if(value.parent is Return) { + if (value.parent is Return) { if (this.asmgen.options.slowCodegenWarnings) println("warning: slow stack evaluation used for return: $value target=${assign.target.kind} at ${value.position}") } - asmgen.translateExpression(value) - if(assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) + exprAsmgen.translateExpression(value) + if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) asmgen.signExtendStackLsb(assign.source.datatype) assignStackValue(assign.target) } diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index 8ffa815f7..a69f5d91a 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -441,6 +441,44 @@ internal class StatementOptimizer(private val program: Program, return noModifications } + override fun after(returnStmt: Return, parent: Node): Iterable { + fun returnViaIntermediary(value: Expression): Iterable? { + val returnDt = returnStmt.definingSubroutine()!!.returntypes.single() + if (returnDt in IntegerDatatypes) { + // first assign to intermediary, then return that register + val returnValueIntermediary = + if (returnDt in ByteDatatypes) + IdentifierReference(listOf("prog8_lib", "retval_interm_b"), returnStmt.position) + else + IdentifierReference(listOf("prog8_lib", "retval_interm_w"), returnStmt.position) + val tgt = AssignTarget(returnValueIntermediary, null, null, returnStmt.position) + val assign = Assignment(tgt, value, returnStmt.position) + val returnReplacement = Return(returnValueIntermediary, returnStmt.position) + return listOf( + IAstModification.InsertBefore(returnStmt, assign, parent as INameScope), + IAstModification.ReplaceNode(returnStmt, returnReplacement, parent) + ) + } + return null + } + + when(returnStmt.value) { + is PrefixExpression -> { + val mod = returnViaIntermediary(returnStmt.value!!) + if(mod!=null) + return mod + } + is BinaryExpression -> { + val mod = returnViaIntermediary(returnStmt.value!!) + if(mod!=null) + return mod + } + else -> {} + } + + return super.after(returnStmt, parent) + } + private fun hasBreak(scope: INameScope): Boolean { class Searcher: IAstVisitor diff --git a/examples/cx16/testgfx2.p8 b/examples/cx16/testgfx2.p8 index 3eab462c7..151d6c10b 100644 --- a/examples/cx16/testgfx2.p8 +++ b/examples/cx16/testgfx2.p8 @@ -125,14 +125,17 @@ main { xx+=4 } - cx16.wait(3*60) + cx16.wait(3*60) + + demo2() + gfx2.screen_mode(255) txt.print("done!\n") test_stack.test() } - sub start2 () { + sub demo2 () { gfx2.text_charset(3) ubyte[] modes = [1, 0, 128] @@ -143,9 +146,6 @@ main { cx16.wait(200) } - gfx2.screen_mode(255) - txt.print("done!\n") - test_stack.test() } sub draw() { diff --git a/examples/test.p8 b/examples/test.p8 index 4d2c20c37..80f79e9d9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,91 +1,36 @@ %import test_stack %import textio -%import diskio +%import floats %zeropage basicsafe %option no_sysinit main { sub start () { + uword uw + ubyte ub + float ff - uword large_buffer_ptr = progend() - ubyte[256] buffer - uword size - - if diskio.f_open(8, "rom.asm") { - txt.print("read-exact\n") - c64.SETTIM(0,0,0) - size = 0 - while not c64.READST() { - diskio.f_read_exact(&buffer, len(buffer)) - size += 256 - } - - diskio.f_close() - txt.print_uw(size) - txt.chrout('\n') - print_time() - txt.chrout('\n') - } else - txt.print("can't open file!\n") - txt.print(diskio.status(8)) - txt.chrout('\n') - - - if diskio.f_open(8, "rom.asm") { - txt.print("read-all\n") - c64.SETTIM(0,0,0) - size = 0 - size = diskio.f_read_all(large_buffer_ptr) - diskio.f_close() - txt.print_uw(size) - txt.chrout('\n') - print_time() - txt.chrout('\n') - } else - txt.print("can't open file!\n") - txt.print(diskio.status(8)) - txt.chrout('\n') - -; if diskio.f_open(8, "rom.asm") { -; txt.print("read\n") -; c64.SETTIM(0,0,0) -; size = 0 -; while not c64.READST() { -; size += diskio.f_read(&buffer, len(buffer)) -; } -; -; diskio.f_close() -; txt.print_uw(size) -; txt.chrout('\n') -; print_time() -; txt.chrout('\n') -; } - - test_stack.test() - + uw = funcuw() + ub = funcub() + ff = funcff() } + sub funcuw() -> uword { + uword a=1111 + uword b=2222 + return a+b + } - sub print_time() { - ubyte time_lo - ubyte time_mid - ubyte time_hi + sub funcub() -> ubyte { + ubyte a=11 + ubyte b=22 + return a+b + } - %asm {{ - stx P8ZP_SCRATCH_REG - jsr c64.RDTIM ; A/X/Y - sta time_lo - stx time_mid - sty time_hi - ldx P8ZP_SCRATCH_REG - }} - - txt.print_ub(time_hi) - txt.chrout(':') - txt.print_ub(time_mid) - txt.chrout(':') - txt.print_ub(time_lo) - txt.chrout('\n') + sub funcff() -> float { + float a=1111.1 + float b=2222.2 + return a+b } }