fix referencesIdentifier() and better removal of unnecessary assignments

This commit is contained in:
Irmen de Jong 2021-11-20 17:33:02 +01:00
parent f9399bcce7
commit 74db5c6be7
12 changed files with 243 additions and 120 deletions

View File

@ -111,7 +111,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> {
// the initializer value can't refer to the variable itself (recursive definition)
// TODO: use call graph for this?
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true) {
if(decl.value?.referencesIdentifier(listOf(decl.name)) == true || decl.arraysize?.indexExpr?.referencesIdentifier(listOf(decl.name)) == true) {
errors.err("recursive var declaration", decl.position)
return noModifications
}

View File

@ -1,11 +1,9 @@
package prog8.optimizer
import prog8.ast.*
import prog8.ast.base.DataType
import prog8.ast.base.VarDeclType
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.FunctionCall
import prog8.ast.expressions.PrefixExpression
import prog8.ast.expressions.TypecastExpression
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
@ -58,8 +56,7 @@ class UnusedCodeRemover(private val program: Program,
}
override fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> {
val removeDoubleAssignments = deduplicateAssignments(scope.statements)
return removeDoubleAssignments.map { IAstModification.Remove(it, scope) }
return deduplicateAssignments(scope.statements, scope)
}
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
@ -75,8 +72,7 @@ class UnusedCodeRemover(private val program: Program,
}
}
val removeDoubleAssignments = deduplicateAssignments(block.statements)
return removeDoubleAssignments.map { IAstModification.Remove(it, block) }
return deduplicateAssignments(block.statements, block)
}
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
@ -99,8 +95,7 @@ class UnusedCodeRemover(private val program: Program,
}
}
val removeDoubleAssignments = deduplicateAssignments(subroutine.statements)
return removeDoubleAssignments.map { IAstModification.Remove(it, subroutine) }
return deduplicateAssignments(subroutine.statements, subroutine)
}
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
@ -135,28 +130,117 @@ class UnusedCodeRemover(private val program: Program,
return noModifications
}
private fun deduplicateAssignments(statements: List<Statement>): List<Assignment> {
private fun deduplicateAssignments(statements: List<Statement>, scope: IStatementContainer): List<IAstModification> {
// removes 'duplicate' assignments that assign the same target directly after another
val linesToRemove = mutableListOf<Assignment>()
val modifications = mutableListOf<IAstModification>()
for (stmtPairs in statements.windowed(2, step = 1)) {
val assign1 = stmtPairs[0] as? Assignment
val assign2 = stmtPairs[1] as? Assignment
if (assign1 != null && assign2 != null && !assign2.isAugmentable) {
if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) {
if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(*(assign2.target.identifier!!.nameInSource.toTypedArray())))
// only remove the second assignment if its value is a simple expression!
when(assign2.value) {
is PrefixExpression,
is BinaryExpression,
is TypecastExpression,
is FunctionCall -> { /* don't remove */ }
else -> linesToRemove.add(assign1)
}
fun substituteZeroInBinexpr(expr: BinaryExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) {
if(expr.left isSameAs assign2.target) {
// X = X <oper> Right
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
expr.left, zero, expr
))
}
if(expr.right isSameAs assign2.target) {
// X = Left <oper> X
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
expr.right, zero, expr
))
}
val leftBinExpr = expr.left as? BinaryExpression
val rightBinExpr = expr.right as? BinaryExpression
if(leftBinExpr!=null && rightBinExpr==null) {
if(leftBinExpr.left isSameAs assign2.target) {
// X = (X <oper> Right) <oper> Something
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
leftBinExpr.left, zero, leftBinExpr
))
}
if(leftBinExpr.right isSameAs assign2.target) {
// X = (Left <oper> X) <oper> Something
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
leftBinExpr.right, zero, leftBinExpr
))
}
}
if(leftBinExpr==null && rightBinExpr!=null) {
if(rightBinExpr.left isSameAs assign2.target) {
// X = Something <oper> (X <oper> Right)
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
rightBinExpr.left, zero, rightBinExpr
))
}
if(rightBinExpr.right isSameAs assign2.target) {
// X = Something <oper> (Left <oper> X)
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
rightBinExpr.right, zero, rightBinExpr
))
}
}
}
return linesToRemove
fun substituteZeroInPrefixexpr(expr: PrefixExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) {
if(expr.expression isSameAs assign2.target) {
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
expr.expression, zero, expr
))
}
}
fun substituteZeroInTypecast(expr: TypecastExpression, zero: NumericLiteralValue, assign1: Assignment, assign2: Assignment) {
if(expr.expression isSameAs assign2.target) {
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
expr.expression, zero, expr
))
}
val subCast = expr.expression as? TypecastExpression
if(subCast!=null && subCast.expression isSameAs assign2.target) {
linesToRemove.add(assign1)
modifications.add(IAstModification.ReplaceNode(
subCast.expression, zero, subCast
))
}
}
for (stmtPairs in statements.windowed(2, step = 1)) {
val assign1 = stmtPairs[0] as? Assignment
val assign2 = stmtPairs[1] as? Assignment
if (assign1 != null && assign2 != null) {
val cvalue1 = assign1.value.constValue(program)
if(cvalue1!=null && cvalue1.number==0.0 && assign2.isAugmentable) {
val value2 = assign2.value
val zero = VarDecl.defaultZero(value2.inferType(program).getOr(DataType.UNDEFINED), value2.position)
when(value2) {
is BinaryExpression -> substituteZeroInBinexpr(value2, zero, assign1, assign2)
is PrefixExpression -> substituteZeroInPrefixexpr(value2, zero, assign1, assign2)
is TypecastExpression -> substituteZeroInTypecast(value2, zero, assign1, assign2)
else -> {}
}
} else {
if (assign1.target.isSameAs(assign2.target, program) && !assign1.target.isIOAddress(compTarget.machine)) {
if(assign2.target.identifier==null || !assign2.value.referencesIdentifier(assign2.target.identifier!!.nameInSource))
// only remove the second assignment if its value is a simple expression!
when(assign2.value) {
is PrefixExpression,
is BinaryExpression,
is TypecastExpression,
is FunctionCall -> { /* don't remove */ }
else -> linesToRemove.add(assign1)
}
}
}
}
}
return modifications + linesToRemove.map { IAstModification.Remove(it, scope) }
}
}

View File

@ -40,7 +40,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
if (binExpr != null && binExpr.operator !in comparisonOperators) {
if (binExpr.left !is BinaryExpression) {
if (binExpr.right.referencesIdentifier(*assignment.target.identifier!!.nameInSource.toTypedArray())) {
if (binExpr.right.referencesIdentifier(assignment.target.identifier!!.nameInSource)) {
// the right part of the expression contains the target variable itself.
// we can't 'split' it trivially because the variable will be changed halfway through.
if(binExpr.operator in associativeOperators) {

View File

@ -351,7 +351,7 @@ private fun writeAssembly(program: Program,
}
}
fun printAst(program: Program) {
fun printProgram(program: Program) {
println()
val printer = AstToSourceTextConverter(::print, program)
printer.visit(program)

View File

@ -508,7 +508,7 @@ internal class AstChecker(private val program: Program,
fun err(msg: String) = errors.err(msg, decl.position)
// the initializer value can't refer to the variable itself (recursive definition)
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true)
if(decl.value?.referencesIdentifier(listOf(decl.name)) == true || decl.arraysize?.indexExpr?.referencesIdentifier(listOf(decl.name)) == true)
err("recursive var declaration")
// CONST can only occur on simple types (byte, word, float)

View File

@ -97,21 +97,8 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter)
val nextAssign = assignment.nextSibling() as? Assignment
if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) {
// TODO hmm, if both assignments assign to the same thing, can't we just remove the first altogether??? as long as there isn't a function call in the value!
if(nextAssign.value isSameAs assignment.value)
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
if((assignment.value as? NumericLiteralValue)?.number==0.0 && nextAssign.isAugmentable) {
val value = nextAssign.value as BinaryExpression
if(value.left isSameAs assignment.target) {
val assign = Assignment(assignment.target, value.right, nextAssign.position)
return listOf(
IAstModification.Remove(assignment, parent as IStatementContainer),
IAstModification.ReplaceNode(nextAssign, assign, parent)
)
}
}
}
return noModifications

View File

@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.PrefixExpression
import prog8.ast.statements.*
import prog8.compiler.printAst
import prog8.compiler.printProgram
import prog8.compiler.target.C64Target
import prog8.compilerinterface.isIOAddress
import prog8.parser.SourceCode
@ -144,7 +144,7 @@ class TestMemory: FunSpec({
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
assign = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
wrapWithProgram(listOf(assign))
printAst(target.definingModule.program)
printProgram(target.definingModule.program)
target.isIOAddress(C64Target.machine) shouldBe true
}

View File

@ -15,6 +15,7 @@ import prog8.ast.base.Position
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.compiler.BeforeAsmGenerationAstChanger
import prog8.compiler.printProgram
import prog8.compiler.target.C64Target
import prog8.compilerinterface.*
import prog8tests.helpers.*
@ -344,9 +345,15 @@ class TestOptimization: FunSpec({
ubyte @shared z1
z1 = 10
ubyte @shared z2
z2 = z1+z2+5
z2 = ~z2
ubyte @shared z3
z3 = z1+z3-5
z3 = not z3
uword @shared z4
z4 = (z4 as ubyte)
ubyte @shared z5
z5 = z1+z5+5
ubyte @shared z6
z6 = z1+z6-5
}
}"""
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
@ -354,35 +361,53 @@ class TestOptimization: FunSpec({
ubyte z1
z1 = 10
ubyte z2
z2 = z1
z2 += 5
z2 = 255
ubyte z3
z3 = z1
z3 -= 5
*/
z3 = 1
uword z4
z4 = 0
ubyte z5
z5 = z1
z5 += 5
ubyte z6
z6 = z1
z6 -= 5
*/
val statements = result.program.entrypoint.statements
statements.size shouldBe 8
statements.size shouldBe 14
val z1decl = statements[0] as VarDecl
val z1init = statements[1] as Assignment
val z2decl = statements[2] as VarDecl
val z2init = statements[3] as Assignment
val z2plus = statements[4] as Assignment
val z3decl = statements[5] as VarDecl
val z3init = statements[6] as Assignment
val z3plus = statements[7] as Assignment
val z3decl = statements[4] as VarDecl
val z3init = statements[5] as Assignment
val z4decl = statements[6] as VarDecl
val z4init = statements[7] as Assignment
val z5decl = statements[8] as VarDecl
val z5init = statements[9] as Assignment
val z5plus = statements[10] as Assignment
val z6decl = statements[11] as VarDecl
val z6init = statements[12] as Assignment
val z6plus = statements[13] as Assignment
z1decl.name shouldBe "z1"
z1init.value shouldBe NumericLiteralValue(DataType.UBYTE, 10.0, Position.DUMMY)
z2decl.name shouldBe "z2"
z2init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
z2plus.isAugmentable shouldBe true
(z2plus.value as BinaryExpression).operator shouldBe "+"
(z2plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
z2init.value shouldBe NumericLiteralValue(DataType.UBYTE, 255.0, Position.DUMMY)
z3decl.name shouldBe "z3"
z3init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
z3plus.isAugmentable shouldBe true
(z3plus.value as BinaryExpression).operator shouldBe "-"
(z3plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
z3init.value shouldBe NumericLiteralValue(DataType.UBYTE, 1.0, Position.DUMMY)
z4decl.name shouldBe "z4"
z4init.value shouldBe NumericLiteralValue(DataType.UBYTE, 0.0, Position.DUMMY)
z5decl.name shouldBe "z5"
z5init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
z5plus.isAugmentable shouldBe true
(z5plus.value as BinaryExpression).operator shouldBe "+"
(z5plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
z6decl.name shouldBe "z6"
z6init.value shouldBe IdentifierReference(listOf("z1"), Position.DUMMY)
z6plus.isAugmentable shouldBe true
(z6plus.value as BinaryExpression).operator shouldBe "-"
(z6plus.value as BinaryExpression).right shouldBe NumericLiteralValue(DataType.UBYTE, 5.0, Position.DUMMY)
}
test("force_output option should work with optimizing memwrite assignment") {
@ -472,4 +497,35 @@ class TestOptimization: FunSpec({
val result = compileText(C64Target, optimize=false, src, writeAssembly=true).assertSuccess()
result.program.entrypoint.statements.size shouldBe 10
}
test("keep the value initializer assignment if the next one depends on it") {
val src="""
main {
sub start() {
uword @shared yy
yy = 20 ; ok to remove =0 initializer before this
uword @shared zz
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
ubyte @shared xx
xx = 6+sin8u(xx) ; NOT ok to remove initializer
}
}
"""
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
printProgram(result.program)
/* expected result:
uword yy
yy = 20
uword zz
zz = 60
ubyte xx
xx = 0
xx = sin8u(xx)
xx += 6
*/
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 8
stmts.filterIsInstance<VarDecl>().size shouldBe 3
stmts.filterIsInstance<Assignment>().size shouldBe 5
}
})

View File

@ -9,7 +9,6 @@ import io.kotest.matchers.types.instanceOf
import prog8.ast.base.DataType
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.compiler.printAst
import prog8.compiler.target.C64Target
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertFailure

View File

@ -22,7 +22,7 @@ sealed class Expression: Node {
abstract fun constValue(program: Program): NumericLiteralValue?
abstract fun accept(visitor: IAstVisitor)
abstract fun accept(visitor: AstWalker, parent: Node)
abstract fun referencesIdentifier(vararg scopedName: String): Boolean
abstract fun referencesIdentifier(nameInSource: List<String>): Boolean
abstract fun inferType(program: Program): InferredTypes.InferredType
abstract val isSimple: Boolean
@ -123,7 +123,7 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String) = expression.referencesIdentifier(*scopedName)
override fun referencesIdentifier(nameInSource: List<String>) = expression.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val inferred = expression.inferType(program)
return when(operator) {
@ -183,7 +183,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String) = left.referencesIdentifier(*scopedName) || right.referencesIdentifier(*scopedName)
override fun referencesIdentifier(nameInSource: List<String>) = left.referencesIdentifier(nameInSource) || right.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val leftDt = left.inferType(program)
val rightDt = right.inferType(program)
@ -300,7 +300,7 @@ class ArrayIndexedExpression(var arrayvar: IdentifierReference,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String) = arrayvar.referencesIdentifier(*scopedName)
override fun referencesIdentifier(nameInSource: List<String>) = arrayvar.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val target = arrayvar.targetStatement(program)
@ -341,7 +341,7 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String) = expression.referencesIdentifier(*scopedName)
override fun referencesIdentifier(nameInSource: List<String>) = expression.referencesIdentifier(nameInSource)
override fun inferType(program: Program) = InferredTypes.knownFor(type)
override fun constValue(program: Program): NumericLiteralValue? {
val cv = expression.constValue(program) ?: return null
@ -378,7 +378,7 @@ data class AddressOf(var identifier: IdentifierReference, override val position:
override fun copy() = AddressOf(identifier.copy(), position)
override fun constValue(program: Program): NumericLiteralValue? = null
override fun referencesIdentifier(vararg scopedName: String) = false
override fun referencesIdentifier(nameInSource: List<String>) = identifier.nameInSource==nameInSource
override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UWORD)
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
@ -404,7 +404,7 @@ class DirectMemoryRead(var addressExpression: Expression, override val position:
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String) = false
override fun referencesIdentifier(nameInSource: List<String>) = addressExpression.referencesIdentifier(nameInSource)
override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UBYTE)
override fun constValue(program: Program): NumericLiteralValue? = null
@ -472,7 +472,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
throw FatalAstException("can't replace here")
}
override fun referencesIdentifier(vararg scopedName: String) = false
override fun referencesIdentifier(nameInSource: List<String>) = false
override fun constValue(program: Program) = this
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
@ -579,7 +579,7 @@ class CharLiteral(val value: Char,
}
override fun copy() = CharLiteral(value, altEncoding, position)
override fun referencesIdentifier(vararg scopedName: String) = false
override fun referencesIdentifier(nameInSource: List<String>) = false
override fun constValue(program: Program): NumericLiteralValue {
val bytevalue = program.encoding.encodeString(value.toString(), altEncoding).single()
return NumericLiteralValue(DataType.UBYTE, bytevalue.toDouble(), position)
@ -614,7 +614,7 @@ class StringLiteralValue(val value: String,
throw FatalAstException("can't replace here")
}
override fun referencesIdentifier(vararg scopedName: String) = false
override fun referencesIdentifier(nameInSource: List<String>) = false
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
@ -650,7 +650,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
replacement.parent = this
}
override fun referencesIdentifier(vararg scopedName: String) = value.any { it.referencesIdentifier(*scopedName) }
override fun referencesIdentifier(nameInSource: List<String>) = value.any { it.referencesIdentifier(nameInSource) }
override fun constValue(program: Program): NumericLiteralValue? = null
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
@ -757,7 +757,7 @@ class RangeExpr(var from: Expression,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String): Boolean = from.referencesIdentifier(*scopedName) || to.referencesIdentifier(*scopedName)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = from.referencesIdentifier(nameInSource) || to.referencesIdentifier(nameInSource)
override fun inferType(program: Program): InferredTypes.InferredType {
val fromDt=from.inferType(program)
val toDt=to.inferType(program)
@ -829,8 +829,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String): Boolean =
nameInSource.size==scopedName.size && nameInSource.toTypedArray().contentEquals(scopedName)
override fun referencesIdentifier(nameInSource: List<String>): Boolean = this.nameInSource==nameInSource
override fun inferType(program: Program): InferredTypes.InferredType {
return when (val targetStmt = targetStatement(program)) {
@ -899,7 +898,7 @@ class FunctionCall(override var target: IdentifierReference,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
override fun referencesIdentifier(vararg scopedName: String): Boolean = target.referencesIdentifier(*scopedName) || args.any{it.referencesIdentifier(*scopedName)}
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource) || args.any{it.referencesIdentifier(nameInSource)}
override fun inferType(program: Program): InferredTypes.InferredType {
val constVal = constValue(program ,false)

View File

@ -5,8 +5,6 @@ For next compiler release (7.4)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fix "test augmented expression asmgen" unittest (and textelite compilation)
TODO certain typecast expressions are also augmentable?? what does this even mean, and does the generated code make a difference???
optimize TODO in "Add assignment to initialize with zero" in StatementReorderer
optimize TODO in after(assignment) in VariousCleanups
optimize: add some more constant folders mentioned in test.p8

View File

@ -11,42 +11,42 @@ main {
byte bb
float fl
; TODO add these constant folders:
; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2)
; (X + C1) - (Y + C2) => (X - Y) + (C1 - C2)
; ---> together: (X + C1) <plusmin> (Y + C2) => (X <plusmin> Y) + (C1 <plusmin> C2)
; (X - C1) + (Y - C2) => (X + Y) - (C1 + C2)
; (X - C1) - (Y - C2) => (X - Y) - (C1 - C2)
xx=6
yy=8
yy = (xx+5)+(yy+10)
txt.print_ub(yy) ; 29
txt.nl()
xx=100
yy=8
yy = (xx+5)-(yy+10)
txt.print_ub(yy) ; 87
txt.nl()
xx=50
yy=40
yy = (xx-5)+(yy-10)
txt.print_ub(yy) ; 75
txt.nl()
xx=50
yy=20
yy = (xx-5)-(yy-10)
txt.print_ub(yy) ; 35
txt.nl()
repeat {
}
;; TODO add these constant folders:
;
;; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2)
;; (X + C1) - (Y + C2) => (X - Y) + (C1 - C2)
;; ---> together: (X + C1) <plusmin> (Y + C2) => (X <plusmin> Y) + (C1 <plusmin> C2)
;
;
;; (X - C1) + (Y - C2) => (X + Y) - (C1 + C2)
;; (X - C1) - (Y - C2) => (X - Y) - (C1 - C2)
;
; xx=6
; yy=8
;
; yy = (xx+5)+(yy+10)
; txt.print_ub(yy) ; 29
; txt.nl()
;
; xx=100
; yy=8
; yy = (xx+5)-(yy+10)
; txt.print_ub(yy) ; 87
; txt.nl()
;
; xx=50
; yy=40
; yy = (xx-5)+(yy-10)
; txt.print_ub(yy) ; 75
; txt.nl()
;
; xx=50
; yy=20
; yy = (xx-5)-(yy-10)
; txt.print_ub(yy) ; 35
; txt.nl()
;
; repeat {
; }
}
}