optimize conditional expression WORD & $ff00 to just msb(WORD)&$ff

This commit is contained in:
Irmen de Jong 2022-08-11 23:43:05 +02:00
parent d6b8936376
commit 18790d867c
6 changed files with 46 additions and 13 deletions

View File

@ -360,6 +360,12 @@ internal class AssignmentAsmGen(private val program: Program,
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) {
if(expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes &&
expr.left.isSimple && expr.right.isSimple) {
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) {
// TODO("optimized code for logical with right number/variable arg (byte)")
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) {
// TODO("optimized code for logical with left number/variable arg (byte)")
// }
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine)
@ -375,6 +381,11 @@ internal class AssignmentAsmGen(private val program: Program,
}
if(expr.left.inferType(program).isWords && expr.right.inferType(program).isWords &&
expr.left.isSimple && expr.right.isSimple) {
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) {
// TODO("optimized code for logical with right number/variable arg (word)")
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) {
// TODO("optimized code for logical with left number/variable arg (word)")
// }
assignExpressionToRegister(expr.left, RegisterOrPair.AY, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false)

View File

@ -10,13 +10,14 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.*
import prog8.code.target.VMTarget
import kotlin.math.abs
import kotlin.math.log2
import kotlin.math.pow
// TODO add more peephole expression optimizations? Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html
class ExpressionSimplifier(private val program: Program) : AstWalker() {
class ExpressionSimplifier(private val program: Program, private val compTarget: ICompilationTarget) : AstWalker() {
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
@ -71,6 +72,22 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
}
}
}
if(compTarget.name!=VMTarget.NAME) {
val booleanCondition = ifElse.condition as? BinaryExpression
if(booleanCondition!=null && booleanCondition.operator=="&") {
// special optimization of WORD & $ff00 -> just and the msb of WORD with $ff
val rightNum = booleanCondition.right as? NumericLiteral
if(rightNum!=null && rightNum.type==DataType.UWORD && (rightNum.number.toInt() and 0x00ff)==0) {
val msb = BuiltinFunctionCall(IdentifierReference(listOf("msb"), booleanCondition.left.position), mutableListOf(booleanCondition.left), booleanCondition.left.position)
val bytevalue = NumericLiteral(DataType.UBYTE, (rightNum.number.toInt() shr 8).toDouble(), booleanCondition.right.position)
return listOf(
IAstModification.ReplaceNode(booleanCondition.left, msb, booleanCondition),
IAstModification.ReplaceNode(booleanCondition.right, bytevalue, booleanCondition))
}
}
}
return noModifications
}

View File

@ -60,8 +60,8 @@ fun Program.inlineSubroutines(): Int {
return inliner.applyModifications()
}
fun Program.simplifyExpressions() : Int {
val opti = ExpressionSimplifier(this)
fun Program.simplifyExpressions(target: ICompilationTarget) : Int {
val opti = ExpressionSimplifier(this, target)
opti.visit(this)
return opti.applyModifications()
}

View File

@ -358,7 +358,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
remover.applyModifications()
while (true) {
// keep optimizing expressions and statements until no more steps remain
val optsDone1 = program.simplifyExpressions()
val optsDone1 = program.simplifyExpressions(compTarget)
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
val optsDone3 = program.optimizeStatements(errors, functions, compTarget)
val optsDone4 = program.inlineSubroutines()

View File

@ -3,6 +3,9 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- finish the logical expression optimizations set in TODO's in attemptAssignOptimizedBinexpr()
- try more benchmarks from https://gglabs.us/node/2293
...
@ -77,6 +80,7 @@ Optimizations:
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
- when a loopvariable of a forloop isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop
but we have no efficient way right now to see if the body references a variable.
- optimize function argument expressions better (use temporary variables to replace non-simple expressions?)
STRUCTS again?

View File

@ -3,16 +3,17 @@
main {
sub start() {
ubyte[] buffer = [$11,$22,$33,$44]
uword data = &buffer
uword crc = $ffff
crc ^= mkword(@(data), 0)
txt.print_uwhex(crc, true)
crc = $ffff
ubyte variable = @(data)
crc ^= mkword(variable, 0)
txt.print_uwhex(crc, true)
txt.print_uwhex(crc | (crc & $8000), true)
; if crc & $8000 ; msb(crc) & $80
; txt.print("yes")
; else
; txt.print("fail!")
;
; if msb(crc) & $80
; txt.print("yes")
; else
; txt.print("fail!")
}
; sub start2() {