From 74456d11355167d7e004eb4b6e559425fae4f64f Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 6 Nov 2021 17:57:00 +0100 Subject: [PATCH] optimized prefix-expression in to use stack evaluation less --- .../codegen/assignment/AssignmentAsmGen.kt | 31 +++++---- .../assignment/AugmentableAssignmentAsmGen.kt | 64 ++++++++++++++++++- docs/source/todo.rst | 1 + 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index b0956ba83..a25b366de 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -254,22 +254,21 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } } -// TODO OPTIMIZE PREFIX EXPRESSION: -// is PrefixExpression -> { -// // first assign the value to the target then apply the operator in place on the target. -// translateNormalAssignment(AsmAssignment( -// AsmAssignSource.fromAstSource(value.expression, program, asmgen), -// assign.target, -// false, program.memsizer, assign.position -// )) -// when(value.operator) { -// "+" -> {} -// "-" -> augmentableAsmGen.inplaceNegate(assign.target, assign.target.datatype) -// "~" -> augmentableAsmGen.inplaceInvert(assign.target, assign.target.datatype) -// "not" -> augmentableAsmGen.inplaceBooleanNot(assign.target, assign.target.datatype) -// else -> throw AssemblyError("invalid prefix operator") -// } -// } + is PrefixExpression -> { + // first assign the value to the target then apply the operator in place on the target. + translateNormalAssignment(AsmAssignment( + AsmAssignSource.fromAstSource(value.expression, program, asmgen), + assign.target, + false, program.memsizer, assign.position + )) + when(value.operator) { + "+" -> {} + "-" -> augmentableAsmGen.inplaceNegate(assign.target, assign.target.datatype) + "~" -> augmentableAsmGen.inplaceInvert(assign.target, assign.target.datatype) + "not" -> augmentableAsmGen.inplaceBooleanNot(assign.target, assign.target.datatype) + else -> throw AssemblyError("invalid prefix operator") + } + } else -> { // Everything else just evaluate via the stack. // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index ab8e5718d..c1c2d54be 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -1768,7 +1768,28 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } } - TargetStorageKind.REGISTER -> TODO("missing codegen for byte reg not") + TargetStorageKind.REGISTER -> { + when(target.register!!) { + RegisterOrPair.A -> asmgen.out(""" + cmp #0 + beq + + lda #1 + + eor #1""") + RegisterOrPair.X -> asmgen.out(""" + txa + beq + + lda #1 + + eor #1 + tax""") + RegisterOrPair.Y -> asmgen.out(""" + tya + beq + + lda #1 + + eor #1 + tay""") + else -> throw AssemblyError("invalid reg dt for byte not") + } + } TargetStorageKind.STACK -> TODO("missing codegen for byte stack not") else -> throw AssemblyError("missing codegen for in-place not of ubyte ${target.kind}") } @@ -1786,8 +1807,47 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lsr a sta ${target.asmVarname}+1""") } + TargetStorageKind.REGISTER -> { + when(target.register!!) { + RegisterOrPair.AX -> { + asmgen.out(""" + stx P8ZP_SCRATCH_REG + ora P8ZP_SCRATCH_REG + beq + + lda #0 + tax + beq ++ + + lda #1 + +""") + } + RegisterOrPair.AY -> { + asmgen.out(""" + sty P8ZP_SCRATCH_REG + ora P8ZP_SCRATCH_REG + beq + + lda #0 + tay + beq ++ + + lda #1 + +""") + } + RegisterOrPair.XY -> { + asmgen.out(""" + stx P8ZP_SCRATCH_REG + tya + ora P8ZP_SCRATCH_REG + beq + + ldy #0 + ldx #0 + beq ++ + + ldx #1 + +""") + } + in Cx16VirtualRegisters -> TODO() + else -> throw AssemblyError("invalid reg dt for word not") + } + } TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory not") - TargetStorageKind.REGISTER -> TODO("missing codegen for word reg not") TargetStorageKind.STACK -> TODO("missing codegen for word stack not") else -> throw AssemblyError("missing codegen for in-place not of uword for ${target.kind}") } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 36150f440..1cca5d9e4 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -7,6 +7,7 @@ For next compiler release (7.2) - [complicated?] find a way to optimize if-statement codegen so that "if var & %10000" doesn't use evalstack & subroutine call, but also that the simple case "if X {...}" remains fast - fix the asm-labels problem (github issue #62) - start migrating to KoTest library (github issue #70) +- optimize "if not x" / "while not x" to not actually calculate the whole "not x" value first --> transform in to "x==0" in these conditional statements? Blocked by Commander-x16 v39 release