mirror of
https://github.com/irmen/prog8.git
synced 2025-01-23 15:30:10 +00:00
comments
This commit is contained in:
parent
a52699717c
commit
d8d56b195f
@ -235,7 +235,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// TODO OTHER EVALUATION HERE, don't use the estack to transfer the address to read/write from
|
||||
// TODO use some other evaluation here; don't use the estack to transfer the address to read/write from
|
||||
asmgen.assignExpressionTo(memory.addressExpression, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, DataType.UWORD, memory.definingSubroutine))
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
|
||||
when {
|
||||
@ -2081,7 +2081,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta ${target.asmVarname}+1
|
||||
""")
|
||||
}
|
||||
TargetStorageKind.STACK -> TODO("no asm gen for stack float negate")
|
||||
TargetStorageKind.STACK -> TODO("no asm gen for float stack negate")
|
||||
else -> throw AssemblyError("weird target kind for inplace negate float ${target.kind}")
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,6 @@ X = BinExpr X = LeftExpr
|
||||
// )
|
||||
}
|
||||
|
||||
// TODO breaks imageviewer EHB palette
|
||||
if(binExpr.right.isSimple) {
|
||||
val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position)
|
||||
val targetExpr = assignment.target.toExpression()
|
||||
|
@ -198,6 +198,22 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
||||
val leftBinExpr = expr.left as? BinaryExpression
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
if(expr.operator=="+" || expr.operator=="-") {
|
||||
|
||||
if(leftBinExpr!=null && rightconst!=null) {
|
||||
if(leftBinExpr.operator=="+") {
|
||||
val c2 = leftBinExpr.right.constValue(program)
|
||||
if(c2!=null) {
|
||||
// (X + C2) +/- rightConst --> X + (C2 +/- rightConst)
|
||||
// TODO SAME FOR (X - C1) +/- C2 --> X - (C1+C2) mind the operator flip?
|
||||
// TODO SAME FOR (X * C1) * C2 --> X * (C1*C2)
|
||||
// TODO SAME FOR (X / C1) / C2 --> X / (C1*C2)
|
||||
val constants = BinaryExpression(c2, expr.operator, rightconst, c2.position)
|
||||
val newExpr = BinaryExpression(leftBinExpr.left, "+", constants, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(leftBinExpr!=null && rightBinExpr!=null) {
|
||||
val c1 = leftBinExpr.right.constValue(program)
|
||||
val c2 = rightBinExpr.right.constValue(program)
|
||||
@ -378,7 +394,7 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
||||
{
|
||||
// NOTE: THIS IS ONLY VALID ON FLOATING POINT CONSTANTS
|
||||
|
||||
// todo: this implements only a small set of possible reorderings at this time
|
||||
// todo: this implements only a small set of possible reorderings at this time, we could think of more
|
||||
if(expr.operator==subExpr.operator) {
|
||||
// both operators are the same.
|
||||
|
||||
|
@ -71,7 +71,7 @@ fun Program.splitBinaryExpressions(options: CompilationOptions, compTarget: ICom
|
||||
|
||||
fun getTempVarName(dt: InferredTypes.InferredType): List<String> {
|
||||
return when {
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else...
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else during the use of this temporary variable...
|
||||
dt.istype(DataType.UBYTE) -> listOf("cx16", "r9L")
|
||||
dt.istype(DataType.BYTE) -> listOf("cx16", "r9sL")
|
||||
dt.istype(DataType.UWORD) -> listOf("cx16", "r9")
|
||||
|
@ -312,7 +312,8 @@ romsub $ff56 = joystick_get(ubyte joynr @A) -> ubyte @A, ubyte @X, ubyte @Y
|
||||
romsub $ff4d = clock_set_date_time(uword yearmonth @R0, uword dayhours @R1, uword minsecs @R2, ubyte jiffies @R3) clobbers(A, X, Y)
|
||||
romsub $ff50 = clock_get_date_time() clobbers(A, X, Y) -> uword @R0, uword @R1, uword @R2, ubyte @R3 ; result registers see clock_set_date_time()
|
||||
|
||||
; TODO specify the correct clobbers for all functions below, we now assume all 3 regs are clobbered
|
||||
|
||||
; It's not documented what registers are clobbered, so we assume the worst for all following kernal routines...:
|
||||
|
||||
; high level graphics & fonts
|
||||
romsub $ff20 = GRAPH_init(uword vectors @R0) clobbers(A,X,Y)
|
||||
|
@ -229,8 +229,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
|
||||
|
||||
// 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)
|
||||
// TODO: do NOT move this to an earler ast transform phase (such as StatementReorderer or StatementOptimizer)
|
||||
// it WILL result in larger code.
|
||||
// TODO: do NOT move this to an earler ast transform phase (such as StatementReorderer or StatementOptimizer) - it WILL result in larger code.
|
||||
// TODO: this should be replaced by a general expression-evaluation optimization step.
|
||||
// the actual conditional expression in the statement should be no more than VARIABLE <COMPARISON-OPERATOR> SIMPLE-EXPRESSION
|
||||
|
||||
|
@ -106,6 +106,57 @@ class TestOptimization: FunSpec({
|
||||
constvalue.parent shouldBeSameInstanceAs pfx.parent
|
||||
}
|
||||
|
||||
test("const folding multiple scenarios +/-") {
|
||||
val source = """
|
||||
main {
|
||||
const ubyte boardHeightC = 20
|
||||
const ubyte boardOffsetC = 3
|
||||
|
||||
sub start() {
|
||||
uword load_location = 12345
|
||||
cx16.r0 = load_location + 8000 + 1000 + 1000
|
||||
cx16.r1L = @(load_location + 8000 + 1000 + 1000)
|
||||
cx16.r2 = 8000 + 1000 + 1000 + load_location
|
||||
cx16.r3L = @(8000 + 1000 + 1000 + load_location)
|
||||
cx16.r4 = load_location + boardOffsetC + boardHeightC - 1
|
||||
}
|
||||
}"""
|
||||
val result = compileText(C64Target, true, source, writeAssembly = false).assertSuccess()
|
||||
// expected:
|
||||
// uword load_location
|
||||
// load_location = 12345
|
||||
// cx16.r0 = load_location
|
||||
// cx16.r0 += 10000
|
||||
// cx16.r1L = @((load_location+10000))
|
||||
// cx16.r2 = load_location
|
||||
// cx16.r2 += 10000
|
||||
// cx16.r3L = @((load_location+10000))
|
||||
// cx16.r4 = load_location
|
||||
// cx16.r4 += 22
|
||||
val stmts = result.program.entrypoint.statements
|
||||
stmts.size shouldBe 10
|
||||
|
||||
val addR0value = (stmts[3] as Assignment).value
|
||||
val binexpr0 = addR0value as BinaryExpression
|
||||
binexpr0.right shouldBe NumericLiteralValue(DataType.UWORD, 10000.0, Position.DUMMY)
|
||||
val valueR1L = (stmts[4] as Assignment).value
|
||||
val addrExpr1 = ((valueR1L as DirectMemoryRead).addressExpression as BinaryExpression)
|
||||
addrExpr1.left shouldBe IdentifierReference(listOf("load_location"), Position.DUMMY)
|
||||
addrExpr1.right shouldBe NumericLiteralValue(DataType.UWORD, 10000.0, Position.DUMMY)
|
||||
|
||||
val addR2value = (stmts[6] as Assignment).value
|
||||
var binexpr2 = addR2value as BinaryExpression
|
||||
binexpr2.right shouldBe NumericLiteralValue(DataType.UWORD, 10000.0, Position.DUMMY)
|
||||
val valueR3L = (stmts[7] as Assignment).value
|
||||
val addrExpr3 = ((valueR3L as DirectMemoryRead).addressExpression as BinaryExpression)
|
||||
addrExpr3.left shouldBe IdentifierReference(listOf("load_location"), Position.DUMMY)
|
||||
addrExpr3.right shouldBe NumericLiteralValue(DataType.UWORD, 10000.0, Position.DUMMY)
|
||||
|
||||
val addR4value = (stmts[9] as Assignment).value
|
||||
val binexpr4 = addR4value as BinaryExpression
|
||||
binexpr4.right shouldBe NumericLiteralValue(DataType.UWORD, 22.0, Position.DUMMY)
|
||||
}
|
||||
|
||||
test("constantfolded and silently typecasted for initializervalues") {
|
||||
val sourcecode = """
|
||||
main {
|
||||
|
@ -3,6 +3,8 @@ TODO
|
||||
|
||||
For next compiler release (7.5)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
more const-foldings
|
||||
check correctness of inplaceModification_byte_value_to_pointer()
|
||||
...
|
||||
|
||||
|
||||
@ -41,6 +43,8 @@ More code optimization ideas
|
||||
by rewriting while and until expressions into if+jump (just consider them syntactic sugar)
|
||||
but the result should not produce larger code ofcourse!
|
||||
- while-expression should now also get the simplifyConditionalExpression() treatment
|
||||
- byte typed expressions should be evaluated in the accumulator where possible, without (temp)var
|
||||
for instance value = otherbyte >> 1 --> lda otherbite ; lsr a; sta value
|
||||
- rewrite expression tree evaluation such that it doesn't use an eval stack but flatten the tree into linear code that uses a fixed number of predetermined value 'variables'
|
||||
- this removes the need for the BinExprSplitter? (which is problematic and very limited now)
|
||||
- introduce byte-index operator to avoid index multiplications in loops over arrays? see github issue #4
|
||||
|
@ -3,10 +3,11 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
str name = "irmen"
|
||||
txt.print(name)
|
||||
}
|
||||
|
||||
sub func(uword[22] thing) {
|
||||
; TODO other variants of this const folding
|
||||
uword load_location = $6000
|
||||
cx16.r0 = load_location + 8000 + 1000 + 1000
|
||||
cx16.r1L = @(load_location + 8000 + 1000 + 1000)
|
||||
cx16.r2 = 8000 + 1000 + 1000 + load_location
|
||||
cx16.r3L = @(8000 + 1000 + 1000 + load_location)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user