improve const-evaluation of builtin expressions

This commit is contained in:
Irmen de Jong 2022-07-02 14:49:39 +02:00
parent b2c9b7635d
commit 25aad8d7be
6 changed files with 36 additions and 25 deletions

View File

@ -22,6 +22,9 @@ class BinExprSplitter(private val program: Program, private val options: Compila
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
if(options.compTarget.name == VMTarget.NAME)
return noModifications // don't split expressions when targeting the vm codegen, it handles nested expressions well
if(assignment.value.inferType(program) istype DataType.FLOAT && !options.optimizeFloatExpressions)
return noModifications

View File

@ -1,18 +1,15 @@
package prog8.optimizer
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.*
import prog8.ast.base.FatalAstException
import prog8.ast.base.UndefinedSymbolError
import prog8.ast.expressions.*
import prog8.ast.maySwapOperandOrder
import prog8.ast.statements.ForLoop
import prog8.ast.statements.VarDecl
import prog8.ast.statements.VarDeclType
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.AssociativeOperators
import prog8.code.core.DataType
import prog8.compiler.BuiltinFunctions
class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
@ -265,7 +262,6 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
}
override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
// the args of a fuction are constfolded via recursion already.
val constvalue = functionCallExpr.constValue(program)
return if(constvalue!=null)
listOf(IAstModification.ReplaceNode(functionCallExpr, constvalue, parent))
@ -273,6 +269,14 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
noModifications
}
override fun after(bfc: BuiltinFunctionCall, parent: Node): Iterable<IAstModification> {
val constvalue = bfc.constValue(program)
return if(constvalue!=null)
listOf(IAstModification.ReplaceNode(bfc, constvalue, parent))
else
noModifications
}
override fun after(forLoop: ForLoop, parent: Node): Iterable<IAstModification> {
fun adjustRangeDt(rangeFrom: NumericLiteral, targetDt: DataType, rangeTo: NumericLiteral, stepLiteral: NumericLiteral?, range: RangeExpression): RangeExpression? {
val fromCast = rangeFrom.cast(targetDt)

View File

@ -10,6 +10,7 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor
import prog8.code.core.*
import prog8.compiler.BuiltinFunctions
import java.util.*
import kotlin.math.abs
import kotlin.math.floor
@ -1142,7 +1143,13 @@ class BuiltinFunctionCall(override var target: IdentifierReference,
replacement.parent = this
}
override fun constValue(program: Program): NumericLiteral? = null
override fun constValue(program: Program): NumericLiteral? {
val function = BuiltinFunctions.getValue(name)
if(function.pure) {
return program.builtinFunctions.constValue(name, args, position)
}
return null
}
override fun toString() = "BuiltinFunctionCall(name=$name, pos=$position)"
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)

View File

@ -3,17 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- logical.p8 is huge compared to 8.2
- compiling logical.p8 to virtual with optimization generates code that is smaller,
but takes many more vm instructions to execute than not-optimized code!?
- petaxian.prg became quite a bit (150 bytes) larger since 8.2, what causes that
- add some more optimizations in vmPeepholeOptimizer
- vm Instruction needs to know what the read-registers/memory are, and what the write-register/memory is.
this info is needed for more advanced optimizations and later code generation steps.
...
Need help with
^^^^^^^^^^^^^^
@ -25,7 +15,10 @@ Need help with
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
- add true 'bool' type that can only be 0 or 1, so that logical expressons don't have to use boolean() all the time on their operands
- add some more optimizations in vmPeepholeOptimizer
- vm Instruction needs to know what the read-registers/memory are, and what the write-register/memory is.
this info is needed for more advanced optimizations and later code generation steps.
- vm: implement remaining sin/cos functions in math.p8
- vm: somehow deal with asmsubs otherwise the vm IR can't fully encode all of prog8
- vm: don't store symbol names in instructions to make optimizing the IR easier? but what about jumps to labels. And it's no longer readable by humans.

View File

@ -45,7 +45,7 @@ zsound_lib:
const ubyte song_bank = 1
const uword song_address = $a000
const ubyte digi_bank = 5
const ubyte digi_bank = 6
const uword digi_address = $a000
const ubyte zcm_DIGITAB_size = 8 ; header size
@ -82,8 +82,6 @@ zsound_lib:
txt.print_uw(zsm_get_music_speed())
txt.print(" hz\nplaying song! hit enter to also play a digi sample!\n")
; for IRQ based playback instead: cx16.set_irq(&zsm_playIRQ, true)
repeat {
if cx16.joystick_get2(0)!=$ffff
pcm_trigger_digi(digi_bank, digi_address)

View File

@ -3,6 +3,12 @@
%import cx16diskio
%zpreserved $22,$2d ; zsound lib uses this region
; NOTE: this is a proof of concept to stream ZCM digi from disk while playing.
; currently there's no real streaming API / circular buffer in zsound,
; so it simply loads the whole ZCM file in chunks in memory sequentially.
; But it does so while the playback is going on in the background.
; It seems fast enough to stream + play 16khz 16bit stereo samples. (around 64 Kb/sec)
; Maybe we can go faster but 22 Khz seemed too much to keep up with.
main $0830 {
@ -54,7 +60,7 @@ zsound_lib:
pcm_init()
pcm_trigger_digi(digi_bank, digi_address)
cx16.set_irq(&zsm_playroutine, true)
cx16.set_irq(&zsm_playroutine_irq, true)
txt.print("\nstreaming from file, playback in irq!\n")
uword size = 1
@ -73,7 +79,7 @@ zsound_lib:
pcm_stop() ;unreached
}
sub zsm_playroutine() {
sub zsm_playroutine_irq() {
pcm_play()
}
}